从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的源码里有对此的介绍

  1. #. TRANS Broken pipe; there is no process reading from the other end of a pipe.
  2. #. TRANS Every library function that returns this error code also generates a
  3. #. TRANS @code{SIGPIPE} signal; this signal terminates the program if not handled
  4. #. TRANS or blocked. Thus, your program will never actually see @code{EPIPE}
  5. #. TRANS unless it has handled or blocked @code{SIGPIPE}.
  6. #: sysdeps/generic/siglist.h:39 sysdeps/gnu/errlist.c:359
  7. #: sysdeps/unix/siglist.c:39
  8. msgid "Broken pipe"
  9. msgstr "断开的管道"
  10.  
  11. #. TRANS A network connection was closed for reasons outside the control of the
  12. #. TRANS local host, such as by the remote machine rebooting or an unrecoverable
  13. #. TRANS protocol violation.
  14. #: sysdeps/gnu/errlist.c:614
  15. msgid "Connection reset by peer"
  16. 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已经关闭,接着分别进行两种场景测试

  场景:

  1. 服务端往socket里写一次数据,返回继续做select

  2. 服务端连续写两次数据,必须保证两次的buffer都是有数据的,也就是保证ByteBuffer的pos和limit要不是一个值

  结果:

  1. 会抛出Connection reset by peer 

  2. 会抛出Broken pipe

  分析:

  1. 当我们往一个对端已经close的通道写数据的时候,对方的tcp会收到这个报文,并且反馈一个reset报文,tcpdump的结果如下所示,当收到reset报文的时候,继续做select读数据的时候就会抛出Connect reset by peer的异常,从堆栈可以看得出 

  2. 当第一次往一个对端已经close的通道写数据的时候会和上面的情况一样,会收到reset报文,当再次往这个socket写数据的时候,就会抛出Broken pipe了 ,根据tcp的约定,当收到reset包的时候,上层必须要做出处理,调用将socket文件描述符进行关闭,其实也意味着pipe会关闭,因此会抛出这个顾名思义的异常

从tcp原理角度理解Broken pipe和Connection reset by peer的区别的更多相关文章

  1. keepalived+lvs tcp check 引起的后端服务报Connection reset by peer

    方法一: 取消LVS方式进行tcp转发,进而改为http方式反向代理,问题即可解决. 当然,这是在业务允许使用http的情况下,如果必须使用tcp协议,那就得使用下面的方法了. 方法二: 修改keep ...

  2. 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 文件包含 ...

  3. IL角度理解C#中字段,属性与方法的区别

    IL角度理解C#中字段,属性与方法的区别 1.字段,属性与方法的区别 字段的本质是变量,直接在类或者结构体中声明.类或者结构体中会有实例字段,静态字段等(静态字段可实现内存共享功能,比如数学上的pi就 ...

  4. 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) ...

  5. 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 ...

  6. Connection reset by peer原理解析

    “Connection reset by peer”代表什么?“Connection reset by peer”表示当前服务器接受到了通信对端发送的TCP RST信号,即通信对端已经关闭了连接,通过 ...

  7. 记一次压测问题定位: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 ...

  8. TCP连接异常:broken pipe 和EOF

    本文介绍3种TCP连接异常的情况. 1.server端没有启动,client尝试连接 ./client dial failed: dial tcp 127.0.0.1:8080: connect: c ...

  9. tcp连接时,BROKEN PIPE错误的原因以及解决方法

    问题: 写了一个server和一个client,UNIX套接字的,server不断接收消息并打印出来,client是一个交互程序,输入一个消息回车发送,接着又可以输入消息.出问题了:当server监听 ...

随机推荐

  1. 初学Android:意图之intent

    Intent意为:意图.简单的理解就是用来从一个Activity/Service跳转到另一个Activity/Service中,并可以携带数据,也可以在这个程序调用别的程序.这样我们虽然不懂如何结息条 ...

  2. 浅析ASP.NET的状态保持

    ASP.NET的状态保持:1.viewstate:隐藏域,记录服务器端控件的状态,适用于页面不关闭的情况下多次与服务器交互,页面自己给自己传值:文本框的改变事件.IspostBack也依赖viewst ...

  3. Spring 和 MyBatis 环境整合

    本案例主要是讲述Spring  和  MyBatis 的环境整合 , 对页面功能的实现并没有做的很完整 先附上本案例的结构 1 . 创建项目并导入相关jar包 commons-collections4 ...

  4. sql server varchar和nvarchar的区别

    一.前言 在了解varchar 和nvarchar之前咱们先了解一下这些词的字面和常用意思,以方便我们更好的使用: SQL SERVER中生成的语句中,字符串前加N.N 前缀必须是大写字母.是Unic ...

  5. OC - 6.block与protocol

    一.block 1> 基本使用 相当于用来存放代码的代码块 效率高 若没有形参可以省略小括号 2> block与函数的相同点 可以保存代码 可以有返回值 可以有形参 调用方式一样 3> ...

  6. css3中matrix函数的使用

    scale(sx,sy)对应matrix(sx,0,0,sy,0,0)  拉伸 rotate(θ)对应matrix(cosθ,sinθ,-sinθ,cosθ,0,0)  旋转 skew(θx,θy)对 ...

  7. Codevs 3990 中国余数定理 2

    3990 中国余数定理 2 时间限制: 1 s 空间限制: 1000 KB 题目等级 : 白银 Silver 传送门 题目描述 Description Skytree神犇最近在研究中国博大精深的数学. ...

  8. STUN/TURN/ICE协议在P2P SIP中的应用(一)

    1           说明 本文详细描述了基于STUN系列协议实现的P2P SIP电话过程,其中涉及到了SIP信令的交互,P2P的原理,以及STUN.TURN.ICE的协议交互 本文所提到的各个服务 ...

  9. zoj 3686 A Simple Tree Problem (线段树)

    Solution: 根据树的遍历道的时间给树的节点编号,记录下进入节点和退出节点的时间.这个时间区间覆盖了这个节点的所有子树,可以当做连续的区间利用线段树进行操作. /* 线段树 */ #pragma ...

  10. 九度OJ 1081 递推数列 -- 矩阵二分乘法

    题目地址:http://ac.jobdu.com/problem.php?pid=1081 题目描述: 给定a0,a1,以及an=p*a(n-1) + q*a(n-2)中的p,q.这里n >= ...