我将尝试尽可能具体地解决我的问题。我的目标是实现两个套接字(客户端/服务器);客户端必须向服务器发送awk命令+一些输入行。服务器必须使用给定的输入执行awk命令,并将每行awk的stdout和awk的每一行stderr发送回客户端,并与字符串“ERRLINEi”(i =行号)连接。
我问过如何做到这一点,因为我完全迷失了,我得到了很好的建议,使用fork,execl,pipe和dup2。所以我试着把它写下来:
execl("/usr/bin/awk", "awk", command, (char *)0)
但这不起作用。请注意,此函数在while循环中调用,循环直到从客户端接收新输入行。我真的不明白为什么所以我在函数调用之前(在调用run_awk()的main函数中)放了一个printf指令,结果是run_awk()在同一个进程中被多次调用同一个输入。
注意:我的* out和* err参数应该用于存储awk的结果。因为我只是想看看我的程序在做什么,所以我没有使用它们。
更新 我理解了代码中的一些错误。我把分叉部分带回主要功能,但我仍然有问题。实际上,我需要做的是:从父到子发送一个命令(有感觉的awk语法)(我实现了这个)然后让孩子从stdin一个接一个地读取输入行(随机文本),允许execl像这样跑:
if((t_fd = accept(l_fd, (struct sockaddr *)NULL, NULL)) < 0) sockerror(2, 0); //accept connection from client
recv(t_fd, &com_len, sizeof(int), 0); //receive command length
command = malloc(com_len+1);
rbytes = recv(t_fd, command, com_len, 0); //receive command
command[rbytes] = '\0';
printf("Received command: %s\n", command);
if((pipe(in_pipe)+pipe(out_pipe)+pipe(err_pipe)) < 0) syscallerror("pipe"); //init pipes
bool check = true;
while(recv(t_fd, &inp_len, sizeof(int), 0) > 0){ //receive single input line length - loop while there are lines to read
memset(input, 0, inp_len+1);
recv(t_fd, input, inp_len, 0); //receive input line
if((p = fork()) < 0) syscallerror("fork");
if(p > 0){
close(in_pipe[0]); // Close reading end of first pipe
if(check){ //this makes the server write the command in the pipe just once
write(in_pipe[1], command, strlen(command));
check = false;
}
write(in_pipe[1], input, strlen(input)); //write the input line
//close(in_pipe[1]); //I can't close it because other lines will be sent in the loop
close(out_pipe[1]);
close(err_pipe[1]);
int n = read(out_pipe[0], out, 300); //read should block until child has produced output (you can assume it will always produce it)
int k = read(err_pipe[0], err, 300);
if(n > 0) printf("parent %d: received output %s\n", getpid(), out);
if(k > 0) printf("parent %d: received error %s\n", getpid(), err);
close(out_pipe[0]);
close(err_pipe[0]);
memset(out, 0, 301);
memset(err, 0, 301);
}
else{
close(in_pipe[1]); // Close writing end of first pipe
char com[300]; // Read command using first pipe
read(in_pipe[0], com, 300);
// Close all reading ends
close(out_pipe[0]);
close(err_pipe[0]);
dup2(in_pipe[0], 0); //set correct file descriptors
dup2(out_pipe[1], 1);
dup2(err_pipe[1], 2);
close(in_pipe[0]);
close(err_pipe[1]);
close(out_pipe[1]);
if(execl("/usr/bin/awk", "awk", com, (char *)0) < 0) syscallerror("execl");
exit(0);
}
}
close(in_pipe[1]);
kill(p, SIGKILL);
我的新代码是:
<ContentPage.Content>
<ScrollView>
<StackLayout
Padding="{Binding MainStackSidePadding}"
Spacing="15">
<RelativeLayout
Padding="{Binding MainStackSidePadding}"
BackgroundColor="Red">
<Image x:Name="logo" Source="testbar.png" HorizontalOptions="Center" HeightRequest="{Binding LogoSmallHeight}"
RelativeLayout.XConstraint =
"{ConstraintExpression Type=RelativeToParent,
Property=Width,
Factor=0.5,
Constant=0}"
RelativeLayout.YConstraint =
"{ConstraintExpression Type=RelativeToParent,
Property=Height,
Factor=0,
Constant=0}"/>
<Image x:Name="backButton" Source="back.png" HeightRequest="30"
RelativeLayout.XConstraint =
"{ConstraintExpression Type=RelativeToParent,
Property=Width,
Factor=0.025,
Constant=0}"
RelativeLayout.YConstraint =
"{ConstraintExpression Type=RelativeToView,
ElementName = logo,
Property=Height,
Factor=0,
Constant=50}">
<Image.GestureRecognizers>
<TapGestureRecognizer
Command="{Binding GoBackCommand}"/>
</Image.GestureRecognizers>
</Image>
</RelativeLayout>
<!--Some other elements and labels etc. -->
</StackLayout>
</ScrollView>
</ContentPage.Content>
如果您看到任何未初始化的变量,那是因为它们是在此循环之外声明的。我该如何解决这个问题?