处理Google协议缓冲库中的IOExceptions



我有一些代码试图从Java的套接字读取Google Protocol Buffer消息。但是,如果mergeDelimitedFrom()方法读取到无效数据或套接字连接被重置(可能还有其他原因),它可能会引发IOException。如果连接被重置,我想退出循环,但如果这只是一条无效消息,我想继续运行。有一种想法是只需要某种异常计数器,并在连续X次失败后退出,但我希望能够弄清楚发生了什么类型的错误,而不是蒙在鼓里。

这基本上就是我的代码:

while (m_Running)
{
SomeMessage message = null;
try
{
final Builder builder = SomeMessage.newBuilder();
if (builder.mergeDelimitedFrom(m_InputStream))
{
message = builder.build();
}
else
{
// Google protocol buffers doesn't document it very well
// but if mergeDelimietedFrom returns false then it has
// reached the end of the input stream.  For a socket, no
// more data will be coming so exit from the thread
m_Running = false;
}
}
catch (final IOException e)
{
// what should really be done here ???
}
}

不要这么做。如果你直接从套接字中读取协议缓冲区对象,那么你就是在有效地定义你自己的应用程序协议。要做好这件事比你想象的要困难——在《应用程序协议的设计》中对一些问题有一个很好的概括描述。重要的是要理解框架——确定一条消息的结束和另一条消息开始的位置。

这让我们从protobuf的发明者那里得到了一些建议https://developers.google.com/protocol-buffers/docs/techniques.关键的建议是:

如果您想将多条消息写入单个文件或流,则由您来跟踪一条消息的结尾和下一条消息开始的位置。

我建议您决定一个框架协议,将流划分为消息,然后编写一些自定义套接字代码来处理套接字的工作或读取字节,将它们划分为字节数组,其中每个字节数组只包含一条消息,最后使用protobuf将每个消息字节数组反序列化为一个对象。保证反序列化没有IOException原型。

您仍然需要处理IOExceptions,但它将处于较低级别,您只读取字节数组,并且您将确切地知道错误发生时有多少数据被反序列化。

还可以考虑使用netty之类的东西来帮助处理套接字代码。

最新更新