WSARecv()documentation表示有关lpNumberOfBytesRecvd参数的以下内容:



我正在使用IOCP,因此lpOverlapped不能为NULL,同时WSARecv()可以立即完成。因此,如果WSARecv()立即完成,如果lpNumberOfBytesRecvdNULL,我应该如何知道读取了多少字节?还是文档只是意味着我可以将NULL用作lpNumberOfBytesRecvd,但不必这样做?

最佳答案

当重叠的WSARecv()IO_PENDINGSUCCESS完成时,将完成数据包排队到IOCP,请参见this MSDN article for details

在Vista或更高版本中,您可以通过为套接字调用 SetFileCompletionNotificationModes() 并传递FILE_SKIP_COMPLETION_PORT_ON_SUCCESS来更改此设置(请注意,您可以在文档中将File as Socket读取为文件,文件句柄的概念直接转换为套接字)。

如果您确实启用了完成端口跳过功能,则当WSARecv()立即返回数据时(即SUCCESS返回而不是IO_PENDING返回),则您必须直接在WSARecv()调用站点进行处理,因为您将不会获得完成数据包。

请注意,启用“跳过完成端口”处理对于减少上下文切换非常有用,但是您现在确实需要以两种方式处理完成,要么直接(当WSARecv()返回SUCCESS时),要么在常规完成处理程序中(当WSARecv()返回错误且错误是IO_PENDING)。之前,这两个结果都生成了完成包。

因此,回答您的问题...

除非您启用了“跳过完成端口”处理,否则没有理由在调用站点上将lpNumberOfBytesRecvd的值用于WSARecv(),因为即使调用返回SUCCESS也是因为数据已经可用,您仍将把完成操作排队到您要使用的IOCP中必须以通常的方式处理。

如果且仅当您启用了“跳过完成端口”处理时,才应处理对WSARecv()的调用返回的数据,该调用会在您获得SUCCESS结果的位置返回SUCCESS

10-04 12:40