socket编程—— 服务器遇到Broken Pipe崩溃
来源:互联网 发布:网络监察大队怎么报警 编辑:程序博客网 时间:2024/06/05 15:03
我写了一个服务器程序, 在Linux下测试时, 总是莫名退出. 最后跟踪到是write调用导致退出. 用gdb执行程序, 退出时提示"Broken pipe".
最后问题确定为, 对一个对端已经关闭的socket调用两次write, 第二次将会生成SIGPIPE信号, 该信号默认结束进程.
具体的分析可以结合TCP的"四次握手"关闭. TCP是全双工的信道, 可以看作两条单工信道, TCP连接两端的两个端点各负责一条. 当对端调用close时, 虽然本意是关闭整个两条信道, 但本端只是收到FIN包. 按照TCP协议的语义, 表示对端只是关闭了其所负责的那一条单工信道, 仍然可以继续接收数据. 也就是说, 因为TCP协议的限制, 一个端点无法获知对端的socket是调用了close还是shutdown.
对一个已经收到FIN包的socket调用read方法, 如果接收缓冲已空, 则返回0, 这就是常说的表示连接关闭. 但第一次对其调用write方法时, 如果发送缓冲没问题, 会返回正确写入(发送). 但发送的报文会导致对端发送RST报文, 因为对端的socket已经调用了close, 完全关闭, 既不发送, 也不接收数据. 所以, 第二次调用write方法(假设在收到RST之后), 会生成SIGPIPE信号, 导致进程退出.
为了避免进程退出, 可以捕获SIGPIPE信号, 或者忽略它, 给它设置SIG_IGN信号处理函数:
signal(SIGPIPE, SIG_IGN);
这样, 第二次调用write方法时, 会返回-1, 同时errno置为SIGPIPE. 程序便能知道对端已经关闭.
PS: Linux下的SIGALRM似乎会每1秒钟往后偏移1毫秒, 但Windows下经过测试完全准时, 不差1毫秒.
当然还有其他方法来处理SIGPIPE
设置当前socket在进行写操作时不产生SIGPIPE。
int
set = 1;
setsockopt(sd, SOL_SOCKET, SO_NOSIGPIPE, (
void
*)&set,
sizeof
(
int
));
这样做的好处在于:在某些情况 下我们并不需要一个全局的SIGPIPE handler。但是据说这种并不通用,在linux下没有相应的定义—-但我在mac下测试通过。
转自 http://blog.csdn.net/mustanglau/article/details/4485491
- socket编程—— 服务器遇到Broken Pipe崩溃
- socket编程—— 服务器遇到Broken Pipe崩溃
- socket编程—— 服务器遇到Broken Pipe崩溃
- 服务器遇到Broken Pipe崩溃
- Socket 编程时候遇到的Broken pipe问题
- Java socket broken pipe
- Linux编程问题—broken pipe 问题解决方法
- linux socket c : send data when socket close—SIGPIPE, Broken pipe
- linux socket c : send data when socket close—SIGPIPE, Broken pipe
- linux网络编程:Broken pipe
- socket 打破的管道 broken pipe
- broken pipe
- broken pipe
- broken pipe
- broken pipe
- broken pipe
- linux 下写socket遭遇broken pipe(SIGPIPE C++)
- java服务器出现broken pipe ,connection reset解决方法
- 微软证实:Windows 9开发工作已经展开
- Android APK报错:java.io.IOException: Permission denied
- 展讯android LEDS模块分析----四大路径
- hdu 1541 树状数组简单
- 长程调度、中程调度、短程调度
- socket编程—— 服务器遇到Broken Pipe崩溃
- create file遇到操作系统错误5拒绝访问
- Khan公开课 - 统计学学习笔记:(八)样本均值之差
- 第5周任务3-摄氏温度值转华氏温度
- 展讯android LEDS模块分析----各种关系
- 星号
- ant简单打包build.xml文件
- ARM汇编中的标号使用
- 采用python中SQLalchemy模块访问数据库库(二)