Должен ли мой сервер использовать TCP и UDP?

Я пишу приложение клиент/сервер и действительно не могу найти руководства, которые соответствуют моим потребностям. Выполнение этого самостоятельно приводит меня ко многим недостаткам дизайна, прежде чем я даже начал. Например, сервер должен обновлять каждый клиент по своему состоянию много раз каждую секунду. Я предположил, что не могу обновлять каждый клиент отдельно, но UDP-трансляции должны это исправить. Но мне по-прежнему нужен канал TCP, который надежно связывается с каждым клиентом для таких вещей, как: сообщения чата, ввод пользователя и т.д.

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


Теперь я очень смущен тем, как я должен обрабатывать данные на своем сервере. Если я полностью не понял что-то о потере пакетов, я хочу гарантировать, что пользовательский ввод, приводящий к "сервер-запрос-пакеты", не будет потерян. Каждый ответ на SO о гарантии доставки с UDP говорит, что обязательно, используйте TCP. Что еще более расстраивает, так это то, что каждая серверная/клиентская программа, которую я могу себе представить, по крайней мере, требует, чтобы некоторые из ее сообщений были гарантированно доставлены (например, "отключить" сообщения?).

Должен ли я использовать UDP, TCP, оба или я просто думаю совершенно неправильно об этом?

Ответ 1

Позволяет получить некоторые факты в таблице:

  • UDP не является надежным. Когда-нибудь.

  • При некоторых обстоятельствах UDP может быть особенно убыточным; например если есть перегрузка сети, ограничение скорости или профилирование трафика или размер сообщения UDP больше, чем MTU.

  • Передача UDP работает только в сегменте локальной сети. Интернет-маршрутизаторы обычно не позволяют широковещательным вещам распространяться дальше. Это действительно ограничивает его полезность.

  • Многоадресная рассылка по протоколу UDP может быть возможна, за исключением того, что она также блокируется.

Таким образом, это, вероятно, оставляет вам две основные возможности:

  • Обмен сообщениями "точка-точка" UDP с вашего сервера каждому из клиентов.
  • TCP от сервера к каждому из клиентов.

Другая возможность - это некоторая взаимная связь между сетями, использующая UDP или TCP, но это становится очень сложным. Не ходите туда, если вам действительно не нужно, и действительно знаете, что вы делаете.

Итак, на ваш вопрос.

Должен ли я использовать UDP, TCP, оба или я просто думаю совершенно неправильно об этом?

Я рекомендую использовать TCP между сервером и каждым клиентом, потому что он прост. Чтобы упростить еще больше, используйте несколько TCP-соединений для каждого клиента, чтобы избежать сложности мультиплексирования нескольких "разговоров" в одном сокете.

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

Когда вы доберетесь до рабочего приложения (стороны клиента и сервера), и есть люди, которые его используют, вы можете найти (или нет!), что сетевое взаимодействие является основным узким местом и вызывает неудовлетворенность пользователей. Затем вы смотрите на оптимизацию сообщений в версии 2.0 вашего приложения.

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

Ответ 2

.. но UDP-трансляции должны исправить это.

широковещательная работа только внутри локальной сети, и соответствующая многоадресная рассылка нуждается в поддержке инфраструктуры - не тривиальной.

Кроме того: нет общего правила для "..приложения приложения клиент/сервер...". Методы и протоколы связи в значительной степени зависят от варианта использования и могут варьироваться от простых UDP или TCP-пакетов до сложных архитектур передачи сообщений с надежностью и гарантиями в реальном времени и т.д.

Таким образом, то, что вам нужно сделать, зависит от того, чего вы пытаетесь достичь, чего вы не указали достаточно подробно.

Ответ 3

Забудьте о широковещательных протоколах, они просто не работают, как кто-то уже написал. Вам нужно доставить сообщение каждому клиенту, создать класс StateChangeDispatcher или что-то в этом роде.

UDP не является надежным, но быстрее, чем TCP, учитывая, что нет рукопожатия. Рукопожатие не только медленное, но и небольшая полоса пропускания, затрачиваемая в первую очередь, когда вам нужно установить соединение с большим количеством клиентов.

Использование UDP и TCP не так уж плохо, многие известные программы используют этот подход. Например, BitTorrent может использовать оба протокола: UDP для связи с трекером и управлять DHT и TCP для передачи куска файлов. То, что мое объяснение относительно их выбора: трекер или DHT периодически допрашивается, это означает, что за один день использования вы могли бы обновлять свой трекер сотни раз, если несколько раз это не сработало, это не очень важно, потому что вы обновляя ваш трекер в любой момент (такая же идея содержится в протоколе DNS, вы отправляете свой запрос через UDP, если вы не получили ответ в течение разумного промежутка времени, просто повторите запрос). Вместо этого протокол TCP ДОЛЖЕН использоваться для передачи файлов, потому что вы предпочитаете работать медленнее, но вы хотите абсолютную надежность.

