简体   繁体   中英

Read data from a client socket seems miss bytes (from java to python)

Background

I have recently just started to learn networking and google's protocol buffers to build a communication between my java client to a python server. Sending message from my python server to java client works perfect, but the reverse way (from java to python) was always failed.

Problem

After checking the length of message from both sides, I have found the receiver(python) missing some of the bytes transferred by the java code,

java side:
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 side:
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

As you can see, the last 10 bytes is missing. I could not figure out the problem.

Codes

The following is my java code,

// 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);
}

and my python code,

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

Any ideas?

If the diagnosis that the stream is not being flushed is correct, then here is the solution:

    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);
    }

Explanation: by using try-with-resources , we ensure that the resource is always closed as the block exits, no matter how it exits. This has two benefits:

  1. It ensures that the stream is flushed
  2. It ensures that you don't leak the resource (ie the associated FileDescriptor ). Resource leaks can cause various unrelated I/O activity to fail ... later on ... if the GC doesn't get a chance to clean up the mess first.

NOTES:

  1. Calling System.exit(...) in the depths of your code is a bad idea. It preempts other possible approaches to recovery, and makes your code harder to extend and/or reuse.

  2. If you catch and report an exception, you should also report the stacktrace ... somewhere.

  3. A better strategy would be to declare IOException as thrown by the enclosing method, and catch / report / recover at a higher level.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM