为什么parseFrom()函数在java socket中使用protobuf挂起?

时间:2013-05-29 13:38:24

标签: java sockets echo protocol-buffers

我只想使用protobuf和java创建echo服务器/客户端。

我使用protobuf-java-2.4.1和jdk1.7进行了测试。

我写了如下的回声服务器代码

// create server socket and accept for client connection.
// ...
link = servSock.accept();                       
Person person = Person.parseFrom(link.getInputStream()); // blocking position
person.writeTo(link.getOutputStream());

我认为没有必要注意Person.proto。

客户端代码仅使用套接字输入流发送Person对象并接收回显Person对象。

// socket connect code was omitted.
Person person = Person.newBuilder().setId(1).setName("zotiger").build();
person.writeTo(echoSocket.getOutputStream());
person = Person.parseFrom(echoSocket.getInputStream());

但是当服务器和客户端都运行时,服务器在parseFrom函数中被阻止。

我发现如果我使用writeDelimitedTo()和parseDelimitedFrom(),那就没问题。我不明白为什么writeTo()和parseFrom()函数不起作用。

为什么服务器在那里阻塞?

是否有必要从客户端发送一些结束信号?

2 个答案:

答案 0 :(得分:4)

您必须使用writeDelimitedTo() / parseDelimitedFrom()的原因是协议缓冲区可能不知道需要从套接字读取多少数据。这提出了一个问题(我说可能因为你当然可以创建一个只有固定长度字段的消息,不需要这个......但协议缓冲区必须处理这两种情况)

writeDelimitedTo()方法将消息的长度写入OutputStream,然后写入消息本身。它的对应parseDelimitedFrom()读取长度,然后是消息。

您可以将writeTo()pasrseFrom()与流一起使用,但前提是您要写入/读取单个消息并在写入后关闭流。然后,读者将获得一个EOF来指示消息的结束(也就是从只包含一条消息的文件中读取的情况)。

答案 1 :(得分:1)

不要编写自己的客户端/服务器,即。 RPC解决方案。这里有一个...... https://code.google.com/p/protobuf-rpc-pro/,它已经为java提供了一些很好的功能。