sigpipe c server/client - 程序在哪里重新启动?
Posted
技术标签:
【中文标题】sigpipe c server/client - 程序在哪里重新启动?【英文标题】:sigpipe c server/client - where does the program restart? 【发布时间】:2014-10-22 05:40:12 【问题描述】:我有一个客户端/服务器程序,现在我想处理信号。当客户端关闭连接时(例如,如果我关闭终端),服务器必须处理 SIGPIPE,对吗?我想实现这样的东西。有可能吗?
server.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...
【问题讨论】:
当你写到一个封闭的管道时你会得到 SIGPIPE;当您从封闭管道读取时,您会得到 EOF(读取零字节)。 @JonathanLeffler 感谢您的回复。因此,如果我在示例中将读取更改为写入。我该如何处理 SIGPIPE,就像解释的那样? 最简单的就是忽略SIGPIPE,然后监听write()
的返回值。如果它返回 -1 并且 errno
设置为 EINTR,您可能会怀疑您有一个 SIGPIPE,特别是如果您没有任何其他信号处理集。当然,无论如何,您应该查看来自write()
和read()
的返回值。您不想从信号处理程序中递归调用 main()
。您可以在main()
中编写一个循环,并让信号处理程序设置一个您在循环中测试的标志。根据标准 C,您在信号处理程序中唯一能做的就是修改变量或退出。
【参考方案1】:
将 cmets 转换为答案。
请注意,只有当您写入没有进程且管道的读取端打开的管道时,您才会获得 SIGPIPE。当您从没有进程且管道的写入端打开的管道中读取时,您会得到 EOF(读取零字节)。
所以,如果我在示例中将
read()
更改为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
的全局变量将是一个非常糟糕的主意。
【讨论】:
以上是关于sigpipe c server/client - 程序在哪里重新启动?的主要内容,如果未能解决你的问题,请参考以下文章
Eclipse CDT:线程在调试模式下获取 SIGPIPE
c udp server client demo --待调试
c tcp sockt server client -- demo