Как получить реальный IP-адрес и порт клиента с помощью IOCP?

Мне нужно взять ip-адрес и порт клиентов на сервере. Сервер написан на C++ с использованием IOCP, поэтому я не принимаю клиентов, я создаю новый сокет и затем принимаю (AcceptEx) клиента на этот готовый сокет. И из-за этого структура sockaddr_in неверна.

Как я могу это сделать?

Спасибо!


person Alexander    schedule 05.04.2012    source источник


Ответы (1)


AcceptEx может вернуть вам как ваш адрес, так и адрес пира (ip+порт сокетов TCP).

BOOL AcceptEx(
  __in   SOCKET sListenSocket,
  __in   SOCKET sAcceptSocket,
  __in   PVOID lpOutputBuffer,
  __in   DWORD dwReceiveDataLength,
  __in   DWORD dwLocalAddressLength,
  __in   DWORD dwRemoteAddressLength,
  __out  LPDWORD lpdwBytesReceived,
  __in   LPOVERLAPPED lpOverlapped
);

Вы должны указать lpOutputBuffer, чтобы указать на буфер с достаточным размером для хранения 2 возвращаемых адресов, затем . dwLocalAddressLength и dwRemoteAddressLength должны быть установлены на размер адреса, зарезервированный в буфере.

Согласно MSDN размер буфера, необходимый для одного адреса (для функции AcceptEx), равен sizeof(SOCKADDR_IN) + 16:

dwLocalAddressLength [in]

The number of bytes reserved for the local address information. This value must be at least 16 bytes more than the maximum address

длина используемого транспортного протокола.

Конечно, буфер должен быть действителен в течение всего времени ввода-вывода. Вы можете поместить его в свою структуру OVERLAPPED. Что-то вроде этого:

struct OverlappedAccept
    :public OVERLAPPED
{
    // some context information that you need
    // ...

    // Buffer for addresses
    struct {
        BYTE m_pLocal[sizeof(SOCKADDR_IN) + 16];
        BYTE m_pRemote[sizeof(SOCKADDR_IN) + 16];
    } m_Bufs;
};


// start accept operation
OverlappedAccept* pOver = /* ... */;

BOOL bRet = AcceptEx(
    hSockListen,
    hSockNew,
    &pOver->m_Bufs,
    0,
    sizeof(pOver->m_Bufs.m_pLocal),
    sizeof(pOver->m_Bufs.m_pRemote),
    &dwBytes,
    pOver);

После того, как ввод-вывод (успешно) завершился, вы можете получить адреса:

sockaddr *pLocal = NULL, *pRemote = NULL;
int nLocal = 0, nRemote = 0;
GetAcceptExSockAddrs(
    &pOver->m_Bufs,
    0,
    sizeof(pOver->m_Bufs.m_pLocal),
    sizeof(pOver->m_Bufs.m_pRemote),
    &pLocal,
    &nLocal,
    &pRemote,
    &nRemote);
person valdo    schedule 05.04.2012