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文 ...
随机推荐
- 微服务架构 | 11.1 整合 Seata AT 模式实现分布式事务
目录 前言 1. Seata 基础知识 1.1 Seata 的 AT 模式 1.2 Seata AT 模式的工作流程 1.3 Seata 服务端的存储模式 1.4 Seata 与 Spring Clo ...
- c语言之sizeof总结+strlen函数
一.sizeof的概念 Sizeof是C语言的一种单目操作符,如C语言的其他操作符++.–等.它并不是函数.Sizeof操作符以字节形式给出了其操作数的存储大小.操作数可以是一个表达式或括在括号内的类 ...
- Html设置文本换行与不按行操作
图片来源:W3C 部分引自大佬:https://zhidao.baidu.com/question/424920602093167052.html 强制不换行 div{ white-space:now ...
- vue3 最长递增子序列 diff优化
//vue3优化版(回头我会完善下算法思路) function getSequence(arr) { const p = arr.slice() const result = [0] let i, j ...
- Android SDK:Android standard develop kits 安卓开发的工具集
目前主流的安卓开发工具: 1.Adnroid-Adt-bundle SDK Manager.exe: Tools(安卓的开发小工具) 各种安卓版本 Extras 额外的开发包 在线更新/安装的安卓版本 ...
- Springcloud-微服务
1.什么是微服务? 通过阅读马丁弗勒关于描述微服务的文章(https://martinfowler.com/articles/microservices.html),在此特作仅用作个人理解的关于微服务 ...
- tabbar选中按钮的标题颜色和字体
@implementation XMGTabBarController /* 问题: 1.选中按钮的图片被渲染 -> iOS7之后默认tabBar上按钮图片都会被渲染 1.修改图片 2.通过代码 ...
- Java中继承时静态块,构造块,构造函数的执行顺序
public class Father { static { System.out.println("Father静态块"); } { System.out.println(&qu ...
- 他人学习Python感悟
作者:王一 链接:https://www.zhihu.com/question/26235428/answer/36568428 来源:知乎 著作权归作者所有.商业转载请联系作者获得授权,非商业转载请 ...
- appium填坑
首次使用appium web driver,不说搭建环境的麻烦,初次写完一个操作计算器的程序,但是运行一直报错:selenium.common.exceptions.WebDriverExceptio ...