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

Posted

技术标签:

【中文标题】如何使用 IOCP 获取客户端真实 IP 地址和端口?【英文标题】:How to get client real ip-address and port using IOCP? 【发布时间】:2012-04-05 11:43:39 【问题描述】:

我需要在服务器中获取客户端的 IP 地址和端口。使用 IOCP 在 C++ 上编写的服务器,所以我不接受客户端,我创建新的套接字,然后在这个准备好的套接字上接受(AcceptEx)客户端。并且因为它 struct sockaddr_in 不正确。

我该怎么做?

谢谢!

【问题讨论】:

【参考方案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 个返回地址的缓冲区,然后. 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

正在使用的传输协议的长度。

当然,缓冲区必须在 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);

在 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);

【讨论】:

以上是关于如何使用 IOCP 获取客户端真实 IP 地址和端口?的主要内容,如果未能解决你的问题,请参考以下文章

如何获取客户端ip

如何获取伪装ip下的真实ip地址

Websocket-Sharp获取客户端IP地址和端口号

如何获取网站用户的真实IP

使用 istio 后如何获取客户端真实 IP

在 k3s 上使用 Traefik 时如何获取客户端的真实 IP 地址?