将IOCP与多个侦听器一起使用

时间:2017-03-24 13:28:43

标签: c windows sockets server iocp

如何为多个侦听器(在不同端口上)设置IOCP套接字?我在网上找到的每个例子都只是一个服务器 - 多个客户端示例,我不明白我是否应该创建多个 IOCP,或者只使用一个所有听众都以某种方式?

例如,我发现了this example on GitHub,这似乎是对Win 7 SDK中某些代码的略微修改,并且此代码为单个侦听器套接字创建了一个完整端口:

g_hIOCP = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0);

for( DWORD dwCPU = 0; dwCPU < g_dwThreadCount; dwCPU++ )
{
    ...
    // associate worker thread with this iocp
    hThread = CreateThread(NULL, 0, WorkerThread, g_hIOCP, 0, &dwThreadId);
    ...
}

如何为多个完成端口使用相同的线程池?或者我是否只需要一个完成端口用于所有侦听器套接字?

3 个答案:

答案 0 :(得分:1)

对于所有侦听器套接字,您只需要一个完成端口。以及将在此完成端口上侦听的多个线程(线程池)。也可能不直接创建完成端口和线程池,但将此任务委托给system(ntdll)。可以使用BindIoCompletionCallbackCreateThreadpoolIo

来完成此操作

所以我们有 - 单个完成端口,几个工作线程监听此端口(通常的线程数==处理器核心数)和多个文件(套接字)通过BindIoCompletionCallback或{{与此完成端口关联3}}或CreateIOCompletionPort(丑陋的逻辑 - 与内部使用的ZwSetInformationFile(..FileCompletionInformation)比较)

答案 1 :(得分:1)

初始化服务器系统时,对每个必须拥有它的端口发出AcceptEx()调用。在通常的&#39;中使用扩展的OVERLAPPED结构。方式,将侦听和客户端套接字传输到处理IO完成事件的线程。

然后,处理程序线程在执行时可以访问所有每个侦听器和每个客户端的数据,因此可以采取适当的操作。请注意,一个或两个数据项可能需要锁定和/或队列,以防止多个池线程修改数据,例如,两个客户端在同一时间连接。

每个监听器不需要完成端口/池,一个池就可以了。

处理程序线程还应为下一个要连接的客户端发出另一个AcceptEx()。

答案 2 :(得分:1)

这个帖子上的其他答案完全合法,但我相信我可以添加一些。

让我们讨论完成端口是什么,我理解它的方式。

完成端口是事件接收器。也就是说,发生事件,通知完成端口。

现在,当然有大量的事件分类。完成端口非常适合特定类型的事件:IO完成。 Cutler和Gang以一种令人惊讶的人类可读语言编写的专利描述了IOCP如何与NT内核集成。

重新封装:完成端口是一个非常适合接收IO完成通知的事件接收器。

现在让我们回到OP的问题:

  
    

如何为多个侦听器(在不同端口上)设置IOCP套接字?

  

您的活动是完成之前发出的AcceptEx()调用。它通常是客户端上的connect()调用,但也可能是某人禁用您的NIC。

首先确定是否要同时或串行处理同一端口上的连接。此外,您还需要决定是否要在不同端口上连接以同时或串行处理。

我看到了三种可能的方法:

  • 所有连接完成都已序列化

CreateIOCompletionPort提前一次,BindIOCompletionCallback为每个监听器,一个工作线程调用GetQueuedCompletionStatus作为RbMm描述

  • 同一个侦听器(在同一端口上)的连接完成被序列化,但不同端口上的连接完成是并发的

你必须为每个监听器创建一个完成端口并启动一个将要GetQueuedCompletionStatus()的工作者

  • 所有连接完成都是并发的

你可以拥有一个完成端口,但你可以启动多个线程来调用GetQueuedCompletionStatus()

如上所述,你并不一定受限制。完成端口很聪明,因此您可以使用一个端口和多个服务员,然后服务员获取每个侦听器锁以进行序列化。内核中的完成端口机制将确定您在适当时阻止并释放其他服务员。

重新开始:首先,你决定你想要的并发性。然后,您可以选择需要的完成端口数。