буферы протокола Google - шифрование в C ++, дешифрование в Java - InvalidProtocolBufferException - PullRequest
3 голосов
/ 12 августа 2011

Извините, но я думаю, что схожу с ума. У меня есть это в C ++:

std::stringstream message;
protoMsg.SerializeToOstream(&message);
boost::system::error_code ignored_error;
std::cout << "Writing response to socket. Byte size " << protoMsg.ByteSize() << " Buffer " << message.str().length() << std::endl;
for(int i(0);i<(int)message.str().length();i++)
    std::cout << (int)message.str().at(i);
std::cout << std::endl;
boost::asio::write(socket, boost::asio::buffer(message.str()), ignored_error);
std::cout << "Done writing." << std::endl;

Что дает этот вывод

Writing response to socket. Byte size 88 Buffer 88
1886811891161111001113278971091012500000000320400480560640730000000081000000008859621061211611110011132115121109789710910111416691201161011141109710832114101113117101115116
Done writing.

И это в Java:

try {
  System.out.println("Parsing");
  int lenbytes = is.read(buffer);
  System.out.println("Read bytes " + lenbytes);
  for(int i=0;i<lenbytes;i++)
    System.out.print(Integer.toString((int)buffer[i]));
  System.out.println("");
  EnvInfoProto envInfoProto = EnvInfoProto.parseFrom(buffer);
  System.out.println("Done");
  return envInfoProto;
} catch(IOException ignore) { System.out.println("Ex: " + ignore.toString(); }

Что дает

Parsing
Read bytes 88
1886811891161111001113278971091012500000000320400480560640730000000081000000008859621061211611110011132115121109789710910111416691201161011141109710832114101113117101115116
Ex: com.google.protobuf.InvalidProtocolBufferException: Protocol message contained an invalid tag (zero).

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

1 Ответ

3 голосов
/ 12 августа 2011

Вы просите, чтобы сообщение было проанализировано из целого из buffer - и я предполагаю, что buffer имеет длину более 88 байтов.

Я не могу вспомнить вручную, позволяет ли parseFrom указать максимальный объем данных для чтения, но альтернативой будет:

ByteArrayIntputStream stream = new ByteArrayInputStream(buffer, 0, lenbytes);
EnvInfoProto envInfoProto = EnvInfoProto.parseFrom(stream);

Обратите внимание, что проблема все еще в том, что вы предполагаете, что вы можете прочитать все данные из потока за один вызов read, что никогда не было хорошей идеей, но отдельный вопрос. Если вы собираетесь закрыть сокет после записи, вы, конечно, можете просто проанализировать поток из сокета InputStream в коде Java. Если вы не собираетесь закрыть поток, я бы предложил сначала записать длину сообщения в сокет (как 32-разрядное целое число), чтобы вы могли затем прочитать это в Java и прочитать точно правильное объем данных, зная, когда вы закончите.

...