Почему я не могу прочитать поле VarInt из двоичных данных с помощью protobuf-net

все,

Я использую библиотеку protobuf-net для сериализации-десериализации текстовых данных в двоичные файлы. У меня была аналогичная ошибка в прошлом, но затем я сделал ошибку, записав двоичные данные в текстовый файл. На этот раз я уверен, что файл записан в двоичном режиме. Во время чтения данных я получаю исключение EndOfStream: попытка чтения после конца потока.

У меня есть заголовок сообщения перед каждым объектом в двоичном файле.

message HeaderMessage {
  required double timestamp = 1;
  required string ric_code = 2;
  required int32 count = 3;
  required int32 total_message_size = 4;
}

Я получаю исключение, когда читаю поле total_message_size в фиксированном месте

HEADER: 1111    1       1       hk      0
File: 398909440 bytes
Reading data objects:
1073561: 09 e3 a5 9b c4 0c b3 e0 40 12 07 31 30 39 33 2e 48 4b 18 04 20 5a
1073677: 09 e3 a5 9b c4 0c b3 e0 40 12 07 30 32 39 37 2e 48 4b 18 02 20 2d
1073748: 09 e3 a5 9b c4 0c b3 e0 40 12 07 30 32 39 37 2e 48 4b 18 04 20 5a
1073864: 09 e3 a5 9b c4 0c b3 e0 40 12 07 38 31 37 33 2e 48 4b 18 02 20 2d
1073935: 09 e3 a5 9b c4 0c b3 e0 40 12 07 38 31 37 33 2e 48 4b 18 04 20 5b
1074052: 09 e3 a5 9b c4 0c b3 e0 40 12 07 30 32 33 35 2e 48 4b 18 02 20 2d
1074123: 09 e3 a5 9b c4 0c b3 e0 40 12 07 30 36 30 33 2e 48 4b 18 02 20 2d
1074194: 09 e3 a5 9b c4 0c b3 e0 40 12 07 30 36 30 33 2e 48 4b 18 04 20 5b
1074311: 09 e3 a5 9b c4 0c b3 e0 40 12 07 30 32 33 35 2e 48 4b 18 06 20 8a

В приведенных выше выходных данных первое поле - это позиция потока. Общая длина потока составляет 398909440. Таким образом, поток не может достигнуть своего конца. Я пытался напечатать отдельные поля в тот момент, когда они не читаются, я вижу, что класс ProtoReader всегда не может прочитать поле total_message_size.

В выводе aboe последняя строка является виновником того, что protobuf-net не может прочитать данные.

1074311: 09 e3 a5 9b c4 0c b3 e0 40 12 07 30 32 33 35 2e 48 4b 18 06 20 8a

Если мы разделим поля, данные будут выглядеть следующим образом:

field1 timestamp field: type: 09  payload: e3 a5 9b c4 0c b3 e0 40
field2 ric_code field: type: 12   payload: 07 30 32 33 35 2e 48 4b
field3 count field:    type: 18   payload: 06
field4 total_message_size: type: 20 payload: 8a

исключение возникает при чтении полезной нагрузки 4-го поля, и значение равно 8a. (десятичное 138).

Трассировка стека выглядит следующим образом:

   at ProtoBuf.ProtoReader.TryReadUInt32VariantWithoutMoving(Boolean trimNegative, UInt32& value) in C:\Dev\protobuf-net\protobuf-net\ProtoReader.cs:line 101
   at ProtoBuf.ProtoReader.ReadUInt32Variant(Boolean trimNegative) in C:\Dev\protobuf-net\protobuf-net\ProtoReader.cs:line 138
   at ProtoBuf.ProtoReader.ReadInt32() in C:\Dev\protobuf-net\protobuf-net\ProtoReader.cs:line 264
   at protobuf_test.Program.Main(String[] args) in H:\Personal\Visual Studio 2010\Projects\protobuf-test\protobuf-test\Program.cs:line 80
   at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
   at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
   at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
   at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Threading.ThreadHelper.ThreadStart()

в чем проблема при чтении значения 138? В чем проблема в этом случае?

С уважением, Алок


person Alok    schedule 19.12.2011    source источник
comment
Спасибо, что предоставили достаточно информации, чтобы дать взвешенный ответ, но это, похоже, проблема с writer (которым IIRC является C ++ в вашем случае), а не с reader (protobuf-net)   -  person Marc Gravell    schedule 19.12.2011


Ответы (1)


0x8a не является допустимым вариантом. Кодирование Varint использует MSB как бит продолжения, что означает: если MSB установлен, ожидается как минимум еще один байт (он продолжается до тех пор, пока MSB не будет не установлен, объединяя оставшиеся 7-битные блоки прямой порядок байтов). Следовательно, 0x8a не может существовать сам по себе в допустимом варинте. 0x8a и что-то еще, конечно. Вы можете увидеть это в спецификации провода. Пожалуйста, убедитесь, что вы случайно не обрезали конец этого отдельного сообщения или неверно указали длину (поскольку я понимаю, что каждая запись индивидуально обернута префиксом размера).

person Marc Gravell    schedule 19.12.2011
comment
Спасибо, Марк. Я сообщал о неправильной длине заголовка при записи длины заголовка. Обычно я помещаю длину заголовка в двоичные данные, а затем перед записью фактического сообщения заголовка я обновлял одно из значений заголовка, которое должно было изменить длину заголовка. - person Alok; 19.12.2011