4

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.

3 Answers 3

5

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

Sign up to request clarification or add additional context in comments.

Comments

0

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.

Comments

0

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.