Есть ли какое-либо различие между IPv4 и IPv6 на уровне сокета?

Я должен добавить поддержку IPv6 существующему основанному на сокете приложению, которое в настоящее время только поддерживает IPv4. Для охвата входящей эры IPv6 кто-то приказал, чтобы я добавил интерфейс IPv6 для приложения и позволил внешнему миру для выбора интерфейса IPv4 или интерфейса IPv6 при попытке общаться с приложением.

Мой вопрос: действительно ли это верно что для сокета, обрабатывающего уровень API в Linux, нет никакого различия между обработкой основанного на IPv4 сокета и основанным на IPv6 сокетом?

Далее больше действительно ли возможно позволить сокету послушать на двух IP-адресах с тем же портом? Если это верно, то реализовать требование, тривиальная работа, я предполагаю.

9
задан Matt Ball 1 March 2010 в 05:44
поделиться

5 ответов

Невозможно прослушивать 2 разных IP-адреса с помощью одного TCP-сокета, однако если вы прослушиваете все интерфейсы, используя in6addr_any адрес, это будет включать все IPv4-адреса (хотя я полагаю, что, например, в linux есть опция ядра для отключения этого сопоставления).

API сокетов (новой версии) достаточно прозрачен в отношении того, используете ли вы IPv4 или IPv6, но необходимо проявлять большую осторожность в отношении того, как обычно кодируются приложения для IPv4.

Например, этот код IPv4, который принимает соединение и выводит адрес удаленного хоста:

 struct sockaddr_in client_addr;
 socklen_t addr_len = sizeof(client_addr);
 client_data->fd = accept(server_fd,(struct sockaddr*)&client_addr,&addr_len);
 log_printf("New client from %s\n",inet_ntoa(client_addr.sin_addr.s_addr));

Придется преобразовать в следующий, который работает и с IPv4, и с IPv6

 struct sockaddr_storage client_addr;
 char numeric_addr[INET6_ADDRSTRLEN];
 socklen_t addr_len = sizeof(client_addr);
 client_data->fd = accept(server_fd,(struct sockaddr*)&client_addr,&addr_len);
 if(client_addr.ss_family == AF_INET)
    log_printf("New client from %s\n",inet_ntop(client_addr.ss_family,((struct sockaddr_in*)&client_addr)->sin_addr.s_addr ,numeric_addr,sizeof numeric_addr));
 else if(client_addr.ss_family == AF_INET6)
    log_printf("New client from %s\n",inet_ntop(client_addr.ss_family,((struct sockaddr_in6*)&client_addr)->sin6_addr ,numeric_addr,sizeof numeric_addr));

Хотя я считаю, что это можно сделать еще более элегантно и прозрачно с помощью getaddrinfo()

Вот дополнительные заметки о независимости уровней IP: http://uw714doc.sco.com/en/SDK_netapi/sockC.PortIPv4appIPv6.html http://www.kame.net/newsletter/19980604/

6
ответ дан 3 November 2019 в 00:00
поделиться

Я считаю, что есть разница, в основном в том, как назначаются/отображаются IP-адреса и маски подсети.

Методы, которые принимают входящий IPv4-адрес, не будут работать и выдадут исключение, если им будет передан чистый IPv6, поэтому ваши методы должны будут проверять, какой тип соединения был инициирован, в остальном я так не думаю.

0
ответ дан 3 November 2019 в 00:00
поделиться

Большая часть работы с сокетами одинакова как для IPv4, так и для IPv6. На сервере, как только вы привязали свой адрес, вызовы listen, accept, recv и send будут работать одинаково как для IPv4, так и для IPv6 соединений.

Но все функции, работающие с адресами, такие как connect, bind, getsockname, getpeername, нужно будет изменить, так как вам нужно будет использовать sockaddr_in6. Также необходимо изменить функции, работающие с адресом (например, вызовы inet_addr необходимо изменить на inet_pton).

В Linux, если вы привяжетесь к in6addr_any, будут работать как IPv4, так и IPv6 соединения с этим портом (хотя это может прослушивать более 2 адресов, потому что он также будет прослушивать IPv4 loopback 127.0.0.1 и IPv6 loopback ::1). Но в Windows мне никогда не удавалось заставить это работать, и мне нужно прослушивать один сокет для IPv4 и другой сокет для IPv6.

4
ответ дан 3 November 2019 в 00:00
поделиться

IPv6 - это 128-битное адресное пространство и предлагает больше функций (без сохранения состояния, многоадресная передача, более простая обработка для маршрутизаторов, и многие другие) по сравнению с IPv4 (который является 32-битным), адресное пространство для IPv4 заканчивается, но с помощью NAT / SNAT это может увеличить долговечность протокола IPv4. Использование IPv6 зависит от того, поддерживает ли ОС новый протокол. Он, безусловно, доступен в Windows 7, Linux ... Главное, что IPv6 обратно совместим с IPv4 ...

Чтобы ответить на ваш вопрос, это зависит от уровня API, при условии, что ОС может поддерживать сетевой стек IPv6, Вот пример сокетов IPv6, который можно найти на MSDN , для Linux использование сокетов в основном такое же, за исключением того, что вы будете использовать sockaddr_in6 ...

Надеюсь, это поможет, С уважением, Том.

0
ответ дан 3 November 2019 в 00:00
поделиться

Руководство Биджа по сетевому программированию рассматривает различия в кодировании для IPv4 и IPv6. http://beej.us/guide/bgnet/

Он посвятил один раздел изменению существующего кода IPv4 для обработки IPv6.

Он также объясняет, как абстрактно кодировать на уровне сокета, так что вам не нужно знать, имеете ли вы дело с адресом IPv4 или IPv6.

2
ответ дан 3 November 2019 в 00:00
поделиться
Другие вопросы по тегам:

Похожие вопросы: