如何使用IOCP获取客户端真正的IP地址和端口?

Ale*_*der 1 c++ sockets winsock iocp

我需要在服务器中使用ip-address和客户端端口.使用IOCP在C++上编写的服务器,所以我不接受客户端,我创建新的套接字然后在这个就绪套接字上接受(AcceptEx)客户端.因为它结构sockaddr_in是不正确的.

我怎样才能做到这一点?

谢谢!

val*_*ldo 5

AcceptEx 可能会返回您的对等地址(TCP套接字的IP +端口).

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
);
Run Code Online (Sandbox Code Playgroud)

您应指定lpOutputBuffer指向具有足够大小的缓冲区以容纳2个返回的地址,然后.dwLocalAddressLengthdwRemoteAddressLength应设置为缓冲区中保留的地址大小.

根据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
Run Code Online (Sandbox Code Playgroud)

使用的传输协议的长度.

当然缓冲区必须对I/O持续时间有效.你可以将它放在你的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);
Run Code Online (Sandbox Code Playgroud)

I/O完成(成功)后,您可以获得以下地址:

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);
Run Code Online (Sandbox Code Playgroud)