簡體   English   中英

帶有輪詢的非阻塞套接字

[英]Non-blocking socket with poll

幾天前,我不得不調查我的應用程序在(顯然)處於空閑狀態時顯示異常高CPU使用率的問題。 我將問題追溯到一個循環,這個循環意味着在套接字被設置為O_NONBLOCK -ing時阻止recvfrom調用,從而導致旋轉鎖定。 有兩種方法可以解決問題:使用pollselect將套接字設置為阻塞或輪詢套接字上的可用數據。 我選擇前者因為它更簡單。 但我想知道為什么任何人會創建一個非阻塞套接字然后單獨輪詢它。 阻塞套接字是否也這樣做? 使用非阻塞套接字和輪詢組合的用例有哪些? 在一般情況下它有什么優勢嗎?

poll()select()與非阻塞文件描述符一起使用會帶來兩個好處:

  • 您可以設置阻止超時;
  • 您可以等待任何一文件描述符變得可用。

如果你只有一個文件描述符(套接字)要等待,而你不介意無限期地等待它,那么是; 你可以使用阻止通話。

第二個優勢實際上是select()和朋友的殺手級用例。 這意味着您可以處理多個套接字連接,以及標准輸入和標准輸出以及可能的文件I / O,所有這些都具有單個控制線程。

我在這里發帖,因為雖然問題很老。 它以某種方式出現在我的谷歌搜索中,並且肯定沒有得到正確回答。

接受的答案僅突出了使用非阻塞套接字的兩個優點,但並沒有真正詳細說明或回答實際問題。

  • 注意:不幸的是,大多數在線“教程”或代碼片段僅具有阻塞套接字代碼,因此對非阻塞套接字的了解較少。

至於你何時使用一個與另一個相比...一般來說,阻塞套接字僅用於在線代碼片段。 在所有(良好)生產應用中,使用非阻塞套接字。 我不是一無所知,如果你知道一個使用阻塞套接字的實現(並且確定這很可能與線程組合) - 或者讓我們更具體一點,在單個線程中使用阻塞套接字 - 請讓我們我知道。

現在我可以給你一個非常容易理解的例子,那里還有很多其他的例子。 我們以游戲服務器為例。 無論玩家是否提供輸入(鼠標/鍵盤)來改變游戲狀態,游戲都會在游戲狀態進行的定期間隔內前進。 現在當套接字在多人游戲中發揮作用時 - 如果你使用阻塞套接字,除非玩家發送更新,否則游戲狀態不會發展 - 所以如果他們有互聯網問題,游戲狀態永遠不會一直更新並傳播給所有玩家的變化。 你會有一個相當不穩定的經歷。

現在使用非阻塞套接字,您可以在單線程上運行游戲服務器,更新游戲狀態以及套接字,使用...假設50毫秒超時間隔 - 並且套接字數據僅在連接用戶時讀取他們實際上發送了一些東西,然后進入服務器模擬,處理並輸入到下一個滴答的游戲狀態計算中。

導致旋轉鎖定。

這種情況通常被稱為緊密循環

有兩種方法可以解決問題:使用poll或select將套接字設置為阻塞或輪詢套接字上的可用數據。 我選擇前者因為它更簡單。

你確定其他代碼部分還沒有使用poll() (或select() )並期望套接字處於非阻塞模式嗎?

否則,是的,切換到阻止模式是最簡單的解決方案。

最好的向后兼容解決方案是在調用recvfrom()之前使用poll()來等待套接字變得可讀。 這樣可以確保代碼的其他部分可以像以前一樣精確地工作。

但我想知道為什么任何人會創建一個非阻塞套接字然后單獨輪詢它。 阻塞套接字是否也這樣做?

對於recvfrom()的情況,我不知道主要的區別。

使用非阻塞套接字和輪詢組合的用例有哪些? 在一般情況下它有什么優勢嗎?

可能是一個簡單的編碼錯誤。 或者有人可能認為在緊密循環中重新調整會以某種方式提高性能。

最好將套接字設置為nonblocking因為即使阻塞套接字有時也會變為就緒狀態(當數據到達但有校驗和錯誤而被丟棄時) - 即使沒有數據要讀取。 因此,使其nonblocking ,通過輪詢等待數據可用性然后讀取。 我認為這是主要優勢。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM