broken pipe 报错分析和解决办法
参考资料:
1.博客1:https://blog.csdn.net/qq_37535749/article/details/113781338
2.博客2:https://blog.csdn.net/zkkdcs1/article/details/88659069
3.博客3:https://superuser.com/questions/554855/how-can-i-fix-a-broken-pipe-error
4.博客4:https://www.cnblogs.com/cthon/p/9139553.html
#include <stdlib.h>
#include <sys/signal.h> //默认读写一个关闭的socket会触发sigpipe信号 该信号的默认操作是关闭进程 有时候这明显是我们不想要的
//所以此时我们需要重新设置sigpipe的信号回调操作函数 比如忽略操作等 使得我们可以防止调用它的默认操作
//信号的处理是异步操作 也就是说 在这一条语句以后继续往下执行中如果碰到信号依旧会调用信号的回调处理函数
//处理sigpipe信号
void handle_for_sigpipe()
{
struct sigaction sa; //信号处理结构体
memset(&sa, '\0', sizeof(sa));
sa.sa_handler = SIG_IGN;//设置信号的处理回调函数 这个SIG_IGN宏代表的操作就是忽略该信号
sa.sa_flags = 0;
if(sigaction(SIGPIPE, &sa, NULL))//将信号和信号的处理结构体绑定
return;
} int main(int argc, char *argv[])
{
handle_for_sigipipe();
while(1){}
return 0;
}
今天在原程序中需要新加若干个http接口,用来请求server端的版本信息,代码写完后放到开发环境测试,
一直在报broken pipe的错误,

后来经过排查,定位到时http client请求server数据的地方有错误。
回忆pipe的特性,pipe如果是两个父子进程掌控读端和写端,可能出现,“子进程写端关闭,父进程读端未关闭,产生僵尸进程”的现象。
用这个思路查阅了相关资料https://blog.csdn.net/zqz_zqz/article/details/52235479
摘除博客中的一句话:客户端读取超时关闭了连接,这时候服务器端再向客户端已经断开的连接写数据时就发生了broken pipe异常!
今天回溯了一下这个错误,发现了一篇讲的比较透彻的博客:https://www.cnblogs.com/cthon/p/9139553.html
问题:
写了一个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些内容,就会出错。
解决方法:
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端发送数据这种情况)
 
broken pipe 报错分析和解决办法的更多相关文章
- MyEclipse的JQuery.min.js报错红叉解决办法
		
MyEclipse的JQuery.min.js报错红叉解决办法 1.选中报错的jquery文件"jquery-1.2.6.min.js".2.右键选择 MyEclipse--> ...
 - 因采用 Flask 原生 WSGI 出现 "Broken pipe" 报错的故障处理
		
:first-child { margin-top: 0; } blockquote > :last-child { margin-bottom: 0; } img { border: 0; m ...
 - pom.xml内容没有错,但一直报错红叉 解决办法
		
转自:http://www.cnblogs.com/sxdcgaq8080/p/5590254.html [maven] pom.xml内容没有错,但一直报错红叉 解决办法 1.首先看一下下面的这两个 ...
 - Eclipse中引入com.sun.image.codec.jpeg包报错的完美解决办法
		
转: Eclipse中引入com.sun.image.codec.jpeg包报错的完美解决办法 更新时间:2018年02月14日 17:13:03 投稿:wdc 我要评论 Java开发中 ...
 - std::unique_ptr使用incomplete type的报错分析和解决
		
Pimpl(Pointer to implementation)很多同学都不陌生,但是从原始指针升级到C++11的独占指针std::unique_ptr时,会遇到一个incomplete type的报 ...
 - 关于Maven报错的一些解决办法(别处贴的)
		
1.警告:The tag handler class for "s:form"(org.apache.struts2.views.jsp.ui.FormTag) was not f ...
 - win7+IE11 中开发工具报错occurredJSLugin.3005解决办法
		
系统环境 win7+IE11 报错描述: Exception in window.onload: Error: An error has ocurredJSPlugin.3005 Stack Trac ...
 - iOS 提交审核报错 ERROR ITMS-90087解决办法
		
ERROR ITMS-: "Unsupported Architectures. The executable for yht.temp_caseinsensitive_rename.app ...
 - 【java-console】如何双击运行可执行jar包及遇到依赖dll报错问题的解决办法
		
如何配置双击运行可执行jar包的步骤,请移步到 这里 查看具体的操作,此处不再介绍. 本文主要解决如何处理依赖dll报错的问题解决办法. 我有一个jar包可执行文件运行需要依赖第三方的dll文 ...
 
随机推荐
- 字节跳动的一道python面试题
			
#!/usr/bin/python #coding=utf-8 #好好学习,天天向上 lst = ['hongkong','xiantyk','chinat','guangdong','z'] lst ...
 - kubernetes之kubeadm 安装kubernetes 高可用集群
			
1. 架构信息 系统版本:CentOS 7.6 内核:3.10.0-957.el7.x86_64 Kubernetes: v1.14.1 Docker-ce: 18.09.5 推荐硬件配置:4核8G ...
 - python网络爬虫-入门(一)
			
前言 1.爬虫程序是Dt(Data Technology,数据技术)收集信息的基础,爬取到目标网站的资料后,就可以分析和建立应用了. 2.python是一个简单.有效的语言,爬虫所需要的获取.存储.整 ...
 - Python初学笔记列表&元组&字典
			
一.从键盘获取 1 print("请输入") 2 username = input("姓名:") 3 age = input("年龄:") ...
 - ExcelPackage 使用說明
			
1.使用方法 public IActionResult Excel() { string sWebRootFolder = _hostingEnvironment.WebRootPath; strin ...
 - 入门 - 复习Kubernetes核心概念 (八)
			
本文将会简单介绍Kubernetes的核心概念.因为这些定义可以在Kubernetes的文档中找到,所以文章也会避免用大段的枯燥的文字介绍.相反,我们会使用一些图表(其中一些是动画)和示例来解释这些概 ...
 - python folium 库学习
			
一.简介 folium是js上著名的地理信息可视化库leaflet.js为Python提供的接口,通过它,我们可以通过在Python端编写代码操纵数据,来调用leaflet的相关功能,基于内建的osm ...
 - SendMessage  键值
			
转载请注明来源:https://www.cnblogs.com/hookjc/ SendMessage(hWnd,WM_SETFOCUS,0,0); SendMessage(hWnd,WM_ACTIV ...
 - 如何使用C++开发PHP扩展(下)
			
更多的情况是业务中已经有独立的 api 库,形式为 libxxx.a / libxxx.so,PHP程序中需要调用这些 api,所以这时就要编写PHP扩展来实现.这时是使用静态库 libxxx.a , ...
 - 【转】zabbix监控mysql
			
纯属搬家收藏,原文链接 https://www.cnblogs.com/shenjianyu/p/6627843.html 注意: 1.关注的重点在agent端部分 2.zabbix_get命令没有, ...