getaddrinfo и getnameinfo являются вашими друзьями .. Насколько это возможно, я предлагаю вам быть лучшими друзьями в вашем стремлении предоставить поддержку IPv4 и IPv6 в существующем приложении.
Если вы сделаете это правильно, добавив поддержку IPv6, вы также завершите абстрагирование системы до того момента, когда неизвестный будущий IP-протокол может работать без изменения кода.
Обычно при подключении вы бы заполнить структуру сокета, порт, семейство адресов, IP-адрес, преобразования адресов/портов в сетевой порядок байтов, и т.д.
С getaddrinfo
отправке IP-адрес или имя хоста и порт или имя порта и возвращает связанный список со структурами и все готовые для передачи непосредственно в socket()
и connect()
.
getaddrinfo
имеет решающее значение для работы как с IP-протоколами, как он знает, что если узел имеет IPv6 или IPv4 подключение и он знает, если равноправная делает, а глядя на DNS AAAA
против A
записей и динамически выясняет, какой протокол (ы) доступны для обслуживания конкретного запроса на соединение.
Я настоятельно рекомендую использовать inet_pton()
, inet_addr()
или знакомые устройства, имеющие конкретную IP-версию. На платформе Windows конкретно inet_pton()
несовместим с более ранними версиями MS Windows (XP, 2003 и др.), Если вы не сворачиваете свои собственные. Также советуйте против отдельных версий для IPv4 и IPv6 ... Это неработоспособно как техническое решение, потому что в ближайшем будущем оба протокола должны будут использоваться одновременно, и люди могут не знать заранее, что использовать. Интерфейсы сокетов являются абстрактными, и легко обнаружить поддержку dualstack или IPv6, пытаясь создать сокет IPv6 или попытаться установить опцию сокета для двойного стека IPv6 для слушателей. Нет причин, по которым результирующее приложение не будет работать в системе, которая не поддерживает или не знает о IPv6.
Для исходящих соединений используйте PF_UNSPEC
в getaddrinfo
, чтобы семейство адресов выбрано для вас при выполнении исходящих подключений. Это, ИМХО, лучше, чем двойной подход, потому что он позволяет платформам, которые не поддерживают работу двойного стека.
Для входящих подключений вы можете подключать разъемы IPv4/IPv6 отдельно, если это разумно, учитывая дизайн или использование двойного стека, если вы не можете делать отдельные прослушиватели. При использовании doublestack getnameinfo
возвращает IPv6-адрес для адресов IPv4, который ИМХО оказывается совершенно бесполезным. Небольшая утилита может преобразовать строку в обычный IPv4-адрес.
Из моего опыта, когда все сделано правильно, вы удалили зависимости от определенных версий IP и закончили с меньшим кодом управления сокетами, чем вы начали.
Стоит также отметить, что все эти вызовы обычно переносимы между Windows, Mac OS X и Linux с небольшими различиями здесь и там. –