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

Java中HttpURLConnection发POST请求遇EOFException问题排查

问题原因分析

你遇到的EOFException核心原因是客户端和服务器的通信协议不匹配:

  • 客户端使用HttpURLConnection发送的是标准HTTP协议请求,会自动在你写入的序列化数据前添加HTTP请求头(比如POST / HTTP/1.1、Content-Type等字段)。
  • 服务器直接用ObjectInputStream读取原始TCP流,而ObjectInputStream在构造时会尝试读取Java序列化格式的魔数(0xACED开头的字节),但此时流的开头是HTTP头内容,根本不是序列化数据,导致读取失败抛出EOFException。
解决方案

根据你的需求(必须使用ObjectInputStream),提供两种可行方案:

方案一:客户端改用原始Socket通信(推荐,协议匹配)

放弃HttpURLConnection,直接用Java Socket和服务器的ServerSocket对接,两端都使用原始TCP流+Java序列化格式,完全匹配:

int serverPort = 9876;
String serverHost = "localhost";
Object payload = "Test payload";
Socket socket = null;

try {
    socket = new Socket(serverHost, serverPort);
    ObjectOutputStream objectOutputStream = new ObjectOutputStream(socket.getOutputStream());
    
    objectOutputStream.writeObject(payload);
    objectOutputStream.flush();
    objectOutputStream.close();
} catch (IOException e) {
    e.printStackTrace();
} finally {
    if (socket != null) {
        try {
            socket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

服务器代码无需修改,即可正常读取序列化的字符串。

方案二:服务器先解析HTTP请求头,再读取序列化数据

如果必须保留客户端的HttpURLConnection,服务器需要先读取并跳过HTTP请求头,直到读到HTTP头结束的空行,再用ObjectInputStream读取请求体中的序列化数据:

private static ServerSocket server;
private static int port = 9876;

public static void main(String[] args) throws IOException, ClassNotFoundException {
    server = new ServerSocket(port);
    while(true){
        System.out.println("Waiting for the client request");
        Socket socket = server.accept();
        BufferedReader headerReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        String line;
        
        // 读取HTTP请求头,直到空行(头结束标志)
        while ((line = headerReader.readLine()) != null && !line.isEmpty()) {
            System.out.println("HTTP Header: " + line);
        }
        
        // 此时流的位置已经到请求体,创建ObjectInputStream读取序列化数据
        ObjectInputStream objectInputStream = new ObjectInputStream(socket.getInputStream());
        Object object = objectInputStream.readObject();
        
        if (object instanceof String) {
            String payload = (String) object;
            System.out.println("Payload received from client: " + payload);
        }
        
        objectInputStream.close();
        socket.close();
    }
}

同时客户端需要修改Content-Type为序列化数据对应的类型(避免HTTP协议的歧义):

// 替换原有的Content-Type设置
connection.setRequestProperty("Content-Type", "application/java-serialized-object");
注意事项
  • Java序列化仅适用于Java客户端和Java服务器的场景,跨语言不兼容,若后续有跨语言需求需考虑其他序列化方案(比如JSON)。
  • 无论哪种方案,都要确保流的关闭顺序正确,避免资源泄漏。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 14:47:06