在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