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