Как создать P2P-соединение, когда оба клиента находятся за NAT

Возможно ли установить прямое соединение между двумя клиентами, которые находятся за разными NAT? Конечно, я понимаю, что в какой-то степени сервер с открытым IP-адресом будет иметь важное значение, но я не хочу, чтобы он был прокси-сервером. Взгляните на следующий сценарий:

  • Я не хочу, чтобы anythig делать с настройкой сетевых устройств. Я просто хочу сделать это в коде.
  • Я не хочу, чтобы сервер принимал участие в процессе передачи файлов (по соображениям производительности)
  • у нас есть клиент A, клиент B и сервер S, и он выглядит примерно так:

А – [Роутер1] – S – [Роутер2] – B

  • A подключается к S и разрешает
  • B подключается к S и разрешает
  • A хочет отправить файл в B
  • A запрашивает S для соединения с B
  • S [здесь магия], и теперь A имеет связь с B
  • A начинает отправлять файл
  • S идет вниз (или, по крайней мере, обходы передачи файлов)
  • все еще существует связь между A и B
  • A продолжает отправку файла в B

Мои вопросы:

  1. Это возможно?
  2. Как это сделать?
  3. Вы столкнулись с примером проекта, который может это сделать?

Я нашел приложение чата WCF / WPF , но оказалось, что это прокси.

Я также нашел некоторые сообщения, предлагающие использовать UPnP и NAT Traversal, но никто не ответил на мой первый вопрос напрямую, поэтому я не глубоко вникнул в него.

Термин, который вы ищете «волшебную часть», называется NAT Hole Punching . К сожалению, тема слишком широка, чтобы полностью объяснить здесь, как ее выполнить, но теперь, зная, что правильный термин должен, по крайней мере, помочь вам начать поиск правильных учебников.

Вот краткое изложение алгоритма на странице UDP Hole Punching .

Пусть A и B – два хоста, каждый в своей собственной частной сети; N1 и N2 – два устройства NAT с глобально достижимыми IP-адресами P1 и P2 соответственно; S – это общеansible сервер с общедоступным IP-адресом, доступным по всему миру.

  1. A и B начинаются с UDP-разговора с S; NAT-устройства N1 и N2 создают состояния преобразования UDP и назначают временные номера внешних портов X и Y
  2. S проверяет пакеты UDP для получения исходного порта, используемого N1 и N2 (внешние NAT-порты X и Y)
  3. S передает P1: от X до B и P2: от Y до A
  4. A отправляет пакет в P2: Y и B отправляет пакет в P1: X, используя тот же исходный порт, что и разговор с S, таким образом, «пробивая» отверстие в NAT по отношению к другому хосту
  5. Если какой-либо хост получает пакет, удары отверстий удачны, и оба узла могут обмениваться данными.

Если на обоих хостах есть NAT с ограниченным конусом или симметричные NAT , внешние порты NAT будут отличаться от внешних, используемых с S. На некоторых маршрутизаторах внешние порты выбираются последовательно, что позволяет установить беседу путем гадания соседних портов.

Независимо от того, будет ли он работать, сильно зависит от того, как ведут себя маршрутизаторы NAT конечной точки, очень вероятно, что значительная часть ваших применений будет спарена, и у обоих есть маршрутизаторы, которые не являются «дружественными отверстиями».

В вашей ситуации я бы попросил мое программное обеспечение выполнить эти шаги.

  1. Проверьте и посмотрите, можно ли просто подключиться (пользователь выполнил ручную переадресацию портов)
  2. Используйте UPnP и откройте порт
  3. Используйте ту или иную форму пробивки отверстий с использованием общедоступного сервера, поскольку
  4. Используйте другой одноранговый узел, который имеет порты, открытые как прокси для данных ( сверхновости ).
  5. Используйте сервер, который я размещаю в качестве прокси для пересылки данных.