You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Winsock2中调用accept()后如何获取已连接客户端的IPv4/IPv6地址

Winsock2 同时兼容IPv4/IPv6获取客户端IP地址解决方案

前置配置

  • 项目引入头文件顺序优先导入winsock2.h,避免与旧版winsock.h冲突,必要时可提前定义WIN32_LEAN_AND_MEAN宏
  • 链接ws2_32.lib库,可直接在代码中添加#pragma comment(lib, "ws2_32.lib")
  • 导入额外头文件ws2tcpip.h、iostream

实现思路

使用SOCKADDR_STORAGE结构存储客户端地址,该结构可同时兼容IPv4、IPv6两种地址格式,避免单使用SOCKADDR_IN仅支持IPv4的问题。地址转字符串使用Winsock2原生提供的InetNtop函数(对应Unix平台的inet_ntop),无需调用DNS相关接口。

完整代码示例

SOCKET listenSocket; // 你已初始化好的监听套接字
SOCKET acceptSocket = INVALID_SOCKET;
// 使用SOCKADDR_STORAGE兼容IPv4/IPv6地址
SOCKADDR_STORAGE clientAddr = {0};
int addrLen = sizeof(clientAddr);

acceptSocket = accept(listenSocket, (SOCKADDR*)&clientAddr, &addrLen);
if (acceptSocket == INVALID_SOCKET) {
    // 错误处理逻辑
} else {
    char ipBuf[INET6_ADDRSTRLEN] = {0};
    USHORT clientPort = 0;

    // 判断地址类型分别处理
    if (clientAddr.ss_family == AF_INET) {
        // IPv4地址转换
        SOCKADDR_IN* ipv4Addr = (SOCKADDR_IN*)&clientAddr;
        InetNtop(AF_INET, &ipv4Addr->sin_addr, ipBuf, INET_ADDRSTRLEN);
        clientPort = ntohs(ipv4Addr->sin_port);
    } else if (clientAddr.ss_family == AF_INET6) {
        // IPv6地址转换
        SOCKADDR_IN6* ipv6Addr = (SOCKADDR_IN6*)&clientAddr;
        InetNtop(AF_INET6, &ipv6Addr->sin6_addr, ipBuf, INET6_ADDRSTRLEN);
        clientPort = ntohs(ipv6Addr->sin6_port);
    }

    // 输出客户端地址与端口
    std::cout << ipBuf << ":" << clientPort << std::endl;
}

getpeername 修正方案

你之前的类型错误是因为第二个参数需要传入sockaddr结构指针而非字符数组,正确用法如下:

SOCKADDR_STORAGE peerAddr = {0};
int addrLen = sizeof(peerAddr);
int ret = getpeername(acceptSocket, (SOCKADDR*)&peerAddr, &addrLen);
if (ret == 0) {
    // 调用成功,后续地址转换逻辑和上述accept后的处理完全一致
    char ipBuf[INET6_ADDRSTRLEN] = {0};
    USHORT peerPort = 0;
    if (peerAddr.ss_family == AF_INET) {
        SOCKADDR_IN* ipv4 = (SOCKADDR_IN*)&peerAddr;
        InetNtop(AF_INET, &ipv4->sin_addr, ipBuf, INET_ADDRSTRLEN);
        peerPort = ntohs(ipv4->sin_port);
    } else if (peerAddr.ss_family == AF_INET6) {
        SOCKADDR_IN6* ipv6 = (SOCKADDR_IN6*)&peerAddr;
        InetNtop(AF_INET6, &ipv6->sin6_addr, ipBuf, INET6_ADDRSTRLEN);
        peerPort = ntohs(ipv6->sin6_port);
    }
    std::cout << "对端地址:" << ipBuf << ":" << peerPort << std::endl;
}

常见编译错误解决

  • 提示InetNtop未定义:检查是否导入了ws2tcpip.h,且项目的Windows SDK版本支持该函数(Vista及以上系统默认支持)
  • 旧版SDK下可替换为WSAAddressToString函数实现相同效果
  • 端口输出数值异常:确认调用了ntohs将网络字节序转换为主机字节序

内容的提问来源于stack exchange,提问作者user2138149

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.28 14:36:00