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

Winsock2服务器绑定后如何获取真实本地IPv4地址?

问题原因

你现在拿到0.0.0.0是完全符合预期的:

  • 如果你绑定监听套接字的时候用的是INADDR_ANY(也就是0.0.0.0),代表这个套接字会监听本机所有网卡的所有IPv4地址,套接字本身没有绑定单一固定IP,getsockname自然只能返回你绑定的通配地址0.0.0.0。
  • 之前从addrinfo拿到的2开头公网IP,是调用getaddrinfo传入主机名时返回的本机公网出口IP,不是内网网卡的私有地址。

解决方案

方案1:遍历本机所有可用的IPv4地址(推荐)

如果你的服务端监听所有网卡,要展示所有可用于客户端连接的IP,直接调用GetAdaptersAddressesAPI遍历本机网卡地址即可,示例代码如下:

#include <winsock2.h>
#include <iphlpapi.h>
#include <stdio.h>
#include <iostream>
#pragma comment(lib, "iphlpapi.lib")
#pragma comment(lib, "ws2_32.lib")

void printLocalIPv4() {
    ULONG bufSize = 15000;
    PIP_ADAPTER_ADDRESSES pAddresses = (IP_ADAPTER_ADDRESSES*)malloc(bufSize);
    ULONG ret = GetAdaptersAddresses(AF_INET, GAA_FLAG_INCLUDE_PREFIX, NULL, pAddresses, &bufSize);
    if (ret == ERROR_BUFFER_OVERFLOW) {
        free(pAddresses);
        pAddresses = (IP_ADAPTER_ADDRESSES*)malloc(bufSize);
        ret = GetAdaptersAddresses(AF_INET, GAA_FLAG_INCLUDE_PREFIX, NULL, pAddresses, &bufSize);
    }
    if (ret == NO_ERROR) {
        PIP_ADAPTER_ADDRESSES pCurrAddresses = pAddresses;
        while (pCurrAddresses) {
            // 跳过回环、未启用的网卡
            if (pCurrAddresses->OperStatus != IfOperStatusUp || pCurrAddresses->IfType == IF_TYPE_SOFTWARE_LOOPBACK) {
                pCurrAddresses = pCurrAddresses->Next;
                continue;
            }
            PIP_ADAPTER_UNICAST_ADDRESS pUnicast = pCurrAddresses->FirstUnicastAddress;
            while (pUnicast) {
                sockaddr_in* sa_in = (sockaddr_in*)pUnicast->Address.lpSockaddr;
                char ipStr[INET_ADDRSTRLEN];
                inet_ntop(AF_INET, &sa_in->sin_addr, ipStr, INET_ADDRSTRLEN);
                std::cout << "可用服务端IP:" << ipStr << " 网卡名称:" << pCurrAddresses->FriendlyName << std::endl;
                pUnicast = pUnicast->Next;
            }
            pCurrAddresses = pCurrAddresses->Next;
        }
    }
    free(pAddresses);
}

调用这个函数就能输出你要的192.168开头的内网地址,以及其他可用的IP。

方案2:绑定监听套接字到指定IP

如果你确定服务端只需要监听指定的内网网卡,绑定的时候不要用INADDR_ANY,直接指定对应IP即可:

sockaddr_in service;
service.sin_family = AF_INET;
// 替换为你要绑定的内网IP
inet_pton(AF_INET, "192.168.1.18", &service.sin_addr.s_addr);
service.sin_port = htons(你的端口号);

bind(m_ListenSocket, (SOCKADDR*)&service, sizeof(service));

绑定完成后再调用你原来的getsockname代码,就能正确输出绑定的192.168.1.18地址。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 14:54:11