【发布时间】:2013-12-02 16:43:15
【问题描述】:
我写了一个程序来获取本地主机名。如果不是很明显,我的意思是获取本地机器的主机名类似于gethostname的方法,而不是获取字符串localhost
我使用getaddrinfo 和NULL 作为主机名,然后使用第一个地址调用getnameinfo。
它在 Windows 机器上完美运行,并给了我规范的主机名,但在 Linux 中它没有给我本地主机名,给我:: 用于 IPv6 或0.0.0.0 用于 IPv4。
请注意,我在getaddrinfo 中使用了AI_PASSIVE 标志,这意味着它给我的地址不超过两个。
如果我在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;
}
编辑
服务器也应该接受来自其他机器的客户端,所以它不能报告监听
::或0.0.0.0。我知道我可以这样修补它:
if(std::string("::") == hostname || std::string("0.0.0.0") == hostname)
gethostname(hostname,100)
- 我不想得到
localhost作为结果,除非地址是127.0.0.1或::1。
【问题讨论】:
-
如果您只想要本地主机名,为什么不使用 INADDR_LOOPBACK?
-
我不想要 localhost 界面。服务器正在外面监听,我想知道我当前正在监听哪个主机名。如果客户端尝试连接到 :: 或 0.0.0.0,它将无法连接。
标签: c++ c linux windows getaddrinfo