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

Java Swing客户端服务器通信报错:socket write error求助

解决 SocketException: Software caused connection abort: socket write error 问题

我来帮你分析下这个错误的根源,以及对应的修复方案:

核心问题拆解

这个报错本质是客户端与服务器的连接逻辑不匹配,再加上代码里的几个细节bug共同导致的:

  • 客户端点击按钮后,先通过sendToServer创建一个Socket发送请求,随后直接关闭了这个Socket;紧接着又调用receiveFromServer新建了一个Socket去等待响应——但服务器是在第一个连接的Socket上准备发送响应的,此时第一个Socket已经被客户端主动关闭,服务器写数据时就会触发连接中断的错误。
  • 服务器的switch语句没有加break,处理完目标case后会直接走到default抛出异常,哪怕逻辑执行完成也会报错。
  • 客户端发送的请求字符串是"Read",但服务器判断的是"Reader button click",两者不匹配,会直接触发IllegalArgumentException。

分步修复方案

我们需要让客户端和服务器在同一个Socket连接上完成请求-响应交互,同时修正其他细节问题:

1. 修正服务器代码

public class StartServer {
    public static void main(String[] argv) throws Exception {
        ServerSocket serverSocket = new ServerSocket(9999);
        System.out.println("Server started");
        while (true) {
            List<String> receive = new ArrayList<String>();
            // 等待客户端连接
            Socket aNewClientSocket = serverSocket.accept();
            System.out.println("Server-Client connexion established!!");
            
            ObjectInputStream toReceiveFromClient = new ObjectInputStream(aNewClientSocket.getInputStream());
            receive = (List<String>) toReceiveFromClient.readObject();
            
            System.out.println(aNewClientSocket.getLocalPort());
            System.out.println(aNewClientSocket.getInetAddress());
            
            switch (receive.get(0)) {
                case "Read": // 匹配客户端实际发送的请求字符串
                    List<Object> toSend = new ArrayList<Object>();
                    Article a=new Article();
                    a.setTitle("New Title");
                    toSend.add(a);
                    
                    ObjectOutputStream objectWayToSend = new ObjectOutputStream(aNewClientSocket.getOutputStream());
                    objectWayToSend.writeObject(toSend);
                    objectWayToSend.flush();
                    
                    // 关闭流与Socket资源
                    objectWayToSend.close();
                    toReceiveFromClient.close();
                    aNewClientSocket.close();
                    break; // 必须添加break,避免进入default分支
                default:
                    throw new IllegalArgumentException("Bad request from client!!");
            }
        }
    }
}

2. 重构客户端的请求-响应逻辑

把发送请求和接收响应合并到同一个方法里,复用同一个Socket:

// 合并请求发送与响应接收的方法
public List<Object> sendRequestAndReceiveResponse(List<String> toSend) throws IOException, ClassNotFoundException {
    List<Object> receive = new ArrayList<Object>();
    Socket socket = null;
    try {
        socket = new Socket("localhost", 9999);
        
        // 发送请求
        ObjectOutputStream objectWayToSend = new ObjectOutputStream(socket.getOutputStream());
        objectWayToSend.writeObject(toSend);
        objectWayToSend.flush();
        
        // 接收响应
        ObjectInputStream objectToGet = new ObjectInputStream(socket.getInputStream());
        receive = (List<Object>) objectToGet.readObject();
        
        // 关闭流资源
        objectWayToSend.close();
        objectToGet.close();
    } catch(Exception e) {
        JOptionPane.showMessageDialog(frame, "The server is offline or connection can't be establish!");
        e.printStackTrace();
    } finally {
        // 确保Socket被关闭
        if (socket != null && !socket.isClosed()) {
            socket.close();
        }
    }
    return receive;
}

3. 更新GUI按钮的事件处理

调用重构后的方法,不再分开发送和接收:

btnCiteste = new JButton("Read");
btnCiteste.addActionListener(new ActionListener() {
    public void actionPerformed(ActionEvent arg0) {
        List<String> toSend = new ArrayList<String>();
        toSend.add("Read");
        try {
            List<Object> received = sendRequestAndReceiveResponse(toSend);
            // 这里可以打开文章窗口,例如传入接收的文章对象
            Article article = (Article) received.get(0);
            new ArticoleReaderFrame(article);
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
});

额外注意事项

  • 确保Article类实现了Serializable接口,因为通过ObjectOutputStream传输对象时,类必须是可序列化的,否则会抛出NotSerializableException。
  • 如果需要支持多客户端同时连接,建议服务器为每个客户端连接启动单独的线程处理,避免主线程被阻塞。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 06:46:39