Получить IP-адрес отправителя с помощью перекрывающегося ввода-вывода - PullRequest
1 голос
/ 21 декабря 2011

Я знаю, что в 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);

comingAddressString теперь равно "204.204.204.204"

Я что-то упустил?

Спасибо

1 Ответ

1 голос
/ 21 декабря 2011

Согласно документации :

Кроме того, значения, указанные в lpFrom и lpFromlen, не обновляются, пока не будет указано само завершение.Приложения не должны использовать или нарушать эти значения до тех пор, пока они не будут обновлены, поэтому приложение не должно использовать автоматические (то есть основанные на стеке) переменные для этих параметров.

Как правило, при использовании перекрывающихся операций ввода-выводаО, вы должны определить пользовательскую структуру, которая содержит OVERLAPPED или WSAOVERLAPPED (в зависимости от того, какой 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() вместо usin WSAWaitForMultipleEvents() и WSAGetOverlappedResult().Прочтите эту статью для получения более подробной информации:

Windows Sockets 2.0: создание масштабируемых приложений Winsock с использованием портов завершения

...