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

为何Windows 11中getnameinfo无法返回本地设备的主机名?

问题排查与解决方案

代码中的关键问题

  1. 错误处理逻辑错误
    getnameinfo的返回值dwRetval本身就是错误码,不需要调用WSAGetLastError()。解析失败时,应直接用gai_strerror(dwRetval)获取错误描述,WSAGetLastError()在此场景下无效。

  2. NI_NAMEREQD标志误用
    该标志强制要求必须解析出DNS反向记录,否则直接返回失败。但路由器和手机APP显示的设备名称大多是NetBIOS名称或MDNS(多播DNS)名称,并非DNS反向解析记录,使用此标志会导致多数正常场景被判定为失败。

  3. 过时的地址转换函数
    inet_addr已被废弃,建议使用inet_pton(AF_INET, argv[1], &saGNI.sin_addr),它能更可靠地校验IPv4地址格式,避免无效地址引发的问题。

  4. 不必要的端口设置
    若仅需获取主机名,无需指定具体端口(如代码中的27015),可将saGNI.sin_port设为htons(0),因为服务信息并非目标需求。

修正后的测试代码

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

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

int __cdecl main(int argc, char** argv)
{
    WSADATA wsaData = { 0 };
    int iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
    if (iResult != 0) {
        printf("WSAStartup failed: %d\n", iResult);
        return 1;
    }

    if (argc != 2) {
        printf("usage: %s IPv4 address\n", argv[0]);
        printf("       %s 192.168.1.100\n", argv[0]);
        WSACleanup();
        return 1;
    }

    struct sockaddr_in saGNI = {0};
    char hostname[NI_MAXHOST];
    char servInfo[NI_MAXSERV];

    saGNI.sin_family = AF_INET;
    if (inet_pton(AF_INET, argv[1], &saGNI.sin_addr) != 1) {
        printf("Invalid IPv4 address\n");
        WSACleanup();
        return 1;
    }
    saGNI.sin_port = htons(0); // 无需服务信息,设为0

    DWORD dwRetval = getnameinfo((struct sockaddr*)&saGNI,
        sizeof(struct sockaddr_in), // 使用sizeof(sockaddr_in)更准确
        hostname, NI_MAXHOST,
        servInfo, NI_MAXSERV,
        0); // 移除NI_NAMEREQD,允许无解析结果时返回IP

    if (dwRetval != 0) {
        printf("getnameinfo failed: %s\n", gai_strerror(dwRetval));
    } else {
        printf("Resolved name: %s\n", hostname);
    }

    WSACleanup();
    return 0;
}

更可靠的设备名称获取方法

若修正后的代码仍无法获取路由器/手机APP显示的名称,说明目标设备未配置DNS反向解析,可尝试以下方法:

  • NetBIOS名称查询:Windows系统可通过NetBIOS协议获取局域网设备名称,可调用NetBIOS()核心API,或参考nbtstat命令的实现逻辑(向目标IP的137端口发送NetBIOS查询包)。
  • MDNS查询:多数智能设备会通过MDNS广播自身名称(格式为设备名.local),Windows 11支持DNS-SD API,可使用DnsServiceBrowse等函数查询局域网内的MDNS设备。
  • ARP缓存结合NetBIOS:先通过ARP缓存获取局域网内的IP-MAC映射,再对每个IP执行NetBIOS名称查询,此逻辑与路由器设备列表的实现方式更接近。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 06:36:32