Каковы разделители для сообщений protobuf?

Каковы разделители для сообщений protobuf? Я работаю с сериализованными сообщениями. Я хотел бы знать, начинаются ли сообщения с $$ __ $$ и заканчиваются ли они тем же знаком.

После некоторого обсуждения и размышлений было принято решение добавлять заголовки к сообщениям для решения проблемы. Спасибо всем за вклад.

Marko Bencik 17.09.2018 12:27
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
4
1
3 899
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

Для сообщений верхнего уровня (т.е. отдельных вызовов сериализации) буквально нет ни одного. Если вы не добавите собственное кадрирование, сообщения активно перетекают друг в друга, поскольку десериализатор (по умолчанию) просто читает до конца потока. Итак: если вы слепо объединили несколько объектов без собственного протокола кадрирования: теперь у вас есть проблемы.

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

Итак: похоже, вам нужно добавить свой собственный протокол кадрирования, и в этом случае ответ будет: все, что определяет ваш протокол кадрирования. Просто помните, что protobuf является двоичным, поэтому вы не можете полагаться на какую-либо последовательность байтов в качестве дозорного / терминатора. В идеале вы должны использовать вместо этого подход с префиксом длины.

Так ли обстоит дело с компилятором protobuf 2 и 3? Вы случайно не знаете? Я понимаю то, что вы пытаетесь объяснить. Это определенно то, что я должен пересмотреть в более широкой картине.

Marko Bencik 15.09.2018 12:10

@MarkoBencik двоичный протокол идентичен независимо от того, какой DSL (proto2 / proto3), компилятор или другие инструменты вы используете. Сам бинарный протокол: не завершает внешние сообщения.

Marc Gravell 16.09.2018 14:56

Формат проводного буфера протокола не является саморазграничивающим, поэтому анализаторы буфера протокола не могут самостоятельно определить, где заканчивается сообщение. Самый простой способ решить эту проблему - записать размер каждого сообщения до того, как вы напишете само сообщение. Когда вы читаете сообщения обратно, вы считываете размер, затем считываете байты в отдельный буфер, а затем выполняете синтаксический анализ из этого буфера.

(В дополнение к существующим ответам 1, 2)

Обычный метод кадрирования для буферов протокола заключается в добавлении варинт перед фактическим сообщением protobuf.

Реализация уже является частью библиотеки protobuf, например:

Удачи тебе с твоим проектом!

РЕДАКТИРОВАТЬ> Официальная ссылка утверждает, что:

If you want to write multiple messages to a single file or stream, it is up to you to keep track of where one message ends and the next begins. The Protocol Buffer wire format is not self-delimiting, so protocol buffer parsers cannot determine where a message ends on their own. The easiest way to solve this problem is to write the size of each message before you write the message itself. When you read the messages back in, you read the size, then read the bytes into a separate buffer, then parse from that buffer. (If you want to avoid copying bytes to a separate buffer, check out the CodedInputStream class (in both C++ and Java) which can be told to limit reads to a certain number of bytes.)

Этот подход отлично работает, когда получатель получает байтовый поток с самого начала. Я не слишком хорошо знаком с байтовым потоком protobuf, но я не уверен, что он работает, если получатель получает поток байтов частично, так как может быть трудно различить разделительный varint и сообщение varint и т. д.

bazza 16.09.2018 09:09

@bazza Я понимаю вашу точку зрения, но боюсь, что в вопросе нет такого требования. Кодирование Protobuf определенно не самосинхронизируется. Если возникает необходимость, существуют протоколы кадрирования, обладающие этим свойством (например, COBS). Я уверен, что в большинстве случаев целостность потока гарантируется верхним уровнем. Не стесняйтесь публиковать мысли с лучшим ответом ....

vlp 16.09.2018 09:54

Нет, у меня нет лучшего ответа, ваш ответ отличный и, безусловно, отвечает на вопрос! Я просто хочу, чтобы Protobuf ввел самосинхронизацию, тогда это было бы еще более полезно. Спасибо за подсказку по COBS, я раньше крутил свой собственный (обычно мне это сходило с рук), но вместо этого приятно иметь библиотеку для этого.

bazza 16.09.2018 17:55

Другие вопросы по теме