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

Java客户端与Python服务端Socket通信:客户端收消息死锁求助

Java-Python Socket通信:服务端回复无法被客户端接收的问题解决

我帮你排查下这个问题,核心原因是Java客户端和Python服务端使用的字符串传输格式不兼容,导致客户端的readUTF()方法一直处于等待状态,陷入死锁。

问题根源

Java的DataOutputStream.writeUTF()和DataInputStream.readUTF()是一套成对的专属方法:

  • writeUTF()会先把字符串的UTF-8编码字节长度,以2字节大端序的short类型写入流中,再写入字符串的UTF-8字节;
  • readUTF()则会先读取这2个字节获取长度,再读取对应长度的字节来解码成字符串。

而你的Python服务端直接用conn.send("bye".encode('UTF-8'))发送的是纯UTF-8字节,没有这个长度前缀。Java客户端的readUTF()一直在等待那2个长度字节,自然会卡住。

解决方案(两种可选)

方案1:修改Python服务端,适配Java的readUTF()格式

按照Java的UTF-8传输规范,先发送长度前缀,再发送字符串内容:

import socket
import struct

soc = socket.socket()
host = "localhost"
port = 2004
soc.bind((host, port))
soc.listen(5)

while True:
    conn, addr = soc.accept()
    print("Got connection from", addr)
    
    # 先读取Java发送的2字节长度前缀
    len_prefix = conn.recv(2)
    if not len_prefix:
        conn.close()
        continue
    # 解析大端序的short长度
    msg_length = struct.unpack('!H', len_prefix)[0]
    # 读取对应长度的消息内容
    msg = conn.recv(msg_length).decode('UTF-8')
    print(f"Received: {msg}")
    
    if "Hello" in msg:
        response = "bye"
        response_bytes = response.encode('UTF-8')
        # 先发送2字节的长度前缀(大端序)
        conn.send(struct.pack('!H', len(response_bytes)))
        # 再发送响应内容
        conn.send(response_bytes)
    else:
        print("No valid message received")
    
    conn.close()

方案2:修改Java客户端,使用通用UTF-8传输格式

放弃Java的DataInputStream/DataOutputStream,改用普通的字符流,和Python的纯UTF-8传输兼容:

import java.io.*;
import java.net.*;

public class Client {
    public static void main(String[] args) {
        try {
            Socket socket = new Socket("localhost", 2004);
            // 使用字符流发送UTF-8字符串,添加换行符作为结束标记
            OutputStreamWriter writer = new OutputStreamWriter(socket.getOutputStream(), "UTF-8");
            BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream(), "UTF-8"));
            
            writer.write("Hello\n");
            writer.flush();
            System.out.println("Sent first message");
            
            // 读取服务端发送的换行结尾的字符串
            String response = reader.readLine();
            System.out.println("Received message: " + response);
            
            writer.close();
            reader.close();
            socket.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

对应的Python服务端也要调整为读取换行结尾的字符串:

import socket

soc = socket.socket()
host = "localhost"
port = 2004
soc.bind((host, port))
soc.listen(5)

while True:
    conn, addr = soc.accept()
    print("Got connection from", addr)
    
    # 读取到换行符为止,去除首尾空白
    msg = conn.recv(1024).decode('UTF-8').strip()
    print(f"Received: {msg}")
    
    if "Hello" in msg:
        # 发送带换行的响应,让Java的readLine()可以识别
        conn.send("bye\n".encode('UTF-8'))
    else:
        print("No valid message received")
    
    conn.close()

额外注意点

  • 不管用哪种方案,处理完连接后记得调用conn.close()关闭连接,避免资源泄漏;
  • 如果需要传输大文件或长消息,要注意recv()可能不会一次性读取全部内容,需要循环读取直到获取完整数据。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 08:15:55