Home > Enterprise >  Java client and python server socket connection - end of file error when receiving message
Java client and python server socket connection - end of file error when receiving message

Time:11-09

I need to send a message from a java client program to a python server program.

Here is my code:

Java client:

import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;

public class Client {
    public static void main(String[] args) throws IOException {
        // need host and port, we want to connect to the ServerSocket at port 7777
        Socket socket = new Socket("localhost", 7777);
        System.out.println("Connected!");

        // get the output stream from the socket.
        OutputStream outputStream = socket.getOutputStream();
        // create a data output stream from the output stream so we can send data through it
        DataOutputStream dataOutputStream = new DataOutputStream(outputStream);

        System.out.println("Sending string to the ServerSocket");

        // write the message we want to send
        dataOutputStream.writeUTF("Hello from the other side!");
        dataOutputStream.flush(); // send the message
        dataOutputStream.close(); // close the output stream when we're done.

        System.out.println("Closing socket and terminating program.");
        socket.close();
    }
}

Python server:

from multiprocessing.connection import Listener
address = ('localhost',7777)
while True:
    with Listener(address, authkey=None) as listener
        with listener.accept() as conn:
            print(conn.recv())

When I try to execute this, I get the following error in Python:

OSError: got end of file during message

What am I doing wrong?

CodePudding user response:

Use of the multiprocessing module seems inappropriate in this case and is the root cause of your problem. Here's a simplified Python server that demonstrates how you could achieve your objective. Note that the server terminates after accepting and handling any single connection:

import socket

def server():
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
        s.bind(('0.0.0.0', 7777))
        s.listen()
        conn, _ = s.accept()
        with conn:
            while (data := conn.recv(8192)):
                print(data.decode())

if __name__ == '__main__':
    server()

CodePudding user response:

The issue here is that the recv* functions of the multiprocessing connection expect to get a 32-bit preamble in the message that indicates the actual amount of data being transmitted. So here's what the Java part needs to look like (I haven't bothered about buffered IO - just keeping things to bare bones):

import java.io.IOException;
import java.net.Socket;
import java.io.OutputStream;

public class Client {

    public static void main(String[] args) throws IOException {
        try (Socket socket = new Socket("localhost", 7777)) {
            OutputStream out = socket.getOutputStream();
            byte[] dts = "Hello from the other side!".getBytes();
            out.write(net(dts.length));
            out.write(dts);
        }
    }
    private static byte[] net(int n) {
        byte[] buffer = new byte[4];
        for (int i = 3; i >= 0; i -= 1) {
            buffer[i] = (byte)(n & 0xff);
            n >>>= 8;
        }
        return buffer;
    }
}

Then, your Python server can look something like this:

from multiprocessing.connection import Listener

def main():
    listener = Listener(address=('0.0.0.0', 7777), family='AF_INET', authkey=None)
    with listener.accept() as conn:
        print(conn.recv_bytes().decode())
            

if __name__ == '__main__':
    main()

So, this means that your original problem is due to recv() looking at the first 4 bytes and interpreting that as the length of incoming data. But that would equate to something much larger than was actually being sent.

  • Related