1

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?

1
  • Can you explain why you're using the multiprocessing module when there's no multiprocessing involved? Commented Nov 9, 2021 at 8:14

2 Answers 2

0

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()
Sign up to request clarification or add additional context in comments.

3 Comments

Why can't I use multiprocessing.connection.Listener instead of socket? I thought they work pretty much the same way? See for example this question and the docs for the multiprocessing library.
@josh 2 questions. 1) Are both client and server running on the same machine? 2) Are either or both client and server on Windows or Unix type systems? Once I know that I'll put together a multiprocessing version that should work for you
Yes, they're on the same machine and it runs Windows.
0

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.DataOutputStream;
import java.io.IOException;
import java.net.Socket;

public class Client {

    public static void main(String[] args) throws IOException {
        String message = "Talking isn't doing. It is a kind of good deed to say well; and yet words are not deeds.";
        try (Socket socket = new Socket("localhost", 7777)) {
            try (DataOutputStream out = new DataOutputStream(socket.getOutputStream())) {
                byte[] dts = message.getBytes();
                out.writeInt(dts.length);
                out.write(dts);
            }
        }
    }
}

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.

2 Comments

Ok this works but I'm not sure why. Can you explain what you're trying to do inside the private static byte[] net(int n) function? Also, will this work irrespective of how small or how large the message size is?
The net function takes a 32-bit int and expresses it as a 4-byte byte array. The message is therefore limited to 2,147,483,647 bytes (0x7fffffff)

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.