从客户端套接字读取数据似乎错过字节(从java到python)

时间:2017-06-10 22:50:54

标签: java python network-programming protocol-buffers

背景

我最近刚刚开始学习网络和谷歌的协议缓冲区,以建立我的java客户端与python服务器之间的通信。从我的python服务器发送消息到java客户端是完美的,但相反的方式(从java到python)总是失败。

问题

在检查了双方的消息长度后,我发现接收者(python)缺少java代码传输的一些字节,

  

java方面:
  12 28 08 0b 12 24 15 00 00 80 3f 1a 1b 09 00 00 00 00 00 00 f0 3f 11 00 00 00 00 00 00 f0 3f 19 00 00 00 00 00 00 f0 3f 22 00
  python方:
  12 28 08 0b 12 24 15 00 00 80 3f 1a 1b 09 00 00 00 00 00 00 f0 3f 11 00 00 00 00 00 00 f0 3f

如您所见,缺少最后10个字节。我无法弄清楚这个问题。

以下是我的java代码,

// Both Message and UPDATEs are message types I defined in my .proto file
Message message = Message.newBuilder()
                        .setUpdate(UPDATEs.newBuilder()
                        .setTimeStamp(11)
                        .addUpdates(state))
                        .build();
//System.out.println(message.toString());
System.out.println(message.toByteArray().length); // result -> 42
//System.out.println(byteArrayToHex(message.toByteArray()));
try {   
    OutputStream outputStream = socket.getOutputStream();
    message.writeDelimitedTo(outputStream);     
    System.out.println("Sending finished.");
} catch (IOException e) {
    System.err.println("SteerCommunicator_sendCarData(OutputStream output): " + e.toString());
    System.exit(0);
}

和我的python代码,

def server_loop():
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print "Listening at port {}".format(PORT)
try:
    server.bind(("localhost", PORT))
except:
    print "Unable to listen on the Port" + PORT
    sys.exit()

server.listen(10)

while True:
    client_socket, addr = server.accept()
    print "Received Message from Client {}:{}".format(addr[0],str(addr[1]))
    msg = client_socket.recv(1024)
    print len(msg) # result -> 32

有什么想法吗?

1 个答案:

答案 0 :(得分:0)

如果没有刷新流的诊断是正确的,那么这是解决方案:

    try (OutputStream outputStream = socket.getOutputStream()) {
        message.writeDelimitedTo(outputStream);     
        System.out.println("Sending finished.");
    } catch (IOException e) {
        // SEE NOTES!!
        System.err.println("blah blah" + e.toString());
        System.exit(0);
    }

说明:通过使用 try-with-resources ,我们确保在块退出时始终关闭资源,无论 如何退出。这有两个好处:

  1. 确保刷新流
  2. 确保您不会泄漏资源(即关联的FileDescriptor)。资源泄漏可能导致各种不相关的I / O活动失败......稍后......如果GC没有机会先清理混乱。
  3. 注意:

    1. 在代码的深处调用System.exit(...)是一个坏主意。它抢占了其他可能的恢复方法,并使您的代码更难扩展和/或重用。

    2. 如果您捕获并报告异常,您还应该在某处报告堆栈跟踪。

    3. 更好的策略是将IOException声明为封闭方法,并在更高级别捕获/报告/恢复。