【发布时间】:2014-05-02 06:57:37
【问题描述】:
我正在使用SetFileCompletionNotificationModes() API 来优化我的 I/O 完成端口循环,但它似乎无法正常工作。
即使我为套接字和 HANDLE 设置了 FILE_SKIP_COMPLETION_PORT_ON_SUCCESS,如果 ReadFile() WriteFile() WSARecv() WSASend() 确实返回 synchronosly,仍然会调用 I/O 端口的完成回调。
我确定 MSDN 所说的 3 个条件必须为真(完成端口与文件句柄相关联,文件已为异步 I/O 打开文件,请求立即返回成功而不返回 ERROR_PENDING),并且都是真的,那为什么我仍然会收到 I/O 完成调用?
当我调用SetFileCompletionNotificationModes() 时,它返回成功,所以没有错误或任何错误,系统是 Windows 7。
当我在我的套接字/HANDLE 上激活SetFileCompletionNotificationModes() 后,我可以清楚地看到 I/O 完成回调不会被调用时,如何复制一个场景?
我猜是当我在套接字上写入几个字节时会发生这种情况,因为套接字的缓冲区很大,我没有把它填满,所以另外几个字节的另一个写入不应该阻塞,因为还有很多缓冲区中的空间,所以它应该立即返回,但不是 ERROR_IO_PENDING,只是以同步方式,对吧? (或多或少,以类似于 unix EWOULDBLOCK/EAGAIN 的方式:当我为几个字节调用 write() 时,它会立即返回,并且不会返回 EAGAIN,因为写入缓冲区中仍有空间)。
好吧,它不会那样做。即使在一个套接字上多次写入几个字节,它仍然调用 I/O 完成回调,避免设置 FILE_SKIP_COMPLETION_PORT_ON_SUCCESS 的好处
我错过了什么重要的东西吗?有什么线索吗?
注意:我知道如果套接字仅与返回可安装文件系统 (IFS) 句柄的分层服务提供程序 (LSP) 兼容,这将不起作用,但这不是我的情况,它应该起作用。 顺便说一句,我也在尝试使用管道和文件。
文件不应该永远不会调用 I/O 完成回调,因为它们永远不会阻塞,就像 unix 中的 read() 和 write() 调用本地文件永远不会返回 EWOULDBLOCK/EAGAIN,所以 ReadFile() 和 WriteFile() 带有用 FILE_SKIP_COMPLETION_PORT_ON_SUCCESS 设置的句柄应该立即返回吗?
【问题讨论】:
-
显示关联完成端口并调用 SetFileCompletionNotificationModes() 的代码。我预计您的代码中存在错误...
-
好吧,为了确定这不是一个错误,我将再次检查代码并进行更多测试。现在它适用于命名管道,但不适用于 tcp/udp 套接字。顺便说一句,基本上代码是
if (pSetFileCompletionNotificationModes != 0) pSetFileCompletionNotificationModes(handle, flags);
标签: c++ sockets winapi io iocp