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
相关产品推荐
相关产品推荐

