0

我有一个客户端/服务器程序,现在我想处理信号。当客户端关闭连接时(例如,如果我关闭终端),服务器必须处理 SIGPIPE,对吗?我想实现这样的东西。可能吗?

服务器.c:

void function(){
   printf("...");
   read(socket,buff,size);
   //IF THE CLIENT CLOSES, THE SERVER RECEIVES A SIGPIPE
   ...the resting part of the scheduled code should be ignored if sigpipe is received, and the program should begin from where I wrote on the handler of the sigpipe...
   printf("not working"); //this should be ignored, but it's printed 2 times immediatly, and when I've finished the actions indicated in the function by the handler, it prints it another time, because the program counter restarts from here...
}

void sigpipehandler(){
   close(socket);
   main(); //I'd like that the program restarts from the main when I've received a SIGPIPE. It restarts from the main, but only after having printed "not working" two times...
}

int main(){
   sigPipe.sa_sigaction = &sigpipehandler;
   sigPipe.sa_flags = SA_SIGINFO;
   sigaction(SIGPIPE, &sigpipehandler, NULL);
   ...code...
}
4

1 回答 1

1

将评论转换为答案。

请注意,只有当您写入没有进程且管道的读取端打开的管道时,您才会获得 SIGPIPE。当您从没有进程且管道写入端打开的管道中读取时,您将获得 EOF(读取零字节)。

因此,如果我在示例中read()使用 a更改。write()我该如何处理 SIGPIPE?

最简单的方法是忽略 SIGPIPE( signal(SIGPIPE, SIG_IGN)),然后监视来自 的返回值write()。如果它返回 -1 并errno设置为EINTR,您可以假设您被某些信号打断,而且很可能是 SIGPIPE,尤其是在您没有任何其他信号处理集的情况下。当然,无论如何,您都应该查看来自write()- 和- 的返回值。read()

或者,如果你想要一个显式的 SIGPIPE 处理程序,那么你肯定不想main()从你的信号处理程序递归调用。您可以在 中编写一个循环main(),并让信号处理程序设置一个您在循环中测试的标志。根据标准 C,您在信号处理程序中唯一能做的就是修改变量或退出。

static volatile sigatomic_t sig_recvd = 0;
static int sock_fd = -1;

void sigpipehandler(int signum)
{
   close(sock_fd);
   sock_fd = -1;
   sig_recvd = signum;
}

int main(void)
{
    sigPipe.sa_sigaction = &sigpipehandler;
    sigPipe.sa_flags = SA_SIGINFO;
    sigemptyset(&sigPipe.sa_mask);
    sigaction(SIGPIPE, &sigpipehandler, NULL);

    int done = 0;

    while (!done)
    {
        if (sock_fd == -1)
        {
            if (sig_recvd != 0)
            {
                ...report signal received...
                sig_recvd = 0;
            }
            ...(re)open socket on sock_fd...
        }
        ...code as before - sets done = 1 when loop should terminate...
    }
    return 0;
}

请注意,将变量命名为与系统调用相同(socket在您的代码中)是如履薄冰;因此,我将其重命名sock_fd。一个名为的全局变量socket将是一个非常糟糕的主意。

于 2014-10-22T17:20:00.820 回答