【发布时间】:2011-07-02 15:19:32
【问题描述】:
我已经使用 protobuf 几个星期了,但在 Java 中解析 protobuf 消息时我仍然不断收到异常。
我使用 C++ 创建我的 protobuf 消息并使用 boost sockets 将它们发送到 Java 客户端正在侦听的服务器套接字。用于传输消息的 C++ 代码是这样的:
boost::asio::streambuf b;
std::ostream os(&b);
ZeroCopyOutputStream *raw_output = new OstreamOutputStream(&os);
CodedOutputStream *coded_output = new CodedOutputStream(raw_output);
coded_output->WriteVarint32(agentMessage.ByteSize());
agentMessage.SerializeToCodedStream(coded_output);
delete coded_output;
delete raw_output;
boost::system::error_code ignored_error;
boost::asio::async_write(socket, b.data(), boost::bind(
&MessageService::handle_write, this,
boost::asio::placeholders::error));
如你所见,我用WriteVarint32 写了消息的长度,因此Java 端应该知道使用parseDelimitedFrom 应该读多远:
AgentMessage agentMessage = AgentMessageProtos.AgentMessage
.parseDelimitedFrom(socket.getInputStream());
但这无济于事,我不断收到这些异常:
Protocol message contained an invalid tag (zero).
Message missing required fields: ...
Protocol message tag had invalid wire type.
Protocol message end-group tag did not match expected tag.
While parsing a protocol message, the input ended unexpectedly in the middle of a field. This could mean either than the input has been truncated or that an embedded message misreported its own length.
重要要知道,这些异常不会在每条消息上都抛出。这只是我收到最多的消息的一小部分,效果很好 - 我仍然想解决这个问题,因为我不想忽略这些消息。
如果有人可以帮助我或将他的想法付诸实践,我将非常感激。
另一个有趣的事实是我收到的消息数量。我的程序通常在 2 秒内总共有 1.000 条消息。在 20 秒内大约 100.000 等等。我人为地减少了发送的消息,当只发送 6-8 条消息时,完全没有错误。那么这可能是Java客户端套接字端的缓冲问题吗?
假设有 60.000 条消息,其中平均有 5 条已损坏。
【问题讨论】:
-
这可能是一个愚蠢的问题,但有没有什么办法让您在数据中留下填充/超大缓冲区,而不是修剪任何盈余?
-
(这个错误肯定很容易由备用零引起)
-
@Marc-Gravell:什么是超大缓冲区?实际上,我不明白您认为可能导致这种情况的原因。也许你可以指出我应该在哪里寻找这个?顺便提一句。我还添加了一些我收到的其他例外情况。
-
我见过的其他人经常这样做 - 使用编码尝试将 BLOB 获取为字符串,然后解码.保证损坏(如果你想要一个字符串,而不是 UTF/codepage/etc,应该使用 base-64 或 hex 等)
-
"Java 客户端套接字端" - 好吧,我更容易期待流处理代码中的一个错误,尤其是在异步/线程的情况下。可以是读也可以是写,在这种情况下......降低速率显然会消除许多由不正确的异步引起的意外冲突。
标签: java c++ sockets tcp protocol-buffers