我写了一个服务器程序,在Linux下测试,而后用C++写了客户端用千万级别数量的短连接进行压力测试. 可是服务器老是莫名退出,没有core文件.linux
最后问题肯定为, 对一个对端已经关闭的socket调用两次write, 第二次将会生成SIGPIPE信号, 该信号默认结束进程.安全
具体的分析能够结合TCP的"四次握手"关闭. TCP是全双工的信道, 能够看做两条单工信道, TCP链接两端的两个端点各负责一条. 当对端调用close时, 虽然本意是关闭整个两条信道, 但本端只是收到FIN包. 按照TCP协议的语义, 表示对端只是关闭了其所负责的那一条单工信道, 仍然能够继续接收数据. 也就是说, 由于TCP协议的限制, 一个端点没法获知对端的socket是调用了close仍是shutdown.服务器
对一个已经收到FIN包的socket调用read方法, 若是接收缓冲已空, 则返回0, 这就是常说的表示链接关闭. 但第一次对其调用write方法时, 若是发送缓冲没问题, 会返回正确写入(发送). 但发送的报文会致使对端发送RST报文, 由于对端的socket已经调用了close, 彻底关闭, 既不发送, 也不接收数据. 因此, 第二次调用write方法(假设在收到RST以后), 会生成SIGPIPE信号, 致使进程退出.socket
为了不进程退出, 能够捕获SIGPIPE信号, 或者忽略它, 给它设置SIG_IGN信号处理函数:函数
signal(SIGPIPE, SIG_IGN);测试
这样, 第二次调用write方法时, 会返回-1, 同时errno置为SIGPIPE. 程序便能知道对端已经关闭.线程
在linux下写socket的程序的时候,若是尝试send到一个disconnected socket上,就会让底层抛出一个SIGPIPE信号。
这个信号的缺省处理方法是退出进程,大多数时候这都不是咱们指望的。所以咱们须要重载这个信号的处理方法。调用如下代码,便可安全的屏蔽SIGPIPE:server
signal (SIGPIPE, SIG_IGN);进程
个人程序产生这个信号的缘由是:
client端经过 pipe 发送信息到server端后,就关闭client端, 这时server端,返回信息给 client 端时就产生Broken pipe 信号了,服务器就会被系统结束了。ip
对于产生信号,咱们能够在产生信号前利用方法 signal(int signum, sighandler_t handler) 设置信号的处理。若是没有调用此方法,系统就会调用默认处理方法:停止程序,显示提示信息(就是咱们常常遇到的问题)。咱们能够调用系统的处理方法,也能够自定义处理方法。
系统里边定义了三种处理方法:
(1)SIG_DFL信号专用的默认动做:
(a)若是默认动做是暂停线程,则该线程的执行被暂时挂起。当线程暂停期间,发送给线程的任何附加信号都不交付,直到该线程开始执行,可是SIGKILL除外。
(b)把挂起信号的信号动做设置成SIG_DFL,且其默认动做是忽略信号 (SIGCHLD)。
(2)SIG_IGN忽略信号
(a)该信号的交付对线程没有影响
(b)系统不容许把SIGKILL或SIGTOP信号的动做设置为SIG_DFL
3)SIG_ERR
项目中我调用了signal(SIGPIPE, SIG_IGN), 这样产生 SIGPIPE 信号时就不会停止程序,直接把这个信号忽略掉。