Получение ip сервера 0.0.0.0:0 от getaddrinfo () - PullRequest
5 голосов
/ 30 октября 2011

Я следую руководству Биджа по NP.

Я сделал несколько изменений и пытаюсь получить IP-адрес моей серверной программы через getaddrinfo ().
(оригинал можно найти здесь http://beej.us/guide/bgnet/output/html/singlepage/bgnet.html#simpleserver)

Ниже приведены части, которые я изменил / добавил.

if ((rv = getaddrinfo(NULL, "0", &hints, &servinfo)) != 0) { //0 for random port?
    fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
    return 1;
 }

//... some code emitted ...

//freeaddrinfo(servinfo); //I still need it!


printf("ip: %s\nport: %d\n",
    inet_ntop(AF_INET, &((struct sockaddr_in *)p->ai_addr)->sin_addr, ip4, INET_ADDRSTRLEN),
    ntohs(((struct sockaddr_in *)p->ai_addr)->sin_port)
);

Проблема в том, что я получаю результаты

ip: 0.0.0.0  
port: 0  

Q1: я читал изна нескольких веб-сайтах говорится, что установка «0» для порта говорит ОС, что вы хотите следующий доступный порт, а не 0. Это правда?

Q2: Я также прочитал это gethostbyname (gethostname (...)) может дать вам ip машины, но Бидж сказал, что они заменены getaddrinfo (). Итак, я должен использовать getaddrinfo? Или gethostbyname?

Q3: Есть ли что-нибудь еще, что я 'я делаю неправильно?

Ответы [ 2 ]

8 голосов
/ 30 октября 2011

Он возвращает именно то, что вы ожидаете.

С man getaddrinfo:

Если в hints.ai_flags указан флаг AI_PASSIVE, а узел имеет значение NULL, товозвращенные адреса сокетов будут пригодны для связывания (2) сокета, который будет принимать (2) соединения.Возвращенный адрес сокета будет содержать «подстановочный адрес» (INADDR_ANY для адресов IPv4, IN6ADDR_ANY_INIT для адресов IPv6).Подстановочный адрес используется приложениями (обычно серверами), которые намереваются принимать подключения по любому из сетевых адресов хостов.Если узел не равен NULL, тогда флаг AI_PASSIVE игнорируется.

Код, на который вы ссылаетесь, устанавливает hints.ai_flags на AI_PASSIVE, и вы передаете NULL для узла.Адрес подстановочного знака 0.0.0.0.Работает как указано.Привязка к этому адресу означает, что вы привязываетесь к каждому IP-адресу на вашей машине.

Что касается порта ... вы указываете "0", который ... это именно то, что вы получаете обратно.Вам нужно установить фактический порт, который вы хотите прослушивать, как пример кода, на который вы ссылаетесь.

6 голосов
/ 30 октября 2011

В1. Я читал на нескольких веб-сайтах, где говорилось, что установка «0» для порта говорит ОС, что вы хотите следующий доступный порт, а не 0. Это правда?

Да, но только после того, как вы использовали bind(), чтобы прикрепить адрес к реальному сокету.В этот момент используйте getsockname(), чтобы получить связанный адрес из сокета;порт будет частью этого.

Q2: Я также читал, что gethostbyname (gethostname (...)) может дать вам IP-адрес машины, но Бидж сказал, что они заменены getaddrinfo().Итак, я должен использовать getaddrinfo?Или gethostbyname?

Использование getaddrinfo();он делает все, что сделал gethostbyname() и более, и интерфейс отстой намного меньше.(Например, обычно он ориентирован на многопотоковое исполнение.)

Q3: Есть ли что-то еще, что я делаю неправильно?

Нет четкого определения IP-адреса сервера.адрес.Серверов может быть много из-за таких вещей, как множественные сетевые карты (гораздо более распространенные для серверов, чем настольные системы), и тот, который знает об этом внешний мир, может и не быть одним из них (благодаря межсетевым экранам NAT).Иногда вы можете точно знать, откуда поступают сообщения до подключения клиента - наиболее распространенный вариант - знать, что клиент будет на localhost, что является частью информации, которую вы установили во время bind(), но это редко.Вы можете найти адрес клиента после установления соединения, используя getpeername(), но NAT все еще может сделать это функционально бесполезным.Такие адреса обычно задаются в файле конфигурации приложения во время развертывания.

Если вам нужна только информация для ведения журнала, продолжайте.Но остерегайтесь использовать его для чего-то еще, так как на самом деле это мало что говорит вам.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...