在Windows上的multithreading应用程序中阻塞服务器/侦听套接字的最佳方法?

我正在Windows上编写一个TCP服务器/客户端应用程序,以熟悉Winsock API。 我来自UNIX背景,想知道哪些是实现应用程序的最佳方法:

首先是规范

  • 必须在多处理器和单处理器系统上良好地扩展。
  • 没有硬连接的限制。
  • 应用程序既可以监听连接,充当服务器,也可以充当客户端。
  • multithreading

第一种方法

  • 在“服务器”线程中用于监听的非阻塞select式套接字
  • 为每个客户端连接我们产生一个单独的线程。

第二种方法

  • 在“服务器”线程中阻塞用于监听的套接字。
  • 为每个客户端连接我们产生一个单独的线程。

第三种方法

  • 在“服务器”线程中用于监听的非阻塞select式套接字。
  • 没有单独的线程为每个传入的连接,协议将需要状态信息跨会议我保留。

我不知道什么是最有效和可扩展的方法,特别是如果它也可以使用UDP套接字。

注意:我在纯C和旧C中编写应用程序。不涉及.NET和C ++,也禁用C ++exception。

正如Gary所说,I / O完成端口是在Windows平台上以非阻塞/异步方式管理多个网络连接的最有效方法。

使用IOCP,当网络操作完成时,您会收到通知,您可以使用少量的线程处理这些完成。 您可以决定分配多少个线程来处理完成,内核决定何时使用您提供的线程。 它以LIFO顺序使用它们来减少上下文切换,所以如果你只使用最少的线程数量,而且你重复使用相同的线程,而不是循环遍历所有可用的线程使用。

IOCP编程的异步特性可能会有点混乱,但一旦你掌握了它,它就相当简单了。

我有一些免费的IOCP服务器代码,演示了基础知识,并提供了一些很容易构建的示例服务器。 你可以在这里找到代码: http : //www.serverframework.com/products—the-free-framework.html 。 该页面也链接到我写的一些文章来解释代码。

将此与您的问题的细节相关联。 你应该看看你的第三种方法的变化。 使用AcceptEx()接受新的连接,这可以以异步的方式使用,所以你不需要一个单独的线程来接受连接,并且可以使用也处理重叠/异步读写操作的线程。

我写了一个不使用阻塞套接字的异步客户端,所以如果你对这种方法感兴趣,那么看看我的客户端: http : //codesprout.blogspot.com/2011/04/asynchronousous-http- client.html

这是一个HTTP客户端,但是我已经在那里显示了很少的HTTP协议处理,这只是.NET套接字。 服务器将以类似的方式工作:您可以利用诸如AsseptAsync Async方法。

在Windows下,使用I / O完成调用可以获得最好的性能。

这是因为列表和排队机制是在内核中完成的,远离了大量的用户模式开销(如果你敢自己努力工作,则会拖累你的代码)。

不幸的是,Windows I / O完成调用需要分配许多线程来进行扩展,这很快就会导致性能下降(与可以独立于决定参与任务的工作线程数量进行扩展的Linux epoll相比)。

最近,我发现http://gwan.com/是一个来自Windows的Web服务器,然后在Linux下移植。 他们的作者在他们的论坛上详细描述了这个问题。