幾天前,我必須調查一個問題,即當我的應用程序顯然處於空閒狀態時,它顯示的CPU使用率異常高。我將問題追蹤到一個循環,該循環意圖在套接字已設置爲O_NONBLOCK
時調用recvfrom
調用,從而導致自旋鎖定。解決此問題的方法有兩種:將套接字設置爲阻塞或使用poll
或select
輪詢套接字上的可用數據。我選擇了前者,因爲它更簡單。但我想知道爲什麼有人會創建一個非阻塞套接字,然後分別進行輪詢。不是一個阻塞的套接字是不是一樣的?有人會使用非阻塞套接字和輪詢組合的用例是什麼?在一般情況下它有什麼優點嗎?帶輪詢的非阻塞套接字
回答
使用poll()
或select()
與非阻塞文件描述符爲您提供了兩個優點:
- 您可以設置超時阻塞;
- 您可以等待文件描述符集集合中的任何一個變爲可用。
如果您只有一個文件描述符(套接字)需要等待,並且您不介意在其上無限期等待,那麼是的;你可以使用阻塞呼叫。
第二個優勢實際上是select()
和朋友的殺手級用例。這意味着您可以處理多個套接字連接,以及標準輸入和標準輸出以及可能的文件I/O,所有這些都通過單個控制線程來完成。
導致自旋鎖定。
這種情況通常稱爲緊密環。
解決此問題的方法有兩種:將套接字設置爲阻塞或使用poll或select在套接字上輪詢可用數據。我選擇了前者,因爲它更簡單。
確定,其他的部分代碼沒有使用過poll()
(或select()
),並期望socket爲非阻塞模式?
否則,是的,切換到阻塞模式是最簡單的解決方案。
最佳向後兼容的解決方案將一直呼籲recvfrom()
使用poll()
等待插座成爲可讀的之前。這樣可以確保代碼的其他部分能夠像以前一樣精確地工作。
但我想知道爲什麼有人會創建一個非阻塞套接字,然後單獨輪詢它。不是一個阻塞的套接字是不是一樣的?
對於recvfrom()
的情況,我沒有什麼大的區別。
有人會使用非阻塞套接字和輪詢組合的用例是什麼?在一般情況下它有什麼優點嗎?
可能是一個簡單的編碼錯誤。或者有人可能會認爲在緊縮環節中調整會以某種方式提高性能。
將套接字編號爲nonblocking
總是比較好,因爲即使阻塞的套接字有時(即當數據到達但有校驗和錯誤並且被丟棄時)也處於就緒狀態 - 即使沒有要讀取的數據。因此,使它nonblocking
,通過查詢等待數據可用性然後讀取。我認爲這是主要優勢。
我在這裏發帖,因爲雖然問題是舊的。它出現在我的谷歌搜索不知何故,並沒有得到妥善回答。
接受的答案僅僅強調了使用非阻塞套接字的兩個優點,但沒有真正詳細說明或回答實際問題。
- 注:在非阻塞套接字不幸的是大多數在線「教程」或代碼片段只攔截功能套接字代碼,所以知識傳播較少。
至於什麼時候你會使用一個與另一個相比......一般情況下,阻塞套接字只用於在線代碼片段。在所有(良好)生產應用中都使用非阻塞式插座。我不是無知的,如果你知道一個使用阻塞套接字的實現(並且確定這個套接字可以很好地與線程結合) - 或者讓我們更具體的在單線程中使用阻塞套接字 - 請讓我們我知道。
現在我可以給你一個很容易理解的例子,還有很多其他的例子。我們來看一個遊戲服務器的例子。無論玩家是否提供輸入(鼠標/鍵盤)來改變遊戲狀態,遊戲都會在蜱中前進,遊戲狀態會持續一段時間。現在,當多人遊戲中的套接字發揮作用時 - 如果您要使用阻塞套接字,除非玩家發送更新,否則遊戲狀態不會提前 - 因此,如果他們遇到互聯網問題,遊戲狀態將永遠不會持續更新並向所有玩家傳播更改。你會有一個相當不穩定的經歷。
現在使用非阻塞套接字,您可以在單線程上運行遊戲服務器,更新遊戲狀態以及套接字,使用...讓我們說50ms超時間隔 - 套接字數據只讀來自連接的用戶,當他們真正發送一些東西時,然後送入服務器模擬,處理並饋送到下一個打勾的遊戲狀態計算中。
- 1. 帶選擇的非阻塞套接字
- 2. select()在非阻塞套接字上VS「手動輪詢」
- 3. 阻塞套接字性能與非阻塞套接字
- 4. 非阻塞套接字
- 5. pyzmq非阻塞套接字
- 6. 非阻塞python套接字
- 7. PHP非阻塞套接字
- 8. 在阻塞連接之後設置非阻塞的套接字
- 9. Python中的非阻塞套接字?
- 10. c中的非阻塞套接字
- 11. 服務器的非阻塞套接字
- 12. 代理中的非阻塞套接字和輪詢()怪癖 - 新手
- 13. 使用select與阻塞和非阻塞套接字的影響
- 14. 非阻塞服務器套接字(linux)
- 15. 加速非阻塞Unix套接字(C++)
- 16. 關閉非阻塞套接字通道
- 17. 選擇非阻塞套接字
- 18. OCaml:Lwt和非阻塞套接字
- 19. SSL和NIO非阻塞套接字
- 20. sendfile()完成到非阻塞套接字
- 21. recv與非阻塞套接字
- 22. 多線程與非阻塞套接字
- 23. 簡單套接字非阻塞I/O
- 24. Android非阻塞從套接字讀取
- 25. 非阻塞套接字和發送()
- 26. 非阻塞套接字,錯誤總是
- 27. C/C++套接字和非阻塞recv()
- 28. 非阻塞套接字和io
- 29. 非阻塞式TCP套接字編程
- 30. 套接字:非阻塞關機(SHUT_WR)?
不要'select'和'poll'通過通知您某個特定操作**在您執行該操作時不會阻止**來緩解阻塞問題?這些優秀的生產應用程序是否仍禁用阻止? – TheBuzzSaw 2017-09-07 18:53:45
@ TheBuzzSaw我不確定我是否理解這個問題。我們在這裏排除了單個套接字的用法,所以你有一套你每次使用的文件描述符,它不是select,而是實際的recv調用塊,等待數據被接收。 – 2017-09-07 20:08:10
我在說,當一個程序使用'select'來複用十幾個套接字時,通常沒有必要將這些套接字放入非阻塞模式,因爲調用'select'可以確定哪些動作不會被阻塞。如果'select'返回並告訴我'45'套接字不會阻塞讀取,我可以調用'recv'而不用擔心阻塞,對吧? – TheBuzzSaw 2017-09-07 22:10:24