Используя сокеты TCP (C #), как я могу определить, было ли сообщение прервано при передаче на стороне получателя? - PullRequest
3 голосов
/ 03 июля 2011

Я пишу серверное приложение для своего приложения для iPhone. Раздел сервера, над которым я работаю, является сервером ретрансляции. Это по существу передает сообщения между iPhone, через сервер, используя сокеты TCP. Сервер считывает длину заголовка из потока, а затем считывает это количество байтов из потока. Он десериализует заголовок и проверяет, должно ли сообщение быть передано на другой iPhone (а не обрабатываться на сервере).

Если он должен быть передан, он начинает читать байты из сокета отправителя, по 1024 байта за раз. После получения каждых 1024 байтов эти байты (в виде «пакета» байтов) добавляются в очередь исходящих сообщений, которая обрабатывается по порядку.

Впрочем, это все нормально, но что произойдет, если отправитель будет прерван, поэтому он не отправит все свои байты (скажем, из 3000 байтов, которые ему пришлось отправить, отправляющий iPhone отправляется в туннель после 2500 байт)

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

Очевидно из приведенного выше описания, я использую кадрирование сообщений, но я думаю, что я что-то упустил. Из того, что я вижу, кадрирование сообщений только позволяет получателю узнать точное количество байтов для чтения из сокета, прежде чем собирать их в объект. Разве вещи не начинают становиться волосатыми, когда один или два байта сбиваются с пути в какой-то момент, что приводит к потере синхронизации? Есть ли стандартный способ снова вернуться в синхронизацию?

1 Ответ

3 голосов
/ 03 июля 2011

Разве вещи не начинают становиться волосатыми, когда один или два байта в какой-то момент сбиваются с пути, нарушая синхронизацию?Существует ли стандартный способ снова вернуться в синхронизацию?

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

В этом случае, вот несколько вариантов вне моей головы:

  • Пусть сервер буферизует сообщение whole из точки A перед отправкой его в точку B.
  • Закройте сокеты на стороне B, если обнаружено ненормальное закрытие со стороны A.
  • Измените принимающую сторону протокола, чтобы клиент на стороне B мог обнаруживать и восстанавливать частичный поток A, не прерывая и не восстанавливая сокет.например, если сервер дал уникальный идентификатор каждому входящему A-потоку, то B-клиент сможет определить, запускается ли другой поток.Или используйте дополнительный префикс длины, чтобы клиент B знал как ожидаемую длину, так и длину для этого отдельного сообщения.

Какой вариант вы выберете, зависит от типа передаваемых данных инасколько легко менять различные детали.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...