我知道WSARecvFrom有一个参数,用于返回发件人的IP地址。但是,当我使用重叠的io时,我传递的变量不会被填充。
WSARecvFrom(udpSocket, &receiveBuffer, 1, 0, &flags, (sockaddr*)&incomingAddress, &SocketAddressSize, &receiveOverlapped, 0)
...
WSAWaitForMultipleEvents(2, networkEvents, false, WSA_INFINITE, false)
...
WSAGetOverlappedResult(udpSocket, &receiveOverlapped, &transferCount, true, &flags);
...
char* incomingAddressString = inet_ntoa(incomingAddress.sin_addr);
incomingAddressString现在等于“204.204.204.204”
我错过了什么吗?
由于
答案 0 :(得分:1)
此外,lpFrom和lpFromlen指示的值不会更新 直到完成本身表明。申请不得使用或 干扰这些值直到它们被更新,因此 应用程序不得使用自动(即基于堆栈)变量 对于这些参数。
通常,在使用重叠I / O时,您应该定义一个包含OVERLAPPED
或WSAOVERLAPPED
的自定义结构(取决于您使用的API - WSAOVERLAPPED
在这种情况下)和您需要的其他数据(例如在这种情况下您的sockaddr_in
缓冲区)。然后分配struct的动态实例并将其数据成员传递给WSARecvFrom()
并等待操作完成,然后释放struct的内存。这样,当operlapped操作自行执行时,内存仍然有效。例如:
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()
和{{1},则此方法更有用}。阅读这篇文章了解更多详情:
Windows Sockets 2.0: Write Scalable Winsock Apps Using Completion Ports