關於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

相關文章
相關標籤/搜索