2012-09-28 39 views
0

我有一些代码试图从Java套接字中读取Google Protocol Buffer消息。但是,如果mergeDelimitedFrom()方法读入无效数据或套接字连接已重置(可能还有其他原因),则可能会引发IOException。如果连接重置,我想退出循环,但如果这只是一个无效的消息,我想继续运行。一个想法是在X连续失败后只需要有某种异常计数器并退出,但我希望能够找出发生的错误类型,而不是在黑暗中。处理来自Google协议缓冲区库的IOExceptions

这基本上是我的代码:

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 ??? 
    } 
} 

回答

1

只是不去做。如果您直接从套接字读取协议缓冲区对象,那么您正在有效地定义自己的应用程序协议。这比你想象的要难得多 - 对On the Design of Application Protocols的一些问题有一个很好的概括性描述。理解框架非常重要 - 确定一个消息的结束位置和另一个消息的开始位置。

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

如果你想写多个消息到单个文件或流,它是由你来跟踪一个消息结束和下一个开始的地方。

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

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

还可以考虑使用类似netty的协助套接字代码。

+0

我想通过使用mergeDelimitedFrom而不是mergeFrom来选择成帧协议,因为协议缓冲库负责八位字节计数。让我想知道为什么他们提供这种方法,如果不实用的话。我想我可以通过直接从流中读取数据并将字节数组传递给协议缓冲区库来重复同样的逻辑,但是这看起来好像重新发明了一下轮子。 –