如果連接了一個tcp服務器和客戶端,我想確定客戶端何時不再連接。我想我可以簡單地通過嘗試向客戶端發送消息來做到這一點,一旦send()返回-1,我就可以拆卸套接字。這個實現可以在Windows上找到,但是當我嘗試在BSD套接字的Linux上執行此操作時,服務器端應用程序對send()的調用會導致我的服務器應用程序在客戶端不再連接時崩潰。它甚至不返回-1,只是終止程序。TCP發送不會導致崩潰進程
請解釋爲什麼會發生這種情況。提前致謝!
如果連接了一個tcp服務器和客戶端,我想確定客戶端何時不再連接。我想我可以簡單地通過嘗試向客戶端發送消息來做到這一點,一旦send()返回-1,我就可以拆卸套接字。這個實現可以在Windows上找到,但是當我嘗試在BSD套接字的Linux上執行此操作時,服務器端應用程序對send()的調用會導致我的服務器應用程序在客戶端不再連接時崩潰。它甚至不返回-1,只是終止程序。TCP發送不會導致崩潰進程
請解釋爲什麼會發生這種情況。提前致謝!
這是由SIGPIPE信號引起的。見send(2)
:如果
的發送()函數將失敗:
[EPIPE] 插座關閉寫入,或者套接字連接模式和不再連接。在後一種情況下,如果套接字的類型爲SOCK_STREAM或SOCK_SEQPACKET且MSG_NOSIGNAL標誌未設置,則會向調用線程生成SIGPIPE信號。
您可以通過使用在send()
呼叫MSG_NOSIGNAL
標誌,或在你的程序的開始忽略SIGPIPE
信號與signal(SIGPIPE, SIG_IGN)
避免這種情況。然後在這種情況下,send()
函數將返回-1並將errno
設置爲EPIPE
。
您需要忽略SIGPIPE信號。如果在套接字上發生寫入錯誤,使用SIGPIPE進行處理,並且該信號的默認行爲是終止進程。 在* nix上編寫網絡代碼您通常需要:
signal(SIGPIPE,SIG_IGN);