протокол прикладного уровня - разные размеры пакетов

Предположим, я определил свой собственный протокол прикладного уровня поверх TCP для обмена мгновенными сообщениями. Я использовал структуру пакета для сообщений. Поскольку я использую симметричное (AES) и асимметричное (RSA) шифрование, я получаю разный размер пакета для разных типов сообщений. Теперь к моим вопросам.

Как прочитать из сокета, что я получаю один пакет прикладного уровня? Какой размер указать?

Заранее спасибо.

Я имею в виду два подхода.

  1. Считайте из потока TCP фиксированное количество байтов, которое представляет фактический размер пакета, и, наконец, повторно прочитайте из потока ранее собранный размер байтов.

  2. Считайте максимальный размер пакета из потока. Проверьте фактический размер полученных байтов и решите, какой это был тип сообщения.

Теперь более общий вопрос. Должен ли я предоставлять метаданные, такие как размер пакета, метод шифрования, получатель, отправитель и т. д.? Если да, следует ли мне также шифровать эти метаданные?


person auermich    schedule 04.05.2016    source источник


Ответы (1)


Помните, что при использовании TCP при чтении из сети нет гарантии относительно количества байтов, полученных в этот момент времени. То есть клиент может отправить полный пакет в своем write(), но это не означает, что ваш read() получит такое же количество байтов. Таким образом, вашему коду всегда нужно будет прочитать некоторое количество байтов из сети, затем проверить (на основе накопленных данных), что вы получили необходимое количество байт, и тогда вы можете проверить пакет ( тип, содержимое и и т. д.).

Некоторые приложения используют кодировщики/декодеры конечного автомата и буферы фиксированного размера для чтения/записи своих сетевых данных; другие приложения динамически выделяют буферы, достаточно большие для «полного пакета», затем продолжают чтение байтов из сети до тех пор, пока буфер «полного пакета» не заполнится. Какой подход вы выберете, зависит от вашего приложения. Таким образом, размер, который вы используете для чтения, не так важен, как то, как ваш код гарантирует, что он получил полный пакет.

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

Надеюсь это поможет!

person Castaglia    schedule 04.05.2016
comment
Но для уточнения, обычно ли размер пакета отправляется в виде метаданных заранее и отделяется от фактической полезной нагрузки, а не только для передачи полезной нагрузки? - person auermich; 04.05.2016
comment
Если ваши пакеты имеют переменный размер (а многие так и делают), то да, отправка размера пакета (как некоторого значения фиксированной длины) в качестве префикса довольно распространена. Например, прочитать первые 4 байта как число с прямым порядком байтов, указывающее длину следующего пакета, затем прочитать ‹len› количество байтов, затем декодировать/разобрать пакет. - person Castaglia; 04.05.2016
comment
Если вы получаете меньше байтов, чем ожидалось, или информация в заголовке искажена, вы бы предложили использовать тайм-аут (на стороне клиента) или, скорее, отправить явное сообщение об ошибке с сервера на клиент? Спасибо за вашу помощь. - person auermich; 07.05.2016
comment
Зависит от того, насколько полезным вы хотите, чтобы ваш протокол был. Многие протоколы имеют механизм сообщения об ошибках, так что сервер (или клиент) может отправить сообщение отправляющему одноранговому узлу с указанием ошибки. Это позволяет узлу, возможно, исправить проблему (или, по крайней мере, зарегистрировать, что это произошло). - person Castaglia; 07.05.2016
comment
При реализации возникла еще одна проблема. Предположим, что на сервер прибыл искаженный заголовок (не удалось расшифровать размер); как и сколько байт вы сбрасываете из tcp потока? Вы не хотите уничтожать законные пакеты после искаженного. Более того, поскольку речь идет об обмене мгновенными сообщениями, вы не хотите подтверждать пакет заголовка. Поэтому может случиться так, что несколько пакетов уже были отправлены. - person auermich; 13.05.2016
comment
Если поток настолько поврежден, то единственное, что нужно сделать, это разорвать TCP-соединение и заставить клиента повторно подключиться, возобновив поток. Вот почему некоторые протоколы имеют подтверждения или контрольные точки, где сервер подтверждает некоторое число; клиент, если он повторно подключается, знает этот последний акк и может оттуда возобновить поток. (Все это часть увлекательного мира разработки протоколов.) - person Castaglia; 13.05.2016