Основы протокола сокетов - PullRequest
11 голосов
/ 03 марта 2010

Недавно, читая Socket Programming HOWTO , у меня выскочил следующий раздел:

Но если вы планируете повторно использовать свой сокет для дальнейшей передачи, вам необходимо понимать, что в сокете нет "EOT" (End of Transfer). Повторюсь: если сокет send или recv возвращается после обработки 0 байтов, соединение разорвано. Если соединение не было разорвано, вы можете ждать на recv вечно, потому что сокет не скажет вам, что больше нечего читать (пока). Теперь, если вы немного подумаете об этом, вы поймете фундаментальную истину о сокетах: сообщения должны быть либо фиксированной длины (фу), либо с разделителями (пожимание плечами), или указывает, как долго они (намного лучше), или завершается отключением соединения . Выбор остается за вами (но некоторые пути вернее других).

В этом разделе рассматриваются 4 возможности написания сокета-протокола для передачи сообщений. У меня вопрос, какой метод предпочтительнее использовать для реальных приложений?

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

Ответы [ 5 ]

5 голосов
/ 03 марта 2010

Общие протоколы либо указывают длину в заголовке, либо разделяются (например, HTTP).

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

2 голосов
/ 03 марта 2010

Если вы разрабатываете свой собственный протокол, то сначала посмотрите на работу других людей; там уже может быть что-то похожее, что вы могли бы использовать «как есть» или переназначить и настроить. Например; ISO-8583 для финансовых txns, HTTP или POP3 все работают по-разному, но проверенными способами ... На самом деле стоит взглянуть В любом случае, вы многое узнаете о том, как составляются протоколы реального мира.

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

2 голосов
/ 03 марта 2010

Это действительно наш выбор с TCP. HTTP, например, использует сочетание второй, третьей и четвертой опций (двойные заголовки запроса / ответа в конце новой строки, которые могут содержать заголовок Content-Length или указывают chunked encoding , или он может сказать Connection: close и не давать вам длину контента, но ожидать, что вы будете полагаться на чтение EOF.)

Я предпочитаю третий вариант, то есть сообщения с самоописанием, хотя фиксированная длина проста, когда подходит.

1 голос
/ 03 марта 2010

Решение должно зависеть от данных, которые вы хотите отправить (что это такое, как это собирается). Если данные фиксированной длины, то пакеты фиксированной длины, вероятно, будут лучшими. Если данные могут быть легко (без необходимости экранирования) разделены на объекты с разделителями, тогда разделение может быть хорошим. Если вы знаете размер данных, когда начинаете отправлять фрагмент данных, префикс может быть даже лучше. Если отправляемые данные всегда состоят из одного символа или даже одного бита (например, «включено» / «выключено»), то все, что отличается от сообщения с одним символом фиксированного размера, будет слишком большим.

Также подумайте, как протокол может развиваться. Строки, разделенные EOL, хороши, если они не содержат сами символы EOL. Фиксированная длина может быть хорошей, пока данные не могут быть расширены некоторыми дополнительными частями и т. Д.

1 голос
/ 03 марта 2010

Я не знаю, есть ли предпочтительный вариант. В нашей реальной ситуации (клиент-серверное приложение) мы используем опцию отправки общей длины сообщения в качестве одной из первых частей данных. Это просто и работает для наших реализаций TCP и UDP. Это делает логику достаточно «простой» при чтении данных в обеих ситуациях. С TCP объем кода довольно мал (для сравнения). Версия UDP немного сложнее, но все же зависит от размера, который передается в начальном пакете, чтобы знать, когда все данные были отправлены.

...