根据documentation:
另外,lpFrom 和 lpFromlen 指示的值不会更新
直到完成本身指示。应用程序不得使用或
扰乱这些值,直到它们被更新,因此
应用程序不得使用自动(即基于堆栈的)变量
对于这些参数。
通常,在使用重叠 I/O 时,您应该定义一个自定义结构,其中包含 OVERLAPPED 或 WSAOVERLAPPED(取决于您使用的 API - 在这种情况下为 WSAOVERLAPPED)以及您需要的任何其他数据(就像你在这种情况下的 sockaddr_in 缓冲区)。然后分配该结构的动态实例并将其数据成员传递给WSARecvFrom() 并等待操作完成,然后再为该结构释放内存。这样,当操作重叠的操作自己进行时,内存仍然有效。例如:
struct MyOverlappedInfo
{
WSAOVERLAPPED Overlapped;
DWORD Flags;
sockaddr_in IncomingAddress;
int IncomingAddressSize;
BYTE Data[1024];
DWORD DataSize;
WSABUF Buffer;
MyOverlappedInfo()
{
memset(this, 0, sizeof(this));
Overlapped.hEvent = WSACreateEvent();
Buffer.len = sizeof(Data);
Buffer.buf = (char*) Data;
}
~MyOverlappedInfo()
{
WSACloseEvent(Overlapped.hEvent);
}
};
MyOverlappedInfo info = new MyOverlappedInfo;
WSARecvFrom(udpSocket, &info->Buffer, 1, NULL, &info->Flags, (sockaddr*)&info->IncomingAddress, &info->IncomingAddressSize, &info->Overlapped, NULL);
...
WSAWaitForMultipleEvents(2, networkEvents, false, WSA_INFINITE, false)
...
WSAGetOverlappedResult(udpSocket, &info->Overlapped, &info->DataSize, TRUE, &info->Flags);
...
char* incomingAddressString = inet_ntoa(info->IncomingAddress.sin_addr);
delete info;
如果您通过CreateIOCompletionPort() 和GetQueuedCompletionStatus() 为您的套接字I/O 使用I/O 完成端口,而不是使用WSAWaitForMultipleEvents() 和WSAGetOverlappedResult(),这种方法会更有用。阅读这篇文章了解更多详情:
Windows Sockets 2.0: Write Scalable Winsock Apps Using Completion Ports