【问题标题】:Read data from a client socket seems miss bytes (from java to python)从客户端套接字读取数据似乎丢失字节(从 java 到 python)
【发布时间】:2017-06-10 22:50:53
【问题描述】:

背景

我最近刚刚开始学习网络和谷歌的协议缓冲区,以在我的 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
蟒蛇方面:
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

有什么想法吗?

【问题讨论】:

  • 你试过 outputStream.flush() 因为它可以被缓冲并且永远不会被发送吗?同样在python循环中,您应该在无限循环中从client_socket读取数据,直到socket关闭,因为数据可能以不同的数据包/消息到达。
  • @DmitryZvorygin 哦,谢谢。问题确实是我从来没有让我的接收器陷入无限循环..
  • @DmitryZvorygin 顺便说一句,我是否也应该在 java 的 while 循环中附上我读取数据的方法?还有...可以帮我解决这个问题...
  • 如果您想关闭问题,请点击“删除”链接。
  • 是的,如果您阅读 Java 中的任何内容,您必须知道 inputStream.read(byte[] buffer) 不会承诺读取“完整”缓冲区,但会读取至少一个字节并且返回读取的字节数作为返回值(不知道 Python API,但假设它是相同的)。此外,正如@stephen-c 建议的那样,一旦完成,您应该关闭套接字/流(关闭流通常会间接刷新所有缓冲区)。

标签: java python network-programming protocol-buffers


【解决方案1】:

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

    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 没有机会先清理混乱。

注意事项:

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

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

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

【讨论】:

  • 感谢您的回答!
猜你喜欢
  • 2012-07-08
  • 2016-03-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多