簡體   English   中英

異步套接字問題

[英]Asynchronous socket questions

好吧,我在這個問題中發現輪詢套接字不能擴展,所以我決定研究異步套接字,我有幾個問題。

  1. 如果我有幾百個客戶端都試圖向他們的合作伙伴發送數據,那么最好的異步方法是什么? select()poll()或者我可以在非阻塞套接字上調用recv()嗎?
  2. 當我查詢並發現有數據要讀取時,我應該生成一個線程來處理嗎?
  3. 我應該擔心任何睡眠功能,還是應該讓程序占用100%的CPU?
  4. 將整個功能集成到一個類中是否有效? 我真的想做這樣的事情:

//thread 1:  
while(!quit){  
   manager.check_clients();  
   manager.handle_clients();  
   manager.display_clients();  
 }
//thread 2:
while(!quit)
  manager.manage_admin_input();

輪詢方法的選擇取決於操作系統。 在linux上,使用epoll,最好是邊緣觸發的。 在FreeBSD上,使用kqueue。 在Windows上,使用例如WSAEventSelect和WSAWaitForMultipleEvents。

你的主循環應該只是:

for (;;) {
  epoll(); // blocking poll until an event happens, optionally with a timeout
  // iterate signaled sockets and process data
  // Other tasks
}

您是選擇在線程池中的每個線程中實現此功能,還是僅在主線程中執行一次,這取決於應用程序的其余部分。 關鍵是讓輪詢功能等待,這樣你就不會使用過多的CPU。

您可以使用非阻塞套接字或ioctl(FIONREAD...來檢查每個套接字上可讀的數據量。

我首選的套接字處理OOP設計是讓套接字完全不知道套接字輪詢器。 套接字輪詢器,隱藏用於輪詢的實際函數,將接受套接字和它應該監視的事件,在例如tick()函數中進行輪詢,然后告訴每個套接字外部監聽類有什么東西與插座。 就像是:

class SocketPoller {
public:
  void registerSocket(Socket * s, int EventMask);
  void unregisterSocket(Socket * s);
  virtual void tick() = 0;
}

class SocketPollerEPoll : public SocketPoller {
public:
  void tick() {
    epoll(...); 
    // for each socket with events:
      TheSocket->notifyReadable();
  }
};

class SocketPollerSelect : public SocketPoller {
public:
  void tick() {
    select(...); 
    // for each socket with events:
      TheSocket->notifyReadable();
  }
};

即使已經回答了這個問題,您也可以考慮將Boost.Asio用於您的通信框架。 它很好地將各種平台上的各種輪詢方法包裝成一個干凈,一致且類型安全的頭文件庫。 它成熟,得到很好的支持,並經常在SO上進行討論

您可以使用Push框架, http: //www.pushframework.com它有效地使用異步IO。 還會抽象出低級細節,以便您可以專注於應用程序的業務邏輯。

暫無
暫無

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

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