Краткий ответ: это невозможно сделать надежно.
Длинный ответ:
«Отверстие в отверстии» относится к запуску автоматических правил NAT маршрутизатора для разрешения входящего трафика. Когда вы отправляете UDP-пакет, маршрутизатор (обычно) создает временное правило, отображающее ваш исходный адрес и порт на целевой адрес и порт, и наоборот. UDP-пакеты, возвращающиеся с адреса и порта назначения (и не из других), передаются в исходный адрес и порт источника (и не из других). Это правило истекает через несколько минут бездействия.
Чтобы это работало, когда обе конечные точки находятся за NAT или межсетевые экраны, потребовали бы, чтобы обе конечные точки отправляли пакеты друг другу примерно в одно и то же время. Это означает, что обеим сторонам необходимо знать публичные IP-адреса и номера портов друг друга, а также сообщать об этом друг другу другими способами.
Программа не может напрямую определить свой собственный публичный IP-адрес, если она находится за NAT (она будет видеть только свой частный адрес, такой как 192.168.x.x
). Но поскольку вы предполагаете, что вовлеченные люди знают IP-адреса друг друга, эти люди могут просто ввести адрес другого.
Но настоящая загвоздка в том, что у программы также нет возможности напрямую определить, какой номер порта использует маршрутизатор на публичной стороне. Ваша программа может быть привязана к 12345 на локальном компьютере, но маршрутизатор может сопоставить ее практически с любым портом на общедоступной стороне. (Представьте, что два компьютера в вашей локальной сети отправляют сообщения через порт 12345, очевидно, маршрутизатору придется сопоставить один из них с другим номером.) Поэтому даже если вы и люди можете знать, с каким номером локального порта вы связаны, существует нет способа узнать, какой номер порта маршрутизатор покажет миру.