Основные принципы сокетного протокола

Недавно, при чтении ПРАКТИЧЕСКОГО РУКОВОДСТВА Программирования Сокета следующий раздел выскочил во мне:

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

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

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

11
задан Justin Ethier 3 March 2010 в 18:06
поделиться

5 ответов

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

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

5
ответ дан 3 December 2019 в 09:40
поделиться

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

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

2
ответ дан 3 December 2019 в 09:40
поделиться

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

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

2
ответ дан 3 December 2019 в 09:40
поделиться

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

1
ответ дан 3 December 2019 в 09:40
поделиться

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

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

1
ответ дан 3 December 2019 в 09:40
поделиться
Другие вопросы по тегам:

Похожие вопросы: