socket的sigpipe信號

對一個對端已經關閉的socket調用兩次write,第一次將會收到隊端的RST響應, 第二次將會生成SIGPIPE信號, 該信號默認結束進程.

具體的分析可以結合TCP的"四次握手"關閉. TCP是全雙工的信道, 可以看作兩條單工信道, TCP連接兩端的兩個端點各負責一條. 當對端調用close時, 雖然本意是關閉整個兩條信道, 但本端只是收到FIN包. 按照TCP協議的語義, 表示對端只是關閉了其所負責的那一條單工信道, 它仍然可以通過另外一條信道繼續接收數據. 也就是說, 因爲TCP協議的限制, 一個端點無法獲知對端的socket是調用了close還是shutdown.

對一個已經收到FIN包的socket調用read方法, 如果接收緩衝已空, 則返回0, 這就是常說的表示連接關閉. 但第一次對其調用write方法時, 如果發送緩衝沒問題, 會返回正確寫入(發送). 但發送的報文會導致對端發送RST報文, 因爲對端的socket已經調用了close, 完全關閉, 既不發送, 也不接收數據. 所以, 第二次調用write方法(假設在收到RST之後), 會生成SIGPIPE信號, 導致進程退出.

爲了避免進程退出, 可以捕獲SIGPIPE信號, 或者忽略它, 給它設置SIG_IGN信號處理函數:

signal(SIGPIPESIG_IGN);

這樣, 第二次調用write方法時, 會返回-1, 同時errno置爲SIGPIPE. 程序便能知道對端已經關閉.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章