Основы протокола Socket Protocol

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

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

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

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

Ответ 1

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

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

Ответ 2

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

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

Ответ 3

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

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

Ответ 4

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

Ответ 5

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

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