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

标签 c++ sockets winsock iocp

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

我该怎么做?

谢谢!

最佳答案

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

length for the transport protocol in use.

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

关于c++ - 如何使用 IOCP 获取客户端真实 IP 地址和端口?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10027940/

相关文章:

c++ - Winsock 400 错误请求,openresty

c++ - Winsock 通过 recv() 接收随机字母

c - 在 C (win32) 中发送帧的套接字和线程方法

c++ - 设置对第二个变量的引用

c - 伯克利套接字的网络连接速度慢

c - 绑定(bind)()错误: Cannot assign requested address

delphi - Indy idHttp 卡住 - 如何使用 keep-alive?

android - 使用 Binder 从 native cpp 应用程序中 bundle Intent

c++ - 如何从 C++ 中的字符串中提取子字符串?

c++ - Qt - C++ - 通过带有连接的父访问的子函数