Сервер XMMP отправляет push-уведомления клиенту за NAT, используя общедоступную конечную точку (IP + порт), предоставляемую NAT клиенту. Но как долго эта конечная точка назначается этому конкретному клиенту с помощью NAT, что произойдет, если NAT назначит ту же конечную точку другому клиенту? Как можно решить эту проблему?
Будет ли XMPP работать в среде NAT?
Ответы (2)
XMPP использует стандартное соединение TCP. NAT будут поддерживать ассоциацию до тех пор, пока соединение живо (если только они не будут разорваны).
Обновление: последнюю часть моего утверждения можно было бы немного расширить. Ужасно сломанные реализации NAT существуют. Как правило, это небольшой процент, но многие (наиболее?) популярные клиенты XMPP гарантируют, что они отправляют какие-либо сообщения проверки активности по незанятым соединениям.
Существует три типа поддержки активности, которые вы можете использовать. Я перечислю их здесь в порядке требований к пропускной способности/обработке:
Протоколы TCP Keepalive — хороший облегченный вариант, тем более что после их включения ОС автоматически обрабатывает их. Как их включить, будет зависеть от вашего языка и фреймворка, но на самом низком уровне вам нужно включить параметр SO_KEEPALIVE
в сокете.
Есть две проблемы с поддержкой активности TCP. Во-первых, вы не можете управлять ими из своего приложения (если только вы не пишете код для конкретной платформы). Вторая проблема заключается в том, что некоторые реализации NAT настолько сломаны, что они также будут игнорировать сообщения поддержки активности TCP! Но мы надеемся, что сейчас вы опустились до очень небольшого процента.
Таким образом, другой вариант — сохранение активности с пробелами. Поскольку они связаны с передачей данных через поток, вы должны быть в безопасности даже от сломанных NAT, которые игнорируют сообщения поддержки активности.
Подтверждение активности пробела просто включает отправку символа пробела (' ') через поток XMPP в любое время, когда он не используется. XML и XMPP допускают неограниченное количество пробелов между элементами, и получатель их просто игнорирует.
Наконец, вы можете использовать полноценные эхо-запросы XMPP (XEP-0199). Они включают в себя завершение фактической строфы <iq/>
'get' для сервера, который затем должен ответить. Это гарантирует потоки данных в обоих направлениях, и даже самые неработающие реализации NAT должны поддерживать ваше соединение.
Хорошо, я должен упомянуть, что есть еще худший класс NAT. Я видел NAT, которые просто «забудут» о вашем отображении по целому ряду причин, в том числе при заполнении их таблицы сопоставления или сразу после таймера. Вы ничего не можете сделать, чтобы обойти это, они не работают ни с какими долгоживущими TCP-соединениями. Лучшее, что вы могли бы сделать на этом этапе, это использовать BOSH (по сути, XMPP вместо HTTP).
Вывод. Если вы обеспокоены тем, что ваше приложение может работать на некоторых из этих устройств, я предлагаю что-то вроде следующего алгоритма (точное время может быть изменено, но я рекомендую эти значения как минимальные):
- Если вы не отправляли никаких данных за 60 секунд, отправьте один символ пробела.
- Если вы не получили никаких данных за 120 секунд, отправьте пинг XMPP на свой сервер.
- Если сервер не отвечает на пинг в течение разумного промежутка времени, переподключитесь.
Поскольку поведение неисправных устройств NAT выходит за рамки любой спецификации стандартного протокола, естественно невозможно разработать идеальное решение, которое будет работать со всеми из них все время. Вы просто должны признать, что это незначительное меньшинство, и все это не имеет значения для работающих устройств NAT (хотя есть и другие виды сбоев в сети, которые могут сделать регулярные проверки активности/пинги хорошей идеей, в зависимости от потребностей вашего приложения).
Решение отправляет сообщения подтверждения активности для поддержания записи NAT. Обычно используется пробел XMPP. Отправляйте его, например, каждые десять минут, чтобы сохранить достижимость родного клиента.
Вы должны иметь в виду, что NAT не является стандартизированным методом. Таким образом, существуют разные реализации. Предоставленные RFC в комментарии выше принадлежат рабочей группе BEHAVE.