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

Хорошая вещь в таких языках, как Haskell (в F # она очень похожа, но я не знаю точного синтаксиса - это должно помочь вам понять ->, однако) в том, что вы можете применять только части аргумента, для создания карри функций:

adder n x y = n + x + y

Другими словами: «дай мне три вещи, и я сложу их вместе». Когда вы кидаете числа в него, компилятор выводит типы n x и y. Допустим, вы пишете

adder 1 2 3

Тип 1, 2 и 3 Int. Поэтому:

adder :: Int -> Int -> Int -> Int

То есть, дайте мне три целых числа, и я стану целым числом, в конце концов, или то же самое, что и сказать:

five :: Int
five = 5

Но вот хорошая часть ! Попробуйте это:

add5 = adder 5

Как вы помните, сумматор принимает int, int, int и возвращает вам int. Однако это не вся правда, как вы скоро увидите. Фактически, add5 будет иметь такой тип:

add5 :: Int -> Int -> Int

Это будет так, как если бы вы «сняли» целые числа (крайние левые) и приклеили их непосредственно к функции. Если присмотреться к сигнатуре функции, мы заметим, что -> являются ассоциативно-правыми, то есть:

addder :: Int -> (Int -> (Int -> Int))

Это должно прояснить это: когда вы дадите сумматору первое целое число, оно будет оцениваться любым справа от первой стрелки или:

add5andtwomore :: Int -> (Int -> Int)
add5andtwomore = adder 5

Теперь вы можете использовать add5andtwomore вместо «adder 5». Таким образом, вы можете применить другое целое число, чтобы получить (скажем) «add5and7andonemore»:

add5and7andonemore :: Int -> Int
add5and7andonemore = adder 5 7

Как видите, add5and7andonemore хочет точно другой аргумент, и когда вы его дадите, он внезапно станет целым числом!

  > add5and7andonemore 9
 => ((add5andtwomore) 7) 9
 => ((adder 5) 7) 9)
<=> adder 5 7 9

Подставляя параметры к сумматору (nxy) для (5 7 9), мы получаем:

  > adder 5 7 9 = 5 + 7 + 9
 => 5 + 7 + 9
 => 21

На самом деле , плюс также является просто функция, которая принимает целое число и возвращает вам другое целое число, поэтому вышеприведенное действительно больше похоже на:

  > 5 + 7 + 9
 => (+ 5 (+ 7 9))
 => (+ 5 16)
 => 21

Вот, пожалуйста!

52
задан James McNellis 24 October 2009 в 04:24
поделиться

3 ответа

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

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

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

80
ответ дан 7 November 2019 в 09:22
поделиться

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

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

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

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

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

7
ответ дан 7 November 2019 в 09:22
поделиться

В RFC на самом деле не указывается наличие опции сокета IPV6_V6ONLY, но, если она отсутствует, RFC довольно ясно указывают, что реализация должна быть такой, как если бы эта опция была ЛОЖНОЙ.

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

В случае Windows несоблюдение требований обычно не является сюрпризом. В случае с BSD это в лучшем случае прискорбно.

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

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