You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python Socket服务器与Java客户端通信:readUTF()报EOFException问题

Java与Python Socket跨语言通信:readUTF()抛出EOFException问题

我用Java和Python Socket实现跨语言通信,编写了Python服务器代码和Java客户端代码。连接可正常建立,Java端使用writeUTF()向Python发送数据时正常,但Python发送数据后,Java端使用readUTF()读取会抛出EOFException,而使用readLine()则可正常读取。

服务器代码(Python)

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

客户端代码(Java)

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)

问题原因

  • Java的writeUTF()和readUTF()并非单纯传输UTF-8字符串,而是采用带2字节长度前缀的特殊UTF-8编码格式:writeUTF()会先写入一个表示字符串字节长度的无符号短整数(大端序),再写入字符串的UTF-8字节数据。
  • 你的Python代码直接将字符串转成UTF-8字节发送,没有添加这个长度前缀,导致Java的readUTF()尝试读取长度前缀时,无法获取有效数据,最终因读取到流末尾抛出EOFException。
  • readLine()能正常读取只是巧合,它是按换行符分隔读取数据,和Java的writeUTF()/readUTF()协议完全无关。

解决方案

方案1:Python端模拟Java的writeUTF()格式发送

手动添加长度前缀,符合Java的readUTF()解析规则:

import socket
import struct

ser = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
ser.bind(("localhost", 7000))
ser.listen(1)

cli, addr = ser.accept()

# 注意:如果要正确解析Java的writeUTF()发送的数据,这里也需要先读取长度前缀
# 示例中暂时沿用原接收逻辑,仅修改发送部分
recibido = cli.recv(1024)
recibido = recibido.decode("UTF8")

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

enviar_str = "hola tio"
enviar_bytes = enviar_str.encode("UTF8")
# 写入2字节大端序的长度前缀
cli.send(struct.pack('>H', len(enviar_bytes)))
# 写入字符串的UTF-8字节数据
cli.send(enviar_bytes)

cli.close()
ser.close()

print("Conexiones cerradas")

方案2:两端统一使用普通UTF-8字符串+分隔符通信

放弃readUTF()/writeUTF(),改用基于换行符的普通字符串传输:

修改后的Python服务器发送部分
enviar = "hola tio\n".encode("UTF8")
cli.send(enviar)
修改后的Java客户端接收部分
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
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());
        BufferedReader salida = new BufferedReader(new InputStreamReader(cliente.getInputStream()));

        entrada.writeUTF("Hola soy cliente");

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

内容的提问来源于stack exchange,提问作者MrFull12

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 09:31:13