c++ - 使用重叠 IO 获取发件人的 IP 地址

标签 c++ networking winsock winsock2 overlapped-io

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

我错过了什么吗?

谢谢

最佳答案

根据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.

通常,当使用重叠 I/O 时,您应该定义一个包含 OVERLAPPEDWSAOVERLAPPED 的自定义结构(取决于您使用的 API - WSAOVERLAPPED 在这种情况下)以及您需要的任何其他数据(例如在这种情况下您的 sockaddr_in 缓冲区)。然后分配该结构的动态实例并将其数据成员传递给 WSARecvFrom() 并等待操作完成,然后再为该结构释放内存。这样,当 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()WSAGetOverlappedResult()。阅读这篇文章了解更多详情:

Windows Sockets 2.0: Write Scalable Winsock Apps Using Completion Ports

关于c++ - 使用重叠 IO 获取发件人的 IP 地址,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8582436/

相关文章:

python - 使用 SimpleHTTPServer 和 SocketServer 的简单 python 服务器,如何在重新运行 .py 文件之前关闭套接字?

c - WinDivert 忽略 Tor 流量

c++ - 如何创建一个 "event"系统来接收数据包

c++ - 将 sockaddr 分配给另一个更改地址?

c++ - 编译器将随机字符添加到我的 char 数组

c++ - 什么是boost log,如何获取以及如何构建

c++ - 在读取文件 C++ 时使用 getline 和 >>

html - QT CSS 中的边框渐变透明

ios - 扫描网络设备

c++ - 为什么 getpeername 中的 namelen-parameter 在 Winsock 中使用指针?