IOCP:内核如何决定同步或异步完成 WSASend?

Posted

技术标签:

【中文标题】IOCP:内核如何决定同步或异步完成 WSASend?【英文标题】:IOCP: how does the kernel decide to complete WSASend synchronously or asynchronously? 【发布时间】:2014-11-03 02:44:29 【问题描述】:

我们编写了利用 I/O 完成端口的软件,并在 SOCKET 对象上使用 WSASend,在命名管道上使用 WriteFile。

在这两种情况下,我们发现这些 API 返回 SOCKET_ERROR / WAS_IO_PENDING [1] 的时间比我们预期的要快得多(或命名管道 WriteFile 操作的等价物)。

似乎我们错误地假设如果我们填满发送缓冲区(CreateNamedPipe 中的 nInBufferSize)会触发异步完成,相反它似乎更具侵略性并且与发送缓冲区的大小无关。对于套接字和命名管道,如果足够快,大发送缓冲区(100k+)和小消息(几个字节)总是会在第二次写入时异步完成。

谁能证实这一点?有没有人知道 Windows 实现在决定何时异步完成 I/O 操作时遵循的启发式信息,而不是同步完成?

[1] "如果重叠操作成功启动并稍后完成,WSASend 返回 SOCKET_ERROR 并指示错误代码 WSA_IO_PENDING。" - http://msdn.microsoft.com/en-us/library/windows/desktop/ms742203(v=vs.85).aspx

【问题讨论】:

此类实施细节可能会发生变化。您需要确保您的代码不包含任何关于它们的假设。 【参考方案1】:

为什么你认为你需要知道或关心。它不是 API 的记录部分,它可能受到当时堆栈中的驱动程序和任何分层服务提供程序的影响。

您必须编写正确的代码来处理成功的“同步”发送或待处理的“异步”发送,那么这对您获得这两种结果的频率有何影响?

此外,除非您使用 SetFileCompletionNotificationModes() 启用 FILE_SKIP_COMPLETION_PORT_ON_SUCCESS,否则同步和待处理结果使用相同的代码路径。

【讨论】:

以上是关于IOCP:内核如何决定同步或异步完成 WSASend?的主要内容,如果未能解决你的问题,请参考以下文章

socket通讯IOCP模型

技术派-epoll和IOCP之比较

同步与异步IO && blocking 与nonblocking 原理

同步与异步IO && blocking 与nonblocking 原理

理解I/O Completion Port(完成端口)(转载)

Java NIO(New IO)