1

我知道 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”

我错过了什么吗?

谢谢

4

1 回答 1

1

根据文档

此外,由 lpFrom 和 lpFromlen 指示的值在完成本身指示之前不会更新。应用程序在更新之前不得使用或干扰这些值,因此应用程序不得对这些参数使用自动(即基于堆栈的)变量。

通常,在使用重叠 I/O 时,您应该定义一个自定义结构,其中包含一个OVERLAPPEDor 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()如果您通过and为您的套接字 I/O 使用 I/O 完成端口GetQueuedCompletionStatus(),而不是使用WSAWaitForMultipleEvents()and ,这种方法会更加有用WSAGetOverlappedResult()。阅读这篇文章了解更多详情:

Windows Sockets 2.0:使用完成端口编写可扩展的 Winsock 应用程序

于 2011-12-20T22:26:11.030 回答