问题:

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

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

分析:

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

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

管道的特点:

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

管道特性的表现:

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

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

总结:

如果要进行顺利的管道通信:管道的两端必需都打开。

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

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

解决方法:

  • 忽略SIGPIPE信号

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

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

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

   

tcp连接时,BROKEN PIPE错误的原因以及解决方法的更多相关文章

  1. Navicat 连接 Mysql 报2059错误的原因以及解决方法

    MySQL的8.0.*版本使用的是caching_sha2_password验证方式,而Navicat Premium 12还不支持该种方式.解决方案: 1,降低mysql的版本 2,设置mysql支 ...

  2. Nginx 499错误的原因及解决方法

    今天进行系统维护,发现了大量的499错误, 499错误 ngx_string(ngx_http_error_495_page), /* 495, https certificate error */n ...

  3. 004_Nginx 499错误的原因及解决方法

    一. 今天进行系统维护,发现了大量的499错误, 499错误 ngx_string(ngx_http_error_495_page), /* 495, https certificate error ...

  4. 出现 java.lang.OutOfMemoryError: PermGen space 错误的原因及解决方法

    一.原因及解决方法[1] 1.原因:堆内存的永久保存去区内存分配不足(缺省默认为64M),导致内存溢出错误. 2.解决方法:重新分配内存大小,-Xms1024M -Xmx2048M -XX:PermS ...

  5. qt 旧项目编译运行提示 “启动程序失败,路径或者权限错误?” 原因及解决方法

    qt 旧项目编译运行提示 "启动程序失败,路径或者权限错误?" 原因及解决方法 原因 Qt Creator在打开项目文件的同时会生成.pro.user文件,.pro.user文件叫 ...

  6. TCP连接状态详解及TIME_WAIT过多的解决方法

    上图对排除和定位网络或系统故障时大有帮助,但是怎样牢牢地将这张图刻在脑中呢?那么你就一定要对这张图的每一个状态,及转换的过程有深刻地认识,不能只停留在一知半解之中.下面对这张图的11种状态详细解释一下 ...

  7. Nginx 502 Bad Gateway 错误的原因及解决方法

    http://my.oschina.net/zhouyuan/blog/118708 刚才在调试程序的时候,居然服务器502错误,昨天晚上也发生了,好像我没有做非常规的操作. 然后网上寻找了下答案, ...

  8. 造成win2008 500内部错误不能显示详细错误的原因和解决方法

    造成500错误常见原因有:ASP语法出错.ACCESS数据库连接语句出错.文件引用与包含路径出错.使用了服务器不支持的组件如FSO等. 另外,对于win2008的IIS默认不显示详细出错信息的问题以下 ...

  9. jmeter连接不上MySQL数据库的原因以及解决方法

    1.Cannot create PoolableConnectionFactory (Client does not support authentication protocol requested ...

随机推荐

  1. 查看java中的线程个数名称

    查看java中的线程个数名称 package com.stono.thread2; import java.lang.management.ManagementFactory; import java ...

  2. mysql 执行sql文件的方法

     http://philos.iteye.com/blog/162051   实战代码: #mysql导入mysql -um4n -p01D060A476642BA8335B832AC5B211F22 ...

  3. windows下通过VNC图形化訪问Ubuntu桌面环境

    要在windows下图形化訪问Ubuntu或其他Linux系统桌面环境有非常多方法.我比較喜欢的是使用VNC服务,须要在Ubuntu下安装vncserver和在windows下安装client訪问工具 ...

  4. c语言知识点总结-------静态区、堆、栈、常量区等

    在C语言中地址占4个字节 1.编程语言发展 低级语言----->高级语言 机器语言 ---> 汇编---->高级语言(C语言.C++.JAVA等) 机器语言 :0101 0010 1 ...

  5. 每天一个linux命令(23):Linux 目录结构(转)

    对于每一个Linux学习者来说,了解Linux文件系统的目录结构,是学好Linux的至关重要的一步.,深入了解linux文件目录结构的标准和每个目录的详细功能,对于我们用好linux系统只管重要,下面 ...

  6. cocos2dx3.2 学习笔记(2)--ActionManagerTest

    前面看完了 CppTests的基本框架及流程.如今准备看看详细的每一个Test了 从哪里開始看呢. 额,就第一个吧(ActionManagerTest) 首先看看效果吧,执行了下.发现有几种效果.看不 ...

  7. 《UNIX 网络编程 第二版》编译环境的搭建( 运行本专栏代码必读 )

    第一步:搭建基本的编译环境 安装gcc, g++, bulid-essential等编译软件 第二步:下载本书示例源码包 可在这里下载http://ishare.iask.sina.com.cn/f/ ...

  8. Eclipse-----Eclipse断点调试

  9. 例题6-16 单词 UVa10129

    1.题目描写叙述:点击打开链接 2.解题思路:本题利用欧拉回路存在条件解决. 能够将全部的单词看做边,26个字母看做端点,那么本题事实上就是问是否存在一条路径,能够到达全部出现过的字符端点. 因为本题 ...

  10. difference between http get and post

    1 用get的地方 在浏览器中输入url直接访问资源时,用get.get是通过url传参的. 2 用post的地方 2.1 url长度超限时 post是将参数放在http body中的,因此对参数的长 ...