Russian Qt Forum
Ноябрь 23, 2024, 20:45 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: gethostbyname, getaddrinfo  (Прочитано 7867 раз)
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« : Ноябрь 20, 2011, 10:57 »

Добрый день

Сетью приходится заниматься раз в несколько лет, устранять баги в чужом коде. Поэтому мои познания здесь нулевые Улыбающийся Отловил такой баг
Код
C++ (Qt)
void DomainToIP(const char* iDomainAddress, UInt32 & oIPAddress)
{
struct hostent * hostinfo = gethostbyname(iDomainAddress);
if (hostinfo)
oIPAddress = *(reinterpret_cast<UInt32*>(hostinfo->h_addr_list[0]));
else
throw BadNameException();
 
oIPAddress = ntohl(oIPAddress);
}
 
Раз на несколько тысяч вызовов gethostbyname возвращает NULL. Входная строка (iDomainAddress) всегда одна и та же: Macinrosh.local
Ладно, гуглю. Ага, gethostbyname использовать не рекомендуют. Подлатал  так

Код
C++ (Qt)
void DomainToIP(const char* iDomainAddress, UInt32 & oIPAddress)
{
struct hostent * hostinfo = gethostbyname(iDomainAddress);
if (hostinfo)
oIPAddress = *(reinterpret_cast<UInt32*>(hostinfo->h_addr_list[0]));
else {
struct addrinfo * result = 0;
int error = getaddrinfo(iDomainAddress, NULL, NULL, &result);
if (!error && !result) error = -1;
if (!error)
oIPAddress = *(reinterpret_cast<UInt32*> (result->ai_addr->sa_data + 2));
 
if (result)
freeaddrinfo(result);
 
if (error || oIPAddress == 0)
throw BadNameException();
}
 
oIPAddress = ntohl(oIPAddress);
}
Это работает заметно лучше но все же иногда oIPAddress получается = 0.

Вопросы:

1) Есть ли ф-ция для взятия IP адреса без уродливого reinterpret_cast ?

2) Не понимаю "прынцыпов" - конфигурацию сети никто не трогал, почему ф-ции иногда не видят IP ?

3) Могу ли я (корректно ли) поставить кэш std::map <std::string, UInt32> рассчитывая что IP останется неизменным для того же имени ?

Спасибо
Записан
SimpleSunny
Гость
« Ответ #1 : Ноябрь 20, 2011, 12:11 »

При неудачном вызове gethostbyname проверяйте код ошибки в h_errno
Цитировать
Переменная h_errno может принимать следующие значения:
HOST_NOT_FOUND
    Указанный хост неизвестен.
NO_ADDRESS или NO_DATA
    Запрошенное имя существует, но не имеет IP-адреса.
NO_RECOVERY
    Hепоправимая ошибка сервера имен.
TRY_AGAIN
    Временная ошибка на официальном сервере имен. Повторите попытку позже.
const char *hstrerror(int err); - вернет текстовое описание ошибки

Для getaddrinfo проверяйте код возвращаемой ошибки.
const char *gai_strerror(int errcode);

Возможно ошибка просто во временной недоступности ДНС сервера.

И используйте какой-то один из методов либо gethostbyname, либо getaddrinfo, а то смотрится как-то странно.
« Последнее редактирование: Ноябрь 20, 2011, 12:13 от SimpleSunny » Записан
BRE
Гость
« Ответ #2 : Ноябрь 20, 2011, 13:00 »

И используйте какой-то один из методов либо gethostbyname, либо getaddrinfo, а то смотрится как-то странно.
плюс к сказанному... gethostbyname не умеет IPv6, в отличие от...
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #3 : Ноябрь 20, 2011, 13:26 »

плюс к сказанному... gethostbyname не умеет IPv6, в отличие от...
Ну говорят "doesn't work well with IPv6."  http://beej.us/guide/bgnet/output/html/multipage/gethostbynameman.html

При неудачном вызове gethostbyname проверяйте код ошибки в h_errno
...
Для getaddrinfo проверяйте код возвращаемой ошибки.
...
Возможно ошибка просто во временной недоступности ДНС сервера.
Понял, спасибо

И используйте какой-то один из методов либо gethostbyname, либо getaddrinfo, а то смотрится как-то странно.
То да, но если я чужой код снесу - я потом его не вспомню. А закомментированный смотрится никак не лучше  Улыбающийся
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #4 : Ноябрь 20, 2011, 13:57 »

Хмм... если gethostbyname возвращает NULL, то h_errno = 1 (HOST_NOT_FOUND).
А getaddrinfo не выдает ошибок, но IP = 0  Плачущий

Не хочу быть навязчивым, но все же
3) Могу ли я (корректно ли) поставить кэш std::map <std::string, UInt32> рассчитывая что IP останется неизменным для того же имени ?
Т.к. ситуация возникает раз на много тысяч вызовов
Записан
BRE
Гость
« Ответ #5 : Ноябрь 20, 2011, 15:33 »

3) Могу ли я (корректно ли) поставить кэш std::map <std::string, UInt32> рассчитывая что IP останется неизменным для того же имени ?
А какое время жизни этого кеша?
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #6 : Ноябрь 20, 2011, 15:38 »

А какое время жизни этого кеша?
От одного запуска до другого (просто static). Пользователь (давно) предупрежден что надо выйти из приложения если понадобилось поменять настройки сети
Записан
BRE
Гость
« Ответ #7 : Ноябрь 20, 2011, 15:40 »

От одного запуска до другого (просто static). Пользователь (давно) предупрежден что надо выйти из приложения если понадобилось поменять настройки сети
Думаю можно сделать так. Вести свой кеш, а если вдруг удаленная сторона перестала отвечать по адресу из кеша - перезапрашивать заново информацию у DNS-сервера и обновлять кеш.
« Последнее редактирование: Ноябрь 20, 2011, 15:44 от BRE » Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #8 : Ноябрь 20, 2011, 16:37 »

Думаю можно сделать так. Вести свой кеш, а если вдруг удаленная сторона перестала отвечать по адресу из кеша - перезапрашивать заново информацию у DNS-сервера и обновлять кеш.
В чужом (и весьма обильном) коде сложно понять как же полученный IP используется. Как минимум вижу что он участвует в вычислении имени фолдера куда складываются полученные файлы. Рискну и поставлю кэш (если что верну назад)

Спасибо
Записан
LisandreL
Птица говорун
*****
Offline Offline

Сообщений: 984


Надо улыбаться


Просмотр профиля
« Ответ #9 : Ноябрь 20, 2011, 17:48 »

Раз на несколько тысяч вызовов gethostbyname возвращает NULL
Посмотреть, возвращает ли раз в те же тысячу раз QHostInfo::fromName( "Macinrosh.local" ).addresses() пустой список.
Если нет, то смотреть реализацию.
Но вероятнее всего просто затупы местного DNS-сервера (не отвечает или не укладывается в тайм-аут) и можно в случае NULL'а надо запрашивать повторно (ограничив максимальное число повторений.
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.146 секунд. Запросов: 22.