Другим известным приложением, использующим оба протокола, является Skype, но по разным причинам. Видеозвонки UDP, потому что TCP-протокол при получении неправильного пакета останавливается и снова запрашивает пакет, для этого требуется время. Поэтому предпочтительнее не останавливать вызов, а получать и обрабатывать неправильный пакет. Поэтому в скайпе вы иногда получаете плохое видео или непонятное аудио, вы можете получать видео, так как оно является рекордером, но оно слишком медленное. TCP используется для других вещей, таких как отправка файлов.

Таким образом, вы должны отправлять сообщения нескольким клиентам много раз в секунду. Я бы не установил новое TCP-соединение для каждого сообщения. По-моему, у вас есть два варианта:

  • отправлять каждое изменение состояния сервера через UDP тогда и только тогда, когда вы можете позволить себе потерю данных
  • Установить одно TCP-соединение для каждого клиента и с этим соединением отправить все изменения состояния сервера, чем закрыть соединение, когда клиент отключит

Известный протокол, использующий два TCP-соединения, - FTP, у вас есть одно соединение для отправки заказов и получения ответов на сервер и одно соединение для отправки и получения файлов, помните, что вы не устанавливаете соединение для каждой команды, даже если команды могут быть отложены очень разнесенными во времени (конечно, более чем много раз в секунду), чтобы избежать слишком большого количества рукопожатий. У вас есть много шаблонов, за которыми вы можете следовать, но помните, что протоколы тестирования дороги (вам нужно много времени, и вам может понадобиться более 10 компьютеров, чтобы увидеть, все ли работает), поэтому хорошо подумайте перед началом кодирования, в Интернете вы можете найти некоторые математические методы для расчета производительности протокола и использования полосы пропускания, но они не очень просты. Удачи.

Ответ 4

Тот же принцип, что и вы, используется на DNS-серверах. DNS обычно использует UDP для передачи QUICKLY (принцип протокола UDP), но не надежно. TCP медленнее (с ACK и полезной нагрузкой), но надежным. Итак, как я обрезаю ниже, используйте оба, различайте по полезной нагрузке.

Из документации DNS BIND:

Обычно обычные запросы используют UDP, а в зонах передачи используется TCP.

Однако DNS ограничивает запросы UDP и ответы на 500 байтов. Если ответ будет больше, чем сервер, сервер отправляет обратно до 500 байтов и устанавливает флаг "усеченный". Затем клиент должен повторите тот же запрос, используя TCP, который почти неограничен в размер ответа, который он может отправить...

Если вы хотите обновить ВСЕ серверы за один раз, зарегистрируйте их в MULTICAST и одним процессом, с которым вы общаетесь со всеми клиентскими серверами. Это снова ненадежно, но быстро. https://en.wikipedia.org/wiki/IP_multicast Таким образом, вы создаете сервер, на который будут регистрироваться партнеры многоадресной рассылки и выслушайте его. Чтобы убедиться, что вы обнаруживаете, что датаграммы UDP отбрасываются на маршруте, каждая датаграмма UD имеет свой идентификационный номер. Убедитесь, что вы также можете получать датаграммы в другом порядке, в котором вы их отправляете, поэтому необходимо использовать BUFFER или QUEUE, вычисляя правильный порядок.

Надеюсь, что это поможет.

Ответ 5

Если это клиентская/серверная игра, например Action Game, я рекомендую вам TCP для пользовательского интерфейса, вы НЕ хотите потерять данные пользователей, но In-Game вы не можете позволить себе общение в TCP в быстродействующей многопользовательской игре.

Потому что потеря "некоторой" информации не так уж плоха в игре Action, поэтому я бы порекомендовал UDP в игре или везде, где вам нужна ОЧЕНЬ быстрая связь.

Но если это не игра, которая нуждается в быстрой связи, я бы рекомендовал вам TCP.

Ответ 6

Мне кажется, вы думаете о надежном методе коммуникации между клиентом и сервером, который будет похож на широковещательную передачу без служебной связи TCP/IP.

Я также могу порекомендовать вам использовать Messaging. Создайте сообщение-привод bean (или клиент сообщения, коммюмер), который будет зарегистрирован в канале сообщения или очереди сообщений и активируется по методу PUSH.

Ваш производитель сообщений создает одно сообщение, и все остальные зарегистрированные клиентские серверы (потребители) будут проинформированы об этом и будут обрабатывать его асинхронно. Вы можете использовать любую платформу, а также apache MQ с открытым исходным кодом. https://en.wikipedia.org/wiki/Message_queue