Предыстория: у меня очень простая серверная программа, написанная на PHP. В основном это работает, но только до тех пор, пока на сайт не больше одного клиента.
Вопросы:
Маршрутизатор для сети 192.168.1.x назначает каждому исходящему соединению уникальный порт источника на стороне Интернета. Когда маршрутизатор получает ответ, он ищет порт, на который был отправлен пакет, в своей таблице NAT и сообщает ему, какой IP-адрес и порт следует указать в качестве пункта назначения на стороне LAN.
Когда пакет пересылается из локальной сети в сторону Интернета, маршрутизатор проверяет свою таблицу NAT. Если нет записи, соответствующей этому локальному исходному IP-адресу, локальному исходному порту, удаленному IP-адресу и удаленному порту, создается одна. Назначен новый адрес порта назначения. Пакет отправляется в Интернет, причем исходный IP-адрес перезаписывается на Интернет-IP-адрес маршрутизатора, а исходный порт перезаписывается на назначенный исходный порт.
Когда пакет получен на стороне Интернета, маршрутизатор проверяет порт назначения в своей таблице NAT. Если нет записи, соответствующей этому удаленному IP-адресу и порту назначения, пакет отбрасывается (если этого не требует другой маршрутизатор). Если это так, IP-адрес назначения изменяется на правильный локальный IP-адрес, порт назначения изменяется на исходный локальный порт источника, и пакет отправляется в локальную сеть.
«Уникальный идентификатор», о котором вы говорите, представляет собой комбинацию удаленного IP-адреса, с которым локальный компьютер хочет установить связь, и локального порта источника, выбранного маршрутизатором.
Маршрутизаторы NAT перепишут источник ориг-ip: ориг-порт кортеж исходящих UDP-пакетов для нат-ip: нат-порт и вести таблицу отношений между ориг-ip: ориг-порт и нат-ip: нат-порт поэтому пакеты ответов UDP, прибывающие с нат-ip: нат-порт так как пункт назначения может быть сопоставлен с ориг-ip: ориг-порт место назначения. Подробнее о том, как реализация NAT может справиться с ситуацией, см. как отслеживание соединений реализовано в Linux.
Если ваша реализация не позволяет изменять номер порта клиента, это просто не гарантирует работу за маршрутизаторами NAT. Он может работать для одного клиента, так как многие реализации будут пытаться использовать тот же номер порта источника, что и исходный пакет, если он доступен, поэтому нат-порт будет равно ориг-порт для первого подключения клиента. Но по мере того, как этот порт становится недоступным, последующие попытки неизбежно приведут к состоянию, когда нат-порт отличается от ориг-порт.
Таким образом, основным «ключом», который вам нужно будет различать между разными клиентами, будет исходный UDP-порт клиента. Ваше серверное чат-приложение должно генерировать UDP-пакеты, идущие на тот же порт назначения, из которого он получил клиентский пакет, инициирующий чат-соединение, - создавая практически ту же ситуацию, что и у установленных TCP-сессий.