Я написал программу для получения локального имени хоста. если это не очевидно, я имею в виду получить имя хоста локальной машины, подобное gethostname
метод, чтобы не получить строку localhost
я использую getaddrinfo
с NULL
для имени хоста, а затем позвоните getnameinfo
с первым адресом.
Он отлично работает на компьютерах с Windows и дает мне каноническое имя хоста, но в Linux он не смог дать мне имя локального хоста и дает мне ::
для IPv6 или 0.0.0.0
для IPv4.
Обратите внимание, что я использую 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;
}
РЕДАКТИРОВАТЬ
Сервер также должен принимать клиента с других компьютеров, поэтому он не может сообщить о прослушивании ::
или же 0.0.0.0
,
Я знаю, что могу исправить это так:
if(std::string("::") == hostname || std::string("0.0.0.0") == hostname)
gethostname(hostname,100)
localhost
как результат, если адрес 127.0.0.1
или же ::1
,getaddrinfo()
возвращает заголовок списка struct addrinfo
узлы.
Обходит этот список, используя struct addrinfo
член ai_next
найти адреса всех интерфейсов машины.
Чтобы получить что-то еще, кроме адресов подстановки не указать AI_PASSIVE
флаг в подсказках пройден.
Обновите информацию о различных именах, присвоенных машине и / или адресам ее интерфейсов:
Имя хозяина («имя хоста«) как отреагировал gethostname()
является атрибутом для хоста. это настроен на хосте и не хранится ни в одной внешней базе данных. Это имя хоста по определению не связано к любому из имен, которые разрешают адреса возможных интерфейсов. Имя хоста может быть однако быть сконфигурировано чтобы соответствовать названию один из адресов (интерфейсов машины) разрешается в.
Может быть более одного интерфейса, предоставленного машиной. Адрес каждого из этих интерфейсов должен соответствовать другому имени, которое, в свою очередь, также может отличаться от имени, возвращаемого gethostname()
(см. 1. выше). Это относится ко всем типам интерфейсов, включая IPv4 и IPv6. Там и это виртуальный wildcard-адрес (0.0.0.0
для IPv4), который позволяет программам связываться и слушать все интерфейсы (набранные здесь IPv4), которые предоставляет машина. Подстановочный знак имеет нет название.
Вывод из 1. и 2. это: Нет имени «… как [возвращено] gethostname (), но каноническое.«!
Других решений пока нет …