Codename47
Codename47

Reputation: 285

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.

Upvotes: 4

Views: 1827

Answers (3)

Ryan Haining
Ryan Haining

Reputation: 36872

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

Upvotes: 5

Fedor Gogolev
Fedor Gogolev

Reputation: 10551

Maybe you could use something from io module? BufferedRWPair for example.

Upvotes: 0

dmi_
dmi_

Reputation: 1257

recv(4) will read a maximum of 4 bytes. See the docs: http://docs.python.org/library/socket.html . I think making a simple buffered reader function is a perfectly acceptable solution here.

Upvotes: 0

Related Questions