Search code examples
javapythonsocketssocketserver

Python socket recv from java client


I have a problem with a simple python tcp server (I'm using SocketServer class) that have to receive data from a java client.

Here the server side code:

class ServerRequestHandler(SocketServer.BaseRequestHandler):
    [...]
    def handle(self):
        requestCode = struct.unpack('>i', self.request.recv(4))[0]
        [...]
    [...]

Here there is the client:

addr = InetAddress.getByName(hostname);
SocketAddress sockaddr = new InetSocketAddress(addr, port);
clientSocket = new Socket();
clientSocket.connect(sockaddr, timeoutMs);
clientSocketDataOutputStream = new DataOutputStream(clientSocket.getOutputStream());
int   requestCode = 1;
clientSocketDataOutputStream.writeInt(requestCode);
clientSocketDataOutputStream.flush();

I start the Python server and then I try to execute the client that have to send an integer to the server.

On the server side Python raise an exception because the recv(4) function does not read 4 bytes, it returns only one byte.

My java client sends 4 bytes correctly in fact, if I try to call recv(1) 4 times it reads 4 bytes correctly.

I tried to write a Python client that execute the same operation of my java client and in this case the server's recv(4) works well.

How to solve this problem? I thought to implement a simple python buffered reader function that reads from socket byte by byte but I'm sure that a smarter solution exists.


Solution

  • the recv doesn't have to read 4 bytes, it just grabs whatever is there up to a max of four bytes. Since, as you said, you can call recv(1) 4 times. you can do this

    def recvall(sock, size):
        msg = ''
        while len(msg) < size:
            part = sock.recv(size-len(msg))
            if part == '': 
                break # the connection is closed
            msg += part
        return msg
    

    this will repeatedly call recv on sock until size bytes are received. if part == '' the socket is closed so it will return whatever was there before the close

    so change

    requestCode = struct.unpack('>i', self.request.recv(4))[0]
    

    to

    requestCode = struct.unpack('>i', recvall(self.request, 4))[0]
    

    I'd suggest making recvall a method of your class to make things cleaner.


    this is a modification of a method from the safe socket class defined here: http://docs.python.org/howto/sockets.html