According to the documentation:
Also, the values indicated by lpFrom and lpFromlen are not updated
until completion is itself indicated. Applications must not use or
disturb these values until they have been updated, therefore the
application must not use automatic (that is, stack-based) variables
for these parameters.
Typically, when using overlapped I/O, you should define a custom struct that contains an OVERLAPPED
or WSAOVERLAPPED
(depending on which API you use - WSAOVERLAPPED
in this situation) and whatever other data you need in (like your sockaddr_in
buffer in this situation). Then allocate a dynamic instance of the struct and pass its data members to WSARecvFrom()
and wait for the operation to complete before then freeing the memory for the struct. That way, the memory remains valid while the operlapped operation is doing its own. For example:
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;
This approach is much more useful if you use an I/O Completion Port for your socket I/O via CreateIOCompletionPort()
and GetQueuedCompletionStatus()
, instead of usin WSAWaitForMultipleEvents()
and WSAGetOverlappedResult()
. Read this article for more details:
Windows Sockets 2.0: Write Scalable Winsock Apps Using Completion Ports