對一個對端已經關閉的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(SIGPIPE, SIG_IGN);
這樣, 第二次調用write方法時, 會返回-1, 同時errno置爲SIGPIPE. 程序便能知道對端已經關閉.