从tcp原理角度理解Broken pipe和Connection reset by peer的区别
以前我们经常会碰到Broken pipe
或者Connection reset by peer
之类的异常,但是tcp实现里什么情况下会抛出这些异常呢,以前我给对方的回答都是模棱两可的,自己说实话都没把握,因为自己也没有验证过,对它们的认识都是从网上看来的,正确与否也不知道,昨天独明突然又问到这个问题,前段时间正好对tcp这块研究了一段时间,有了点理论知识之后再从实践角度对此问题进行一下分析,下面对我这次的调研过程进行下描述与大家分享,希望大家以后对此类问题都能很自信地应答。
三次握手和四次挥手过程
在讲具体的原因之前,我们有必要补充下tcp这块的一些基础知识,我们都知道tcp通信有三次握手和四次挥手,网上介绍的文章也一大堆,图我也懒得画了,直接网上找一个图给大家
三次握手是最前面的三条线表示的过程,四次挥手是最后面的四条线表示的过程,里面涉及到几个关键词,SYN,ACK,FIN,MSS,其中SYN是主要用在三次握手过程中的,FIN用在四次挥手过程中,ACK在三次握手和四次挥手过程中的作用就是对收到的SYN和FIN做一个确认,SYN,FIN等存在于TCP头里(tcp报文图也给大家弄了个图,不用再去找啦),0/1表示有无此标记,在tcp实现里后面还会跟一个依次递增的数字,比如上面的J,K等,确认就是递增这些数字(真正的数据报文的ack除外),MSS是表示每一个tcp报文里数据字段的最大长度,不包括tcp头的大小噢 相信大家看到这两个图会对这些概念有了一个清晰的认识了
tcpdump抓包工具
介绍了基础原理之后,再介绍下抓包工具,tcpdump,这工具对你了解tcp的整个过程会非常有帮助,在你无法调试tcp实现的情况下这个工具自然也是必不可少的,具体用法网上有很多介绍,直接从man page上也可以看到详细的介绍,我也不多说啦,下面的截图就是tcpdump根据tcp通信过程获取到的
这要稍微提下tcpdump的结果和上面的几个过程的对应关系 前面三条其实就是我们上面所说的三次握手,四次握手过程上面没有完全表现出来,只完成了一半的挥手过程(5,8两条表示的) 里面有几个标识S,F,ack,P,其实还有个R,如果有这些标识那么在tcp头里的SYN,FIN,ACK,PSH,RET分别为1,其中PSH表示要求tcp立即将数据传递给上层,不要做别的什么处理,RET这个表示重置连接,也是和我们今天讨论的问题有很大关系的FLAG,下面会详细介绍
reset报文发送场景
RST的标志位,这个标识为在如下几种情况下会被设置,以下是我了解的情况,可能还有更多的场景,没有验证
- 当尝试和未开放的服务器端口建立tcp连接时,服务器tcp将会直接向客户端发送reset报文
- 双方之前已经正常建立了通信通道,也可能进行过了交互,当某一方在交互的过程中发生了异常,如崩溃等,异常的一方会向对端发送reset报文,通知对方将连接关闭
- 当收到TCP报文,但是发现该报文不是已建立的TCP连接列表可处理的,则其直接向对端发送reset报文
- ack报文丢失,并且超出一定的重传次数或时间后,会主动向对端发送reset报文释放该TCP连接
Broken pipe以及Connection reset by peer
做了这么些铺垫之后下面进入正题,那么Broken pipe
或者Connection reset by peer
分别代表什么意思呢,下面从glibc的源码里有对此的介绍
- #. TRANS Broken pipe; there is no process reading from the other end of a pipe.
- #. TRANS Every library function that returns this error code also generates a
- #. TRANS @code{SIGPIPE} signal; this signal terminates the program if not handled
- #. TRANS or blocked. Thus, your program will never actually see @code{EPIPE}
- #. TRANS unless it has handled or blocked @code{SIGPIPE}.
- #: sysdeps/generic/siglist.h:39 sysdeps/gnu/errlist.c:359
- #: sysdeps/unix/siglist.c:39
- msgid "Broken pipe"
- msgstr "断开的管道"
- #. TRANS A network connection was closed for reasons outside the control of the
- #. TRANS local host, such as by the remote machine rebooting or an unrecoverable
- #. TRANS protocol violation.
- #: sysdeps/gnu/errlist.c:614
- msgid "Connection reset by peer"
- msgstr ""
其实我们java异常里看到的Broken pipe
或者Connection reset by peer
信息不是jdk或者jvm里定义的,我看到这些关键字往往会首先搜索下jdk或者hotspot源码找到位置进行上下文分析,但是这次没找到,后面才想到应该是linux或者glibc里定义的,果然在glibc离看到了如上的描述和定义
对于Broken pipe
在管道的另外一端没有进程再读的时候就会抛出此异常,Connection reset by peer
的描述其实不是很正确,从我的实践来看只描述了一方面,其实在某一端正常close之后,也是可能会有此异常的。
异常模拟
从我的测试场景是这样的, 共同的前提是客户端向服务端发了数据之后立马调用close关闭socket并进程退出,而服务端在收到客户端的数据之后sleep一会,保证对方的socket已经关闭,接着分别进行两种场景测试
场景:
服务端往socket里写一次数据,返回继续做select
服务端连续写两次数据,必须保证两次的buffer都是有数据的,也就是保证ByteBuffer的pos和limit要不是一个值
结果:
会抛出Connection reset by peer
会抛出Broken pipe
分析:
当我们往一个对端已经close的通道写数据的时候,对方的tcp会收到这个报文,并且反馈一个reset报文,tcpdump的结果如下所示,当收到reset报文的时候,继续做select读数据的时候就会抛出
Connect reset by peer
的异常,从堆栈可以看得出当第一次往一个对端已经close的通道写数据的时候会和上面的情况一样,会收到reset报文,当再次往这个socket写数据的时候,就会抛出
Broken pipe
了 ,根据tcp的约定,当收到reset包的时候,上层必须要做出处理,调用将socket文件描述符进行关闭,其实也意味着pipe会关闭,因此会抛出这个顾名思义的异常
从tcp原理角度理解Broken pipe和Connection reset by peer的区别的更多相关文章
- keepalived+lvs tcp check 引起的后端服务报Connection reset by peer
方法一: 取消LVS方式进行tcp转发,进而改为http方式反向代理,问题即可解决. 当然,这是在业务允许使用http的情况下,如果必须使用tcp协议,那就得使用下面的方法了. 方法二: 修改keep ...
- Linux(CentOS)上配置 SFTP(附解决Write failed: Broken pipe Couldn't read packet: Connection reset by peer)
#创建sftp组: groupadd sftp #创建一个用户sftpuser: useradd -g sftp -s /bin/false sftpuser #提示: /etc/group 文件包含 ...
- IL角度理解C#中字段,属性与方法的区别
IL角度理解C#中字段,属性与方法的区别 1.字段,属性与方法的区别 字段的本质是变量,直接在类或者结构体中声明.类或者结构体中会有实例字段,静态字段等(静态字段可实现内存共享功能,比如数学上的pi就 ...
- OGG-01232 Receive TCP params error: TCP/IP error 104 (Connection reset by peer), endpoint:
源端: 2015-02-05 17:45:49 INFO OGG-01815 Virtual Memory Facilities for: COM anon alloc: mmap(MAP_ANON) ...
- docker: read tcp 192.168.7.235:36512->54.230.212.9:443: read: connection reset by peer.
在学习rancher的时候去下载rancher/agent镜像的时候,出现报错:docker: read tcp 192.168.7.235:36512->54.230.212.9:443: r ...
- Connection reset by peer原理解析
“Connection reset by peer”代表什么?“Connection reset by peer”表示当前服务器接受到了通信对端发送的TCP RST信号,即通信对端已经关闭了连接,通过 ...
- 记一次压测问题定位:connection reset by peer,TCP三次握手后服务端发送RST_网络_c359719435的专栏-CSDN博客 https://blog.csdn.net/c359719435/article/details/80300433
记一次压测问题定位:connection reset by peer,TCP三次握手后服务端发送RST_网络_c359719435的专栏-CSDN博客 https://blog.csdn.net/c3 ...
- TCP连接异常:broken pipe 和EOF
本文介绍3种TCP连接异常的情况. 1.server端没有启动,client尝试连接 ./client dial failed: dial tcp 127.0.0.1:8080: connect: c ...
- tcp连接时,BROKEN PIPE错误的原因以及解决方法
问题: 写了一个server和一个client,UNIX套接字的,server不断接收消息并打印出来,client是一个交互程序,输入一个消息回车发送,接着又可以输入消息.出问题了:当server监听 ...
随机推荐
- 初学Android:意图之intent
Intent意为:意图.简单的理解就是用来从一个Activity/Service跳转到另一个Activity/Service中,并可以携带数据,也可以在这个程序调用别的程序.这样我们虽然不懂如何结息条 ...
- 浅析ASP.NET的状态保持
ASP.NET的状态保持:1.viewstate:隐藏域,记录服务器端控件的状态,适用于页面不关闭的情况下多次与服务器交互,页面自己给自己传值:文本框的改变事件.IspostBack也依赖viewst ...
- Spring 和 MyBatis 环境整合
本案例主要是讲述Spring 和 MyBatis 的环境整合 , 对页面功能的实现并没有做的很完整 先附上本案例的结构 1 . 创建项目并导入相关jar包 commons-collections4 ...
- sql server varchar和nvarchar的区别
一.前言 在了解varchar 和nvarchar之前咱们先了解一下这些词的字面和常用意思,以方便我们更好的使用: SQL SERVER中生成的语句中,字符串前加N.N 前缀必须是大写字母.是Unic ...
- OC - 6.block与protocol
一.block 1> 基本使用 相当于用来存放代码的代码块 效率高 若没有形参可以省略小括号 2> block与函数的相同点 可以保存代码 可以有返回值 可以有形参 调用方式一样 3> ...
- css3中matrix函数的使用
scale(sx,sy)对应matrix(sx,0,0,sy,0,0) 拉伸 rotate(θ)对应matrix(cosθ,sinθ,-sinθ,cosθ,0,0) 旋转 skew(θx,θy)对 ...
- Codevs 3990 中国余数定理 2
3990 中国余数定理 2 时间限制: 1 s 空间限制: 1000 KB 题目等级 : 白银 Silver 传送门 题目描述 Description Skytree神犇最近在研究中国博大精深的数学. ...
- STUN/TURN/ICE协议在P2P SIP中的应用(一)
1 说明 本文详细描述了基于STUN系列协议实现的P2P SIP电话过程,其中涉及到了SIP信令的交互,P2P的原理,以及STUN.TURN.ICE的协议交互 本文所提到的各个服务 ...
- zoj 3686 A Simple Tree Problem (线段树)
Solution: 根据树的遍历道的时间给树的节点编号,记录下进入节点和退出节点的时间.这个时间区间覆盖了这个节点的所有子树,可以当做连续的区间利用线段树进行操作. /* 线段树 */ #pragma ...
- 九度OJ 1081 递推数列 -- 矩阵二分乘法
题目地址:http://ac.jobdu.com/problem.php?pid=1081 题目描述: 给定a0,a1,以及an=p*a(n-1) + q*a(n-2)中的p,q.这里n >= ...