在编写一个Win32服务器时,我已经阅读了很多关于完成端口和重叠I / O的信息,但是我没有看到任何建议,哪些API的产出在服务器上获得最好的结果。
我应该使用完成例程,还是应该使用WaitForMultipleObjects API,为什么?
当您发出重叠操作时,例如WSARecv(),您可以指定一个包含事件的OVERLAPPED结构,您可以等待该事件发出信号,以指示重叠的I / O已完成。这个,我假设是你的WaitForMultipleObjects()方法,并且如前所述,这不能很好地扩展,因为你被限制到可以传递给WaitForMultipleObjects()的句柄数。
或者,您可以传递完成例程,在完成发生时调用。这被称为“alertable I / O”,并且要求发出WSARecv()调用的线程处于调用完成例程的“alertable”状态。线程可以通过多种方式将其置于警报状态(调用SleepEx()或等待功能的各种EX版本等)。我在我面前打开的Richter book表示:“我已经与可信的I / O进行了很多工作,我将首先告诉你,可信的I / O是可怕的,应该避免的”。足够说IMHO
有第三种方法,在发出呼叫之前,您应该将要重叠的I / O的句柄与完成端口相关联。然后,通过调用GetQueuedCompletionStatus()和循环来创建一个服务于此完成端口的线程池。您使用OVERLAPPED结构发出WSARecv(),其中没有事件,当I / O完成在您的一个I / O池线程上弹出GetQueuedCompletionStatus()时,可以在那里处理。
如前所述,Vista / Server 2008已经清理了IOCP如何工作,并删除了这个问题,您必须确保发出重叠请求的线程在请求完成之前继续运行。链接到这个参考可以找到here.但这个问题很容易解决;您只需使用与完成功能相同的IOCP将WSARecv组织到您的一个I / O池线程中…
无论如何,使用IOCP的IMHO是进行重叠I / O的最佳方式。是的,让你的头部绕过重叠/异步性质的电话可能需要一点时间在一开始,但它是非常值得的,因为系统扩展得很好,并提供一个简单的“火和忘记”的方式来处理重叠的操作。
如果您需要一些示例代码来帮助您,那么我有几篇关于编写IO完成端口系统和一堆免费代码的文章,为高性能服务器提供了真实的框架;见here。
放在一边呃,你真的应该看到Jeffrey Richter和Christophe Nasarre的“Windows Via C/C++ (PRO-Developer)”,因为它需要知道重叠的I / O和大多数其他高级Windows平台技术和API。