这是一篇由两部分组成的帖子。我正在使用WSARecvFrom()编写一小段代码来接收UDP数据包。我使用WSA_FLAG_OVERLAPPED创建套接字,我使用ioctlsocket()调用将套接字设置为非阻塞模式,将其绑定到端口,创建扩展的WSAOVERLAPPED结构实例,使用完成例程发布我的接收,并等待其中一个可警告的等待函数。我收到包,工作正常。第一部分:
以下是来自Windows Dev-Center,WSARecvFrom功能文档:
“如果没有发生错误且接收操作立即完成,则WSARecvFrom返回零。在这种情况下,一旦调用线程处于可警告状态,就会调度完成例程。“
这是什么意思?
我对“接收函数已立即完成”的理解是,该函数已经从套接字接收了一些内容,并且已经使用发送给它的任何内容填充了缓冲区,更新了lpNumberOfBytesRecvd参数,并返回0.为什么在这种情况下需要调用完成例程?在这种情况下,完成例程的cbTransfer值是多少呢?
请注意,我得到了其余的文档:“否则,返回SOCKET ERROR的值。错误代码WSA IO PENDING表示已成功启动重叠操作,并且将在以后。“。没关系,WSARecvFrom()返回SOCKET_ERROR,WSAGetLastError()返回WSA_IO_PENDING,我的完成例程被调用,其中有一些东西要读,我在完成例程中发布另一个接收,依此类推。
第二部分:即使上面的内容只是对我的文档的误解(因为这不是我的母语),返回成功完成的异步函数会使代码不必要地重复。或者我离开了。但是,如果我对成功完成的理解是正确的,那么有没有办法防止异步函数返回成功?我可以像WSARecvFrom()这样的函数返回SOCKET_ERROR(使用WSA_IO_PENDING)并且永远不会返回0吗?
感谢您的阅读。
答案 0 :(得分:1)
如果已经准备好要读取数据,WSARecvFrom()
会立即调度完成例程,以便在线程处于可警告状态时调用它以指示数据已被读取。始终调用完成例程,并读取正确的缓冲区大小。无论WSARecvFrom()
是否实际填充缓冲区,您都应该等待在处理缓冲区之前调用完成例程,这样您就不会使代码与自身同步,并且可以集中缓冲区在一个地方处理而不是在两个地方进行处理。