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

Windows平台下如何判断套接字句柄为AF_INET(IPv4)还是AF_INET6(IPv6)

判断Windows套接字句柄地址族(AF_INET/AF_INET6)的方法

当然有办法在Windows平台判断一个已存在的套接字句柄对应的地址族是AF_INET还是AF_INET6,下面是两种实用的方案,适配不同的系统版本:

方案1:使用getsockopt()获取SO_DOMAIN选项

这是最直接可靠的方式,getsockopt可以读取套接字的核心属性,其中SO_DOMAIN选项会直接返回创建套接字时传入的地址族参数(AF_INET或AF_INET6)。

这个方法从Windows Vista和Windows Server 2008开始支持,代码示例:

#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdio.h>

#pragma comment(lib, "ws2_32.lib")

int GetSocketAddrFamily(SOCKET sock) {
    int addrFamily;
    int optLen = sizeof(addrFamily);
    
    if (getsockopt(sock, SOL_SOCKET, SO_DOMAIN, (char*)&addrFamily, &optLen) == SOCKET_ERROR) {
        fprintf(stderr, "getsockopt failed with error: %d\n", WSAGetLastError());
        return -1;
    }
    
    return addrFamily;
}

// 测试示例
int main() {
    WSADATA wsaData;
    if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
        fprintf(stderr, "WSAStartup failed\n");
        return 1;
    }

    // 创建IPv4套接字测试
    SOCKET ipv4Sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    int family = GetSocketAddrFamily(ipv4Sock);
    if (family == AF_INET) {
        printf("This is an AF_INET (IPv4) socket\n");
    } else if (family == AF_INET6) {
        printf("This is an AF_INET6 (IPv6) socket\n");
    }

    closesocket(ipv4Sock);
    WSACleanup();
    return 0;
}

方案2:通过getsockname()/getpeername()判断(兼容旧系统)

如果你的程序需要支持Windows XP或更早版本,SO_DOMAIN不可用,可以通过获取套接字的本地绑定地址(getsockname)或远端连接地址(getpeername),然后读取地址结构的sa_family字段来判断。

注意:这种方法要求套接字已经完成绑定(bind)或连接(connect)操作,否则可能返回错误或不确定的结果。代码示例:

int GetSocketAddrFamilyLegacy(SOCKET sock) {
    struct sockaddr_storage addr;
    int addrLen = sizeof(addr);
    
    if (getsockname(sock, (struct sockaddr*)&addr, &addrLen) == SOCKET_ERROR) {
        fprintf(stderr, "getsockname failed with error: %d\n", WSAGetLastError());
        return -1;
    }
    
    return addr.ss_family;
}

额外注意事项

  • 调用上述函数前,确保套接字句柄是有效的(未被关闭),否则会返回SOCKET_ERROR。
  • 所有Winsock相关操作都需要先调用WSAStartup初始化套接字库,结束后调用WSACleanup释放资源。
  • 编译时记得链接ws2_32.lib库(示例中用#pragma comment(lib, "ws2_32.lib")实现,也可以在编译器设置中添加)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.28 09:07:42