关于linux error, broken pipe 和 connection reset by peer的区别

在linux网络编程中,咱们常常会遇到这两个错误。这两个错误出现的状况有些相似,又有些不一样。先看下glibc对于这两个错误的描述:linux

#. 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 ""

broken pipe:编程

broken pipe只出如今调用write的时候。broken pipe的意思是对端的管道已经断开,每每发生在远端把这个读/写管道关闭了,你没法在对这个管道进行读写操做。从tcp的四次挥手来说,远端已经发送了FIN序号,告诉你我这个管道已经关闭,这时候,若是你继续往管道里写数据,第一次,你会收到一个远端发送的RST信号,若是你继续往管道里write数据,操做系统就会给你发送SIGPIPE的信号,而且将errno置为Broken pipe(32),若是你的程序默认没有对SIGPIPE进行处理,那么程序会中断退出。通常状况下,能够用signal(SIGPIPE,SIG_IGN)忽略这个信号,这样的话程序不会退出,可是write会返回-1而且将errno置为Broken pipe(32)。broken pipe只会出如今往对端已经关闭的管道里写数据的状况下(在收到对端的RST序号后第一次写不会出现broke pipe,而是write返回-1,这时候正确的作法应该是本端也close这个管道,若是继续write,那么就会出现这个错误)。网络

tcpdump截包状况以下:less

connection reset by peer:tcp

connection reset by peer在调用write或者read的时候都会出现。按照glibc的说法,是such as by the remote machine rebooting or an unrecoverable protocol violation。从字面意义上来看,是表示远端机器重启或者发生不可恢复的错误。从个人测试来看,目前只出如今对端直接kill掉进程的状况。这两种状况有什么不一样呢?对比tcpdump的截包图来看,直接kill掉远端进程的话,远端并无发送FIN序号,来告诉对方,我已经关闭管道,而是直接发送了RST序号,而远端若是调用close或者shutdown的话,是会发送FIN序号的。按照TCP的四次挥手来看,是须要FIN这个序号的。我的猜想,若是在本端没有收到对方的FIN序号而直接收到了RST序号的话,代表对端出现了machine rebooting or an unrecoverable protocol violation,这时候对这个管道的IO操做,就会出现connection reset by peer错误。ide

 tcpdump截包状况以下:测试

 

补充一下tcp的三次握手和四次挥手的过程图片,帮助理解:this

 

 若是有不对的地方,望指正~spa

相关文章
相关标签/搜索