tcp链接时,BROKEN PIPE错误的缘由以及解决方法

问题:网络

写了一个server和一个client,UNIX套接字的,server不断接收消息并打印出来,client是一个交互程序,输入一个消息回车发送,接着又能够输入消息。
出问题了:
当server监听着,client第一次发送消息成功,server接收并打印出来了。
client第二次发送消息没成功而且结束程序了,server没接收到消息,保持继续监听。
我用GDB调试时,发现client第二次发送消息时,client收到SIGPIPE(Broken Pipe)信号。server明明还监听着,并且再次启动client仍是第一次成功,第二次失败退出。socket

 一样的,当client由于断开(关闭了网络描述符sfd,或者ctrl+c/ctrl+\异常断开),server端也产生SIGPIPE信号。tcp

分析:spa

TCP协议是端到端的传输控制协议,之因此是“端到端”的协议,是由于”路由“是由IP协议负责的,TCP协议负责为两个通讯端点提供可靠性保证,这个可靠性不是指一个端点发送的数据,另外一个端点确定能收到(这显然是不可能的),而是指,数据的可靠投递或者故障的可靠通知。调试

所谓的“端到端”,指的是在通讯两端之间创建了一个全双工的通讯管道,既然是管道,就不得不了解管道。server

 

管道的特色:blog

  • 管道是半双工的,数据只能向一个方向流动;须要双方通讯时,须要创建起两个管道;
  • 只能用于父子进程或者兄弟进程之间(具备亲缘关系的进程);
  • 单独构成一种独立的文件系统:管道对于管道两端的进程而言,就是一个文件,但它不是普通的文件,它不属于某种文件系统,而是自立门户,单独构成一种文件系统,而且只存在与内存中。
  • 数据的读出和写入:一个进程向管道中写的内容被管道另外一端的进程读出。写入的内容每次都添加在管道缓冲区的末尾,而且每次都是从缓冲区的头部读出数据。

管道特性的表现:进程

  • 若是一个进程以只写打开管道,可是没有以只读或读写打开这个管道的进程,则打开操做会阻塞, 直到有进程以读或读写打开,open 才会返回。(写端打开,读端关闭)
  • 若是一个进程以只读打开管道,可是没有以只写或读写打开这个管道的进程,则打开操做会阻塞, 直到有进程以写或读写打开,open 才会返回。(写端关闭,读端打开)
  • 当写端没有写入数据时,读端会阻塞到 read 调用,直到写端写入数据或者写端关闭。 当管道没有空间时,再写入数据就会被阻塞。直到有进程读取数据,或者全部的读端关闭。(读写顺序)

注意:全双工,指的是每一端均可读可写。前提是对端打开若是对端都关闭了,本端读数据为空,不会出错;但本段写数据确定出错。ip

总结:内存

若是要进行顺利的管道通讯:管道的两端必需都打开。

  • 管道读端关闭,写端不能写,不然会发出SIGPIPE信号,即会生成BROKEN PIPE错误。

也就是说tcp通讯时,client端经过 pipe发送信息到server端后,client端挂没必要,这时server端返回信息,向pipe些内容,就会出错。

 

解决方法:

  • 忽略SIGPIPE信号

    一、signal(SIGPIPE,SIG_INT);//(全局范围内)

    二、setsocketop;//(tcp特性设置)

/// sock 就是设置不发送 `SIGPIPE` 信号的 socket 变量
int value = 1;
setsockopt(sock, SOL_SOCKET, SO_NOSIGPIPE, &value, sizeof(value));
  • 合理规避读端关闭,写端打开的问题。(避免client端关闭,server端发送数据这种状况)
相关文章
相关标签/搜索