Подтвердить что ты не робот

Как поддерживать соединения IPv4 и IPv6

В настоящее время я работаю над приложением UDP-сокета, и мне нужно построить поддержку, чтобы соединения IPV4 и IPV6 могли отправлять пакеты на сервер.

Я надеялся, что кто-то может помочь мне и указать мне в правильном направлении; большая часть документации, которую я нашел, не была полной. Также было бы полезно, если бы вы могли указать на различия между Winsock и сокетами BSD.

Спасибо заранее!

4b9b3361

Ответ 1

Лучший подход - создать сокет сервера IPv6, который также может принимать соединения IPv4. Для этого создайте обычный сокет IPv6, отключите опцию сокета IPV6_V6ONLY, привяжите его к "любому" адресу и начните получать. Адреса IPv4 будут представлены как адреса IPv6 в формате IPv4-mapped.

Основное различие между системами - доступность IPV6_V6ONLY a), b) включение или выключение по умолчанию. Он отключается по умолчанию в Linux (т.е. Разрешает сокеты с двумя стеками без setsockopt) и включается в большинстве других систем.

Кроме того, стек IPv6 в Windows XP не поддерживает эту опцию. В этих случаях вам нужно создать два отдельных сокета сервера и поместить их в один или несколько потоков.

Ответ 2

API сокетов управляется IETF RFC и должен быть одинаковым на всех платформах, включая Windows WRT IPv6.

Для приложений IPv4/IPv6 это ВСЕ о getaddrinfo() и getnameinfo(). getaddrinfo - гений - рассматривает DNS, имена портов и возможности клиента для решения вечного вопроса "могу ли я использовать IPv4, IPv6 или оба для достижения определенного места назначения?" Или, если вы идете по пути двойного стека и хотите, чтобы он возвращал IPv4-адресам IPv4, он также сделает это.

Он предоставляет прямую структуру sockaddr *, которая может быть подключена к bind(), recvfrom(), sendto() и семейству адресов для socket()... Во многих случаях это означает, что беспорядочные структуры sockaddr_in(6) для заполнения и иметь дело с.

Для реализаций UDP я был бы осторожен в настройке сокетов с двумя стеками или, в более общем плане, привязке ко всем интерфейсам (INADDR_ANY). Классическая проблема заключается в том, что когда адреса не блокируются (см. bind()) для определенных интерфейсов, и система имеет несколько запросов интерфейсов, ответы могут проходить с разных адресов для компьютеров с несколькими адресами на основе прихотей таблицы маршрутизации ОС, запутывающие протоколы приложений, особенно любые системы с требованиями аутентификации.

Для реализаций UDP, где это не проблема, или TCP, двойные стековые сокеты могут сэкономить много времени, когда IPv * -изменяет вашу систему. Нужно быть осторожным, чтобы не полагаться полностью на двойной стек, где это не совсем необходимо, поскольку нет недостатка в разумных платформах (Old Linux, BSD, Windows 2003), развернутых с стеками IPv6, не способными к двойным сокетам сокета.

Ответ 3

Я играл с этим под Windows, и на самом деле это проблема безопасности, если вы привязываетесь к адресу loopback, тогда сокет IPv6 правильно связан с [:: 1], но сопоставленный сокет IPv4 привязанный к INADDR_ANY, поэтому ваше (предположительно) безопасное локальное приложение действительно доступно миру.

Ответ 4

RFC на самом деле не указывают на существование опции сокета IPV6_V6ONLY, но, если она отсутствует, RFC довольно ясно, что реализация должна быть такой, как если бы этот параметр был FALSE.

Если опция присутствует, я бы сказал, что она должна иметь значение по умолчанию FALSE, но, по причинам, передающим понимание, BSD и версии Windows по умолчанию имеют значение TRUE. Существует странное утверждение, что это проблема безопасности, потому что незнакомый программист IPv6 может связывать мысли, что они привязываются только к IN6ADDR_ANY только для IPv6 и случайно принимают соединение IPv4, вызывающее проблему безопасности. Я думаю, что это надуманно и абсурдно в дополнение к неожиданности для всех, кто ожидает реализацию, совместимую с RFC.

В случае Windows несоблюдение обычно не является неожиданностью. В случае BSD это в лучшем случае неудачно.