异步套接字问题

发布于 2024-10-20 12:19:33 字数 563 浏览 3 评论 0原文

好吧,我在 this 问题中发现轮询套接字无法扩展,所以我决定研究异步套接字,我有几个问题。

  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();

Alright, I found out in this question that polling sockets does not scale, so I've decided to look into asynchronous sockets, and I have several questions.

  1. If I have several hundred clients all trying to send data to their partner, what would be the best async method to use? select() poll() or can I just call recv() on a non-blocking socket?
  2. When I poll and find there is data to read, should I spawn a thread to take care of it?
  3. Should I worry about any sleep function, or should I just let the program take 100% CPU?
  4. Would it be efficient at all to put this whole functionality into a class? I would really like to do something like this:

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

始终不够 2024-10-27 12:19:33

轮询方法的选择取决于操作系统。在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();
  }
};

The choice of polling method is OS dependent. On linux, use epoll, preferrably edge-triggered. On FreeBSD, use kqueue. On Windows, use e.g. WSAEventSelect and WSAWaitForMultipleEvents.

Your main loop should simply be:

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

Whether you choose to implement this in each thread in a thread pool, or just once in the main thread, is dependent on the rest of your application. The key is to let the polling function do the wait, this way you won't use excessive CPU.

You can either use non-blocking sockets, or ioctl(FIONREAD... to check how much data is readable on each socket.

My preferred OOP design for socket handling is to make a socket completely unaware of the socket poller. A socket poller, hiding the actual function used for polling, would accept sockets and the events it should watch for, do it's polling in e.g. a tick() function, then tell each socket or an external listening class that there's stuff to do with the socket. Something like:

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();
  }
};
滥情稳全场 2024-10-27 12:19:33

即使这个问题已经得到解答,您也可以考虑使用 Boost.Asio 用于您的通信框架。它很好地将各种平台上的各种轮询方法包装成一个干净、一致且类型安全的仅标头库。它很成熟,得到很好的支持,并且经常讨论

Even though this question has already been answered, you might consider using Boost.Asio for your communication framework. It nicely wrappers the various polling methods on a variety of platforms into a clean, consistent, and type-safe header only library. It is mature, well supported, and discussed on SO frequently.

奈何桥上唱咆哮 2024-10-27 12:19:33

您可以使用 Push 框架, http://www.pushframework.com 它有效地使用异步 IO。还可以抽象低级细节,以便您可以专注于应用程序的业务逻辑。

You can use Push framework, http://www.pushframework.com It uses asynchronous IOs efficiently. Also would abstract the low-level details so you can concentrate on the business logic of your app.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文