Home > database >  Connect an Python server to Java client with sockets
Connect an Python server to Java client with sockets

Time:01-03

I need to connect using Java and Python sockets. I wrote code to create a server in Python and code to create a client in Java to be able to communicate between Python and Java.

The connection is created correctly, when sending data from Java to Python using writeUTF() it works, but when sending from Python and reading with java using readUTF(), I get an EOF exception. The funny thing is that if I read from Java with the readLine() method, it works.

The server code:

import socket
 
ser = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
ser.bind(("localhost", 7000))
ser.listen(1)
 
cli, addr = ser.accept()

recibido = cli.recv(1024)
recibido = recibido.decode("UTF8")

print("Recibo conexion de la IP: "   str(addr[0])   " Puerto: "   str(addr[1]))
print(recibido)

enviar = "hola tio".encode("UTF8")
cli.send(enviar)

cli.close()
ser.close()

print("Conexiones cerradas")

The client code:

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

public class Cliente {
    public static void main(String[] args) throws IOException, InterruptedException {
        Socket cliente = new Socket("localhost", 7000);

        DataOutputStream entrada = new DataOutputStream(cliente.getOutputStream());
        DataInputStream salida = new DataInputStream(cliente.getInputStream());

        entrada.writeUTF("Hola soy cliente");

        System.out.println(salida.readUTF());
        cliente.close();
    }
}

The exception:

Exception in thread "main" java.io.EOFException
    at java.base/java.io.DataInputStream.readFully(DataInputStream.java:202)
    at java.base/java.io.DataInputStream.readUTF(DataInputStream.java:614)
    at Cliente.main(Cliente.java:15)

CodePudding user response:

You shouldn't be using a DataOutputStream/DataInputStream, it is for a particular XDR-like serialization format. The writeUTF/readUTF methods use a particular format of serialization that your Python server doesn't provide. That is they write/read 2 bytes to determine the expected length of the data, and it uses a modified UTF-8 format for the subsequent string data. Your Python server doesn't read nor write those two bytes of length (and it doesn't use the modified UTF-8 format).

As the Python server doesn't write length, the first two characters you send are interpreted as length bytes ("ho" is 0x686f or 26735), which then causes the readUTF to try and read a buffer of 26735 bytes. Given the remaining data is "la tio", or 6 bytes, this then results in the EOFException.

With the Python code as given, you should use an (optionally buffered) InputStreamReader and OutputStreamWriter configured with UTF-8. However, your protocol is deficient, because it's not possible to determine message boundaries. In the example as given that is not really relevant, as you can read until the end of input, but in general, when you need to exchange multiple messages, or a message that exceeds the length of a single TCP/IP packet, some form of message length encoding or message boundaries should be used to know when a message is complete.

Alternatively, you need to modify your Python code so it adheres to the protocol of DataOutputStream and DataInputStream. See DataOutput.writeUTF() and DataInput.readUTF() for details on the exact format.

CodePudding user response:

I repair using BufferedWriter and BufferedReader.

BufferedWriter entrada = new BufferedWriter(new OutputStreamWriter(cliente.getOutputStream()));
BufferedReader salida = new BufferedReader(new InputStreamReader(cliente.getInputStream()));
  • Related