【问题标题】:Connect an Python server to Java client with sockets使用套接字将 Python 服务器连接到 Java 客户端
【发布时间】:2023-01-03 01:33:09
【问题描述】:

我需要使用 Java 和 Python 套接字进行连接。我编写了用 Python 创建服务器的代码和用 Java 创建客户端的代码,以便能够在 Python 和 Java 之间进行通信。

连接已正确创建,当使用writeUTF() 将数据从 Java 发送到 Python 时它有效,但是当从 Python 发送数据并使用 readUTF() 使用 java 读取时,我收到 EOF 异常。有趣的是,如果我使用 readLine() 方法从 Java 中读取,它就可以工作。

服务器代码:

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")

客户端代码:

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();
    }
}

例外:

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)

【问题讨论】:

  • 您可能认为您的服务器代码适用于 writeUTF(),但它实际上不能(或者至少,您错过了服务器接收到的字符串包含两个额外字符的事实:NUL (0x00) 和 LF (0x10)。
  • 好问题,因为它包含所有相关信息!

标签: python java sockets


【解决方案1】:

您不应该使用 DataOutputStream/DataInputStream,它适用于特定的类似 XDR 的序列化格式。 writeUTF/readUTF 方法使用您的 Python 服务器不提供的特定序列化格式。也就是说,他们写入/读取 2 个字节以确定数据的预期长度,并且它使用 a modified UTF-8 format 用于后续的字符串数据。您的 Python 服务器既不读取也不写入这两个字节的长度(并且它不使用修改后的 UTF-8 格式)。

由于 Python 服务器不写入长度,您发送的前两个字符被解释为长度字节("ho" 是 0x686f 或 26735),然后导致 readUTF 尝试读取 26735 字节的缓冲区。给定剩余数据为 "la tio",或 6 个字节,这将导致 EOFException

使用给定的 Python 代码,您应该使用配置有 UTF-8 的(可选缓冲的)InputStreamReaderOutputStreamWriter。但是,您的协议有缺陷,因为无法确定消息边界。在给出的示例中,这并不是真正相关的,因为您可以阅读到输入结束,但一般来说,当您需要交换多条消息或超过单个 TCP/IP 数据包长度的消息时,某种形式应该使用消息长度编码或消息边界来了解消息何时完成。

或者,您需要修改 Python 代码,使其遵守 DataOutputStreamDataInputStream 的协议。有关确切格式的详细信息,请参阅DataOutput.writeUTF()DataInput.readUTF()

【讨论】:

    【解决方案2】:

    我使用 BufferedWriter 和 BufferedReader 进行修复。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-02-25
      • 1970-01-01
      • 2023-01-30
      • 1970-01-01
      • 2012-07-24
      • 1970-01-01
      相关资源
      最近更新 更多