Search code examples
javapythonsocketssocketserver

Socket connection between Java and Python


I have a simple Java Socket connected to my Python socketserver. In the client I want to send some data with size given in input: I want first sent an Integer with the size of the data and then the chunk of byte data.

This is the client:

Integer size = 1234
Socket so = new Socket("10.151.0.248", 8000);
byte[] bytes = new byte[size];
DataOutputStream out = new DataOutputStream(so.getOutputStream());
out.writeInt(size);
out.write(bytes);

From the server side I would like to read the amount of data that will arrive first and then read the stream again till everything is received; as final step I will send back an ACK to the client.

Here is the server:

def handle(self):
    tot_data = []

    length = self.request.recv(4)
    size = struct.unpack("!i", length)[0]

    while len(tot_data) < size:
        data = self.request.recv(size - len(tot_data))
        if not data: break
        tot_data.append(data)

    data = bytes(b"ACK")
    # just send back the ack when transfer completed
    self.request.sendall(data)

I am able to retrieve the size of the data in the server, but when I try to read the actual data from the stream, just 4 bytes are retrieved again and then the recv() remain blocked waiting for more data. I would like, first, to retrieve all the data, and then send back the ACK once the transfer is completed.

Any suggestions?


Solution

  • There one problem in the handle method Python side. self.request.recv returns a string (for Python 2.x, it will be bytes for Python3), and you assemble strings in an array. So the length of the array is just the number of chunks and not the number of bytes received.

    You should write:

    def handle(self):
        tot_data = b""
    
        length = self.request.recv(4)
        size = struct.unpack("!i", length)[0]
        while len(tot_data) < size:
            data = self.request.recv(size - len(tot_data))
            if not data: break
            tot_data += data
    
        data = bytes(b"ACK")
        # just send back the ack when transfer completed
        self.request.sendall(data)