在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