0

我有一些代码试图从 Java 中的套接字读取 Google 协议缓冲区消息。但是,如果 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 ???
    }
}
4

1 回答 1

1

只是不要这样做。如果您直接从套接字读取协议缓冲区对象,那么您实际上是在定义自己的应用程序协议。正确地做这件事比您想象的要难 - 在On the Design of Application Protocols中有一些问题的很好的一般描述。理解框架很重要 - 确定一条消息在哪里结束,另一条消息从哪里开始。

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

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

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

您仍然必须处理 IOExceptions,但它将处于较低级别,您只是在读取字节数组,并且您将确切知道发生错误时已反序列化了多少数据。

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

于 2012-09-29T01:37:54.523 回答