获得本地主机名,在Windows上工作,但在Linux中没有

时间:2013-12-02 16:43:16

标签: c++ c linux windows getaddrinfo

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

我正在使用getaddrinfo NULL作为主机名,然后使用第一个地址拨打getnameinfo

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

请注意,我在AI_PASSIVE中使用getaddrinfo标记,表示它只给我两个地址。

getnameinfo如果我使用NI_NAMEREQD它失败。

我这样做是因为我有一台服务器,有时候我想听所有接口,有时候听一个特定的接口,我已经有了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. 我知道我可以这样补丁:

  3. if(std::string("::") == hostname || std::string("0.0.0.0") == hostname) gethostname(hostname,100)

    1. 除非地址为localhost127.0.0.1,否则我不希望得到::1

1 个答案:

答案 0 :(得分:1)

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

使用struct addrinfo成员ai_next遍历此列表,以查找计算机所有接口的地址。

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


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

  1. 主持人的名称(“主机名”)作为gethostname()的回溯是主机的属性。它是在主机上配置,而不是在任何外部数据库中保存。此主机名每个定义未链接到可能的接口地址解析的任何名称。主机名可能已配置以匹配一个地址(机器接口)解析为的名称。

  2. 机器可能提供多个接口。这些接口的每个地址都应该解析为一个不同的名称,而这个名称也可能与gethostname()返回的名称不同(参见上面的1.)。这适用于所有类型的接口,包括IPv4和IPv6。还有虚拟通配符地址(IPv4的0.0.0.0),它允许程序绑定并监听机器提供的所有接口(此处键入的IPv4)。 wildcard-adresse具有名称。

  3. 1.和2.的结论是:没有名称 ...喜欢[返回] gethostname()但是规范。”!