Алгоритм штамповки отверстий UDP

Кто-нибудь может привести пример UDP Hole Punching?

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

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

2 ответа

Решение

Краткий ответ: это невозможно сделать надежно.

Длинный ответ:

"Перфорация отверстий" относится к запуску автоматических правил NAT маршрутизатора, чтобы разрешить входящий трафик. Когда вы отправляете UDP-пакет, маршрутизатор (обычно) создает временное правило, отображающее ваш исходный адрес и порт на адрес и порт назначения, и наоборот. UDP-пакеты, возвращающиеся с адреса и порта назначения (и не из других), передаются в исходный адрес и порт источника (и не из других). Это правило истекает через несколько минут бездействия.

Чтобы это работало, когда обе конечные точки находятся за NAT или межсетевыми экранами, потребуется, чтобы обе конечные точки отправляли пакеты друг другу примерно в одно и то же время. Это означает, что обеим сторонам необходимо знать общедоступные IP-адреса и номера портов друг друга и сообщать их друг другу другими способами.

Программа не может напрямую определить свой собственный публичный IP-адрес, если она находится за NAT (она будет видеть только свой частный адрес, такой как 192.168.x.x). Но так как вы предполагаете, что вовлеченные люди знают IP-адреса друг друга, эти люди могут просто ввести адрес другого.

Но реальная выгода в том, что у программы также нет возможности напрямую определить, какой номер порта использует маршрутизатор на публичной стороне. Ваша программа может быть привязана к 12345 на локальном компьютере, но маршрутизатор может сопоставить ее практически с любым портом на общедоступной стороне. (Представьте, что два компьютера в вашей локальной сети отправляют сообщения через порт 12345, очевидно, что маршрутизатору придется сопоставить один из них с другим номером.) Поэтому даже если вы и люди можете знать, с каким номером локального порта вы связаны, существует нет способа узнать, какой номер порта маршрутизатор покажет миру.

Сетевая библиотека Лидгрена имеет эту встроенную функциональность. После добавления библиотеки в ваше приложение вы должны создать экземпляр NetServer, подключить два NetClients и вызвать NetServer.Introduce().

Ссылка на Лидгрен: https://github.com/lidgren/lidgren-network-gen3

Другие вопросы по тегам