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

TCP银行应用登录后冻结:寻求无响应问题解决方案

TCP银行应用登录后冻结及EOFException问题修复

问题根源分析

  1. ObjectOutputStream缓冲未刷新:客户端发送数据后未调用flush(),导致数据滞留在缓冲区,服务器无法及时接收,双方陷入阻塞,最终触发EOFException。
  2. 服务器缺失指令处理分支:客户端发送的UPDATE_PASSWORD指令在服务器中没有对应的处理逻辑,服务器持续等待后续数据,客户端等待响应,导致阻塞。
  3. 通信同步问题:部分流程中客户端与服务器的读写顺序虽逻辑正确,但缓冲延迟导致实际通信不同步,引发阻塞。

具体修复步骤

1. 客户端添加流刷新操作

在所有发送数据的位置后添加out.flush(),确保数据立即发送到服务器:

  • 注册流程发送完所有数据后:
out.writeObject("REGISTER");
out.writeObject(id);
out.writeObject(name);
out.writeObject(email);
out.writeObject(password);
out.writeObject(address);
out.writeObject(balance);
out.flush(); // 添加此行
  • 登录流程发送完数据后:
out.writeObject("LOGIN");
out.writeObject(id);
out.writeObject(password);
out.flush(); // 添加此行
  • 存款流程的两处发送后:
out.writeObject("GET_BALANCE");
out.writeObject(userId);
out.flush(); // 添加此行

// ...输入金额后
out.writeObject("LODGE_MONEY");
out.writeDouble(amountToLodge);
out.flush(); // 添加此行
  • 修改密码流程发送完数据后:
out.writeObject("UPDATE_PASSWORD");
out.writeObject(newPassword);
out.flush(); // 添加此行
  • 登出流程发送指令后:
out.writeObject("LOGOUT");
out.flush(); // 添加此行

2. 服务器添加UPDATE_PASSWORD指令处理分支

在handleClient方法的while循环中,添加对修改密码指令的处理:

} else if (option.equals("UPDATE_PASSWORD")) {
    String userId = loggedInUsers.get(clientSocket);
    String newPassword = (String) in.readObject();

    if (userId != null && accounts.containsKey(userId)) {
        String[] userDetails = accounts.get(userId);
        userDetails[2] = newPassword; // 索引2对应密码字段
        accounts.put(userId, userDetails);
        out.writeObject("Password updated successfully!");
        saveAccounts(); // 保存修改到文件
    } else {
        out.writeObject("Failed to update password. Please check your login status.");
    }

3. 服务器添加LOGOUT指令处理分支

避免登出后服务器仍保留无效的登录记录:

} else if (option.equals("LOGOUT")) {
    loggedInUsers.remove(clientSocket);
    out.writeObject("Logout successful!");

4. 优化存款流程的服务器逻辑

确认服务器LODGE_MONEY分支的读写顺序与客户端完全匹配,并补充数据保存:

} else if (option.equals("LODGE_MONEY")) {
    String userId = loggedInUsers.get(clientSocket);
    double amountToLodge = in.readDouble();

    if (userId != null && accounts.containsKey(userId)) {
        String[] userDetails = accounts.get(userId);
        double currentBalance = Double.parseDouble(userDetails[userDetails.length - 1]);
        double updatedBalance = currentBalance + amountToLodge;
        userDetails[userDetails.length - 1] = String.valueOf(updatedBalance);
        accounts.put(userId, userDetails);
        out.writeDouble(updatedBalance);
        saveAccounts(); // 存款后保存账户信息
    } else {
        out.writeDouble(-1.0);
    }

额外注意事项

  • 所有未实现的指令(如RETRIEVE_USERS、VIEW_TRANSACTIONS等)都需要补充服务器处理逻辑,否则客户端发送这些指令后同样会陷入阻塞。
  • 可优化异常处理,捕获读取异常后及时关闭连接并清理登录记录,避免资源泄漏。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 07:17:04