2011-12-20 74 views
1

我知道WSARecvFrom有一个参数,用于返回发件人的IP地址。但是,当我将它与重叠的io一起使用时,我传递的变量不会被填充。使用重叠的IO获取发件人的IP地址

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

考虑使用ASIO http://think-async.com/Asio/ – 2011-12-20 21:53:11

回答

1

按照documentation

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

通常情况下,当使用重叠I/O,您应该定义一个包含OVERLAPPEDWSAOVERLAPPED自定义结构(取决于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; 

这种方法更加有用,如果你使用的I/O完成端口为您的套接字I/O通过CreateIOCompletionPort()GetQueuedCompletionStatus(),而不是全光照WSAWaitForMultipleEvents()WSAGetOverlappedResult()。阅读这篇文章,了解详情:

Windows Sockets 2.0: Write Scalable Winsock Apps Using Completion Ports

+0

我所有的网络属于一类,我不传递任何堆栈变量。我测试过将一个新变量传递给lpFromLen,但是除非它设置为地址结构的大小,否则它会发生错误,这使我怀疑那里的文档的准确性。 – XZodia 2011-12-20 22:50:01

+0

这就是你应该做的。我在我的回答中链接到的文档声明:“lpFromlen'指向的值被初始化为该缓冲区的大小,并在完成时被修改以指示存储在那里的实际地址大小。” – 2011-12-20 23:21:33

+0

是的,我指的是“lpFromlen没有更新,直到完成”这没有任何意义(为什么它会改变?)。但是我们在此讨论主题...... – XZodia 2011-12-21 00:37:54