天天看點

linux中send函數MSG_NOSIGNAL異常消息

最近2周在做 ineedle 的國舜項目擴充,需要使用 socket 的 tcp 連接配接向對方發送消息,當然需求很簡單,隻是按照對方要求發送指定格式的消息,程式結構也非常的簡單,一對多的 client/server 模型,ineedle 發送給多個伺服器消息。我們這邊在分析出結果,封裝為相應格式消息後發送給對方,隻需要線上程循環發送消息即可,便在測試環境中編寫簡單的socket進行模拟消息發送,一對一發送,能夠正常發送消息。可以遇到了一個棘手的問題:在伺服器端用ctrl+c 來結束伺服器接收程序來模拟伺服器當機的情況,結束服務 socket 程序之後,服務端自然關閉程序,可是 client 端也竟然出乎意料的關閉掉。

這就奇怪了,我在服務端關閉程序,伺服器會關閉 tcp 連接配接,向 client 發送FIN包,client 響應 ack 後,等雙向 tcp 連接配接關閉後,tcp 連接配接徹底關閉,在 client 端發送消息會失敗,傳回錯誤資訊,錯誤消息會被正常的列印出來,可是很多時候錯誤資訊都沒有列印( write 函數沒有傳回),有時候傳回了錯誤資訊,但是 client 端程序仍然無辜死掉,我的 client 端可是用的 while(1) 死循環啊,怎麼可能。于是乎百度了一番,說法千奇百怪,有說防火牆的問題,關閉防火牆仍然如此。郁悶 ing,測試了其它方法都不行,列印出錯誤錯誤碼,也沒有查詢到結果。

最後問了下我們的張總,問題剛給他說完,他便說他以前也遇到這個問題,給我找到了他以前的解決方案。解決方法是使用 send 函數時候在最後一個參數上加 MSG_NOSIGNAL 标記即可。于是自己更改發送函數 write 為 send 并添加 MSG_NOSIGNAL 标志,重新編譯,運作,中斷 server,果然這個問題被很潇灑的解決了,感謝張總的英明神武。

參考一個博文的介紹

Linux 下當連接配接斷開,還發送資料的時候,不僅 send() 的傳回值會有反映,而且還會向系統發送一個異常消息,如果不作處理,系統會出 BrokePipe,程式會退出,這對于伺服器提供穩定的服務将造成巨大的災難。為此,send() 函數的最後一個參數可以設定為 MSG_NOSIGNAL,禁止 send() 函數向系統發送常消息。

繼續閱讀