2011-12-20 111 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