用于小型单线程应用程序的 I/O 完成端口?
Posted
技术标签:
【中文标题】用于小型单线程应用程序的 I/O 完成端口?【英文标题】:I/O Completion Port for small-scale, single-threaded applications? 【发布时间】:2014-09-24 15:41:44 【问题描述】:让我先说一下我从来没有使用过 I/O 完成端口,尽管我已经听说了很多年了。我的背景主要是select
、poll
、epoll
和WSAEventSelect
以及WaitForMulitpleObjects
。如果我对以下文本中的 I/O 完成端口有根本的误解,请纠正我。
作为工作项目的一部分,我的任务是为模拟开发一个插件 (DLL),它允许客户端连接到插件并通过 TCP 向/从模拟发送/接收数据。该插件充当服务器。该仿真模拟了不同(不是以太网)接口的通信通道,在这个特定的应用程序中,每个通道都有一个套接字是有意义的。我不知道会有多少个客户端,或者每个客户端会打开多少个通道(套接字)。不过,我知道完全有可能超过 64 个,而且不会是一个特别大的数字,最多可能不到一千。
模拟的一个重要方面是插件仅在其test_cycle
函数被调用时才允许工作。在每个测试周期中,我需要:
-
接受来自客户端的任何新连接
从套接字接收数据并将其转发到模拟
从模拟接收数据并将其转发给客户端
由于可能有超过 64 个套接字,我不能(轻松)使用 WSAEventSelect
和 WSAWaitForMultipleEvents
来检查是否可以读取套接字,或者客户端是否已正常终止连接。
所以我想到了另外两种方法可以做到这一点。
让每个套接字都是非阻塞的。每次调用test_cycle
时,循环遍历所有套接字,尝试接收每个套接字的最大数据量。
使用 I/O 完成端口并从套接字发出异步接收。在test_cycle
中,重复调用GetQueuedCompletionStatus
并将dwMilliseconds
参数设置为0
,直到指示超时(WAIT_TIMEOUT
?)。如果发生接收,请将下一次接收调用推迟到测试周期结束,这样客户端向服务器发送垃圾邮件就不会导致我们在test_cycle
中无限循环(希望如此)。
模拟的接口不是线程安全的,将数据转发到模拟的处理工作很少,所以我认为为 I/ 设置工作线程不会有任何好处O 完成端口,它只会做一个锁定并调用模拟 API。但是,不必轮询每个套接字可能会带来更好的性能。
因此,对于这种规模的应用程序,最多少于 1000 个套接字,通常少于 100 个,使用 I/O 完成端口增加的复杂性是否有任何真正的好处?
【问题讨论】:
当您不想提高速度和吞吐量时,请使用 ICOP。一个很好的描述在这里***.com/questions/754068/… 我已经决定,对于这个插件的第一个版本,每次test_cycle
迭代只轮询一次套接字会更快。然后可以根据实际场景对代码进行分析,并在必要时重新编写以使用 IOCP。我宁愿实施一个可以工作的第一个版本,也不愿强迫人们等待更长的时间来等待一个 IOCP 版本,它甚至可能不会(很多)更快。
【参考方案1】:
我认为你可以这样做: 1)建立一个监听线程。为每个连接发送一个套接字副本到线程池; 2) 建立线程池来处理请求;
我使用管道在线程之间进行传输,而不使用 I/O 完成端口,并且性能非常出色。
设置控制限制,确保资源不被耗尽。
【讨论】:
以上是关于用于小型单线程应用程序的 I/O 完成端口?的主要内容,如果未能解决你的问题,请参考以下文章