c++ - 获得本地主机名,在 Windows 上工作,但在 Linux 上不行

标签 c++ c linux windows getaddrinfo

我写了一个程序来获取本地主机名。如果不是很明显,我的意思是获取本地机器的主机名类似于gethostname方法,而不是获取字符串localhost

我正在使用 getaddrinfoNULL 作为主机名,然后使用第一个地址调用 getnameinfo

它在 Windows 机器上完美运行,并为我提供规范的主机名,但在 Linux 中,它无法为我提供本地主机名,并为我提供用于 IPv6 或 0.0 的 ::。 0.0 用于 IPv4。

请注意,我在 getaddrinfo 中使用了 AI_PASSIVE 标志,这意味着它给我的地址不超过两个。

getnameinfo 中,如果我使用 NI_NAMEREQD,它会失败。

我这样做是因为我有一个服务器,有时我想监听所有接口(interface),有时我想监听一个特定的接口(interface),我已经有了 addrinfo 我只想得到如果可能的话,从中获取主机名。

如何让它在 Linux 上运行? 我错过了什么吗?

感谢您的帮助。

这是我的代码:(跨平台,Windows和Linux,只需复制过去) 您可以在两者上编译和运行并查看差异。

#include <iostream> 

#ifdef WIN32

#ifdef UNICODE
#undef UNICODE /* don't want Unicode, to keep code compatibility */
#endif

#include <WS2tcpip.h>
#pragma comment(lib, "ws2_32.lib")
class CWSAInitializer{
public:
    CWSAInitializer(){
        WSADATA data;
        WSAStartup(MAKEWORD(2,2),&data);
    }
    ~CWSAInitializer(){
        WSACleanup();
    }
}autoInit;

#else
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#endif

const char* get_hostname(struct addrinfo* info, char buff[], int buff_len)
{
    int addrlen = (int)info->ai_addrlen;
    int res = getnameinfo(info->ai_addr, addrlen, buff, buff_len, NULL, 0, 0);
    if(res){
        return NULL;
    }
    return buff;
}

int main () 
{
    char temp[100];
    addrinfo *ai,hints;
    memset(&hints,0,sizeof(hints));
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_flags = AI_NUMERICSERV;
    hints.ai_flags |= AI_PASSIVE;

    int res = getaddrinfo(NULL, "0", &hints, &ai); 
    if(res){
        std::cerr<<gai_strerror(res)<<std::endl;
        return -1;
    }
    std::cout<< get_hostname(ai,temp,100)<<std::endl;
    freeaddrinfo(ai);

    return 0;
}

编辑

  1. 服务器也应该接受来自其他机器的客户端,所以它不能报告监听 ::0.0.0.0

  2. 我知道我可以像这样修补它:

if(std::string("::") == 主机名 || std::string("0.0.0.0") == 主机名) gethostname(主机名,100)

  1. 我不想得到 localhost 作为结果,除非地址是 127.0.0.1::1

最佳答案

getaddrinfo() 返回 struct addrinfo 节点列表的头部。

使用struct addrinfo 的一个成员ai_next 遍历这个列表来找到机器所有接口(interface)的地址。

要接收通配符地址以外的任何其他内容,请在传递的提示中指定AI_PASSIVE 标志。


更新给机器和/或其接口(interface)地址的各种名称:

  1. gethostname() 返回的主机名("hostname")是主机的一个属性。它在主机上配置,不保存在任何外部数据库中。此主机名根据定义未链接 到可能的接口(interface)地址解析到的任何名称。然而,主机名可能配置以匹配(机器接口(interface)的)地址之一解析到的名称。

  2. 一台机器可能提供不止一个接口(interface)。这些接口(interface)的地址中的每一个都应该解析为不同的名称,这反过来也可能与 gethostname() 返回的名称不同(请参见上面的 1.)。这适用于所有类型的接口(interface),包括 IPv4 和 IPv6。它还有虚拟通配符地址(0.0.0.0for IPv4),它允许程序绑定(bind)到机器提供的所有接口(interface)(此处键入 IPv4)并在其上监听。通配符地址没有名称。

从 1. 和 2. 得出的结论是:没有名字...像[由] gethostname() 返回但规范。”!

关于c++ - 获得本地主机名,在 Windows 上工作,但在 Linux 上不行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20333364/

相关文章:

c++ - 有没有办法在 C++ 中使用 bool 值作为位图?

C++17 "any_cast"隐式构造函数失败,引发异常

c++ - OpenMP 优化 for 循环的调度

c++ - 使用 sizeof 运算符在 C 和 C++ 中的不同输出

c - 获取错误的字符串长度

c++ - 难以实现 -> 结构取消引用运算符

c - 错误 : invalid type argument of unary ‘*’ (have ‘long int’ )

linux - 参数没有传递好

linux - App Engine 忽略指向目录的符号链接(symbolic link)

php - 在 Linux 中终止 php 浏览器请求