WSARecv()
的documentation表示有关lpNumberOfBytesRecvd
参数的以下内容:
我正在使用IOCP,因此lpOverlapped
不能为NULL
,同时WSARecv()
可以立即完成。因此,如果WSARecv()
立即完成,如果lpNumberOfBytesRecvd
是NULL
,我应该如何知道读取了多少字节?还是文档只是意味着我可以将NULL
用作lpNumberOfBytesRecvd
,但不必这样做?
最佳答案
当重叠的WSARecv()
用IO_PENDING
或SUCCESS
完成时,将完成数据包排队到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
。