sdf水电费SIGPIPE信号产生的规则:当一个进程向某个已收到RST的套接字执行写操作时,内核向该进程发送SIGPIPE信号。
<1>如果客户端关闭了socket(close),而服务端调用了一次write,服务端就会接收到一个RST Segment,如果服务端再次调用write,这个时候就会产生SIGPIPE信号,默认终止进程
直接忽略SIGPIPE信号:signal(SIGPIPE, SIG_IGN)
SIG_IGN忽略信号
<2>SIGPIPE
产生的原因是这样的:如果一个 socket 在接收到了 RST packet 之后,程序仍然向这个 socket 写入数据,那么就会产生SIGPIPE
信号。
这种现象是很常见的,譬如说,当 client 连接到 server 之后,这时候 server 准备向 client 发送多条消息,但在发送消息之前,client 进程意外奔溃了,那么接下来 server 在发送多条消息的过程中,就会出现SIGPIPE
信号
例子代码:
网络编程中的 SIGPIPE 信号 - tycoon3 - 博客园
<3>
另外,我再做一些补充,产生RST响应以至于系统发出SIGPIPE信号,应该分为两种情况:
1. 客户端到服务端之间网络断掉,或者服务端断电等,物理连接断掉了,这种情况下客户端不会退出,send函数正常执行,不会感觉到自己出错。因为由于物理网络断开,服务端不会给客户端回应错误消息,没有RST响应,自然也不会产生SIGPIPE信号。但是当服务端再恢复正常的时候,对客户端send来的消息会产生RST响应,客户端就收到SIGPIPE信号了,程序退出,但是这时send函数是能够返回 -1的。可以进行异常处理。
2.客户端到服务端的网络能通,服务程序挂掉,客户端程序会马上退出,因为服务端能正常返回错误消息,客户端收到,SIGPIPE信号就产生了。不过我不确定此时服务端返回是的RST响应,抓包来看没有RST标志。水平有限,只写到这了。
问题解决:
由上面原因总结出两种方法:
1、设置系统忽略SIGPIPIE消息,从结果解决SIGPIPE错误导致程序崩溃问题;
在socket建立时设置下列属性,socket将不会产生SIGPIPE信号。
int optval=1;
#ifdef __linux__
setsockopt(m_Sockfd, SOL_SOCKET, MSG_NOSIGNAL, &optval, sizeof(optval));
#else
setsockopt(m_Sockfd, SOL_SOCKET, SO_NOSIGPIPE, &optval, sizeof(optval));