c++ Windows 10 为已连接的客户端获取 Ip

c++ Windows 10 Get an Ip for a connected client

我已经设置了一个客户端可以连接的工作 WinSock2 套接字,我怎样才能获得连接的客户端的 IP 地址。

客户端的IP地址由accept() when the client is first accepted. It can also be queried from the client SOCKET at any time using getpeername()报告。这两个函数都填充了一个 sockaddr_... 结构,您必须根据使用 socket():

创建服务器套接字时分配的地址类型分配并传入该结构
  • 如果AF_INET,提供一个sockaddr_in结构:
sockaddr_in clientAddr;
int clientAddrSize = sizeof(clientAddr);
SOCKET client = accept(server, (sockaddr*)&client_addr, &clientAddrSize);
if (client != INVALID_SOCKET)
{
    // use client_addr.sin_addr as needed...
    ...
    clientAddrSize = sizeof(clientAddr);
    if (getpeername(client, (sockaddr*)&client_addr, &clientAddrSize) == 0)
    {
        // use client_addr.sin_addr as needed...
    }
    ...
    closesocket(client);
}
  • 如果 AF_INET6 启用 IPV6_V6ONLY,请提供 sockaddr_in6 结构:
sockaddr_in6 clientAddr;
int clientAddrSize = sizeof(clientAddr);
SOCKET client = accept(server, (sockaddr*)&client_addr, &clientAddrSize);
if (client != INVALID_SOCKET)
{
    // use client_addr.sin6_addr as needed...
    ...
    clientAddrSize = sizeof(clientAddr);
    if (getpeername(client, (sockaddr*)&client_addr, &clientAddrSize) == 0)
    {
        // use client_addr.sin6_addr as needed...
    }
    ...
    closesocket(client);
}
  • 如果 AF_INET6 禁用 IPV6_V6ONLY,提供一个 sockaddr_storage 结构,然后查看其 ss_family 字段以了解是否转换 sockaddr_storage数据到 sockaddr_insockaddr_in6:
sockaddr_storage clientAddr;
sockaddr_in *clientAddr4;
sockaddr_in6 *clientAddr6;
int clientAddrSize = sizeof(clientAddr);
SOCKET client = accept(server, (sockaddr*)&client_addr, &clientAddrSize);
if (client != INVALID_SOCKET)
{
    switch (client_addr.ss_family)
    {
        case AF_INET:
            clientAddr4 = use reinterpret_cast<sockaddr_in*>(&client_addr);
            // use clientAddr4->sin_addr as needed...
            break;
        case AF_INET6:
            clientAddr6 = use reinterpret_cast<sockaddr_in6*>(&client_addr);
            // use clientAddr6->sin6_addr as needed...
            break;
    }
    ...
    clientAddrSize = sizeof(clientAddr);
    if (getpeername(client, (sockaddr*)&client_addr, &clientAddrSize) == 0)
    {
        switch (client_addr.ss_family)
        {
            case AF_INET:
                clientAddr4 = use reinterpret_cast<sockaddr_in*>(&client_addr);
                // use clientAddr4->sin_addr as needed...
                break;
            case AF_INET6:
                clientAddr6 = use reinterpret_cast<sockaddr_in6*>(&client_addr);
                // use clientAddr6->sin6_addr as needed...
                break;
        }
    }
    ...
    closesocket(client);
}