2013-04-25 53 views
4

我必須使用unix套接字(不帶O_NONBLOCK)爲類編寫一個聊天客戶端 - 服務器,併爲它們選擇異步I/O。目前,在服務器上,我從客戶端讀取1024個字節,並直接處理它。避免在不使用O_NONBLOCK時發送阻止

例如,如果有消息,我將收到格式爲MSG <msg>(表示客戶端發送消息)的命令,我將瀏覽所連接客戶端的所有套接字並將消息寫入它們。

這種方法實際上可行,但我最近通過閱讀send的人發現,如果套接字緩衝區已滿並且在套接字上未設置標誌O_NONBLOCK,它可能會阻止。

我認爲,當一個客戶端不讀取某些原因(崩潰,竊聽等),因爲它基本上會阻塞,直到該客戶再次閱讀這將是我的服務器的關鍵可能發生這個問題。

因此,這裏是我的問題:

什麼是可能阻塞的插座上,正確的方法,以避免發送阻止如果套接字緩衝區滿了嗎?

我目前使用只選擇以檢查是否有東西在插座讀,但也許我應該用它也能看到,如果我能在一個特定的插座寫呢?還有,我可以知道有多少字節我可以讀/寫選擇返回時?例如,如果選擇「告訴」我可以在此套接字上編寫代碼,那麼在寫入此套接字之前,我怎麼能知道最多可以寫入多少個字節,實際上會阻塞?

謝謝。

+2

你的問題體現在用詞上逆勢。你想非阻塞的行爲,但你不想插座設置成非阻塞模式。不是一個真正的問題。 – EJP 2013-04-25 10:20:49

+0

send()':)使用MSG_DONTWAIT標誌將它與select結合起來是個不錯的主意,所以當緩衝區已滿時,你不會忙於循環發送。 – thuovila 2013-04-25 11:11:04

+0

這正是O_NONBLOCK的用途。是否有任何理由不將描述符設置爲O_NONBLOCK? – nos 2013-08-05 10:18:59

回答

0

您可以使用setsockopt()SO_SNDTIMEO一起設置最大時間量send()將嘗試執行其工作。

有關詳細信息,請參見man setsockoptman 7 socket

0

這可能是可怕的。如果您不進入NONBLOCK-ing模式並調用select()方法,該方法會在內部使進程進入睡眠狀態達到特定的超時值。這意味着,fd將在特定時間段內被阻止。

0

這種方法實際上工作,但我最近發現通過閱讀發送的人,它可以阻止,如果套接字緩衝區已滿並且標誌O_NONBLOCK未在套接字上設置。

這就是爲什麼你選擇使用,但它仍然是不可靠的,因爲man select狀態:

在Linux下,選擇()可能會報告套接字文件描述符爲「讀就緒」,儘管如此,隨後的讀取塊。例如,當數據有 到達但檢查錯誤的校驗和被丟棄時,可能會發生這種情況。在其他情況下,文件描述符被虛假地報告爲就緒。因此它可能更安全,以便在不應阻塞的套接字上使用O_NONBLOCK。

相關問題