TCP银行应用登录后冻结:寻求无响应问题解决方案
TCP银行应用登录后冻结及EOFException问题修复
问题根源分析
- ObjectOutputStream缓冲未刷新:客户端发送数据后未调用
flush(),导致数据滞留在缓冲区,服务器无法及时接收,双方陷入阻塞,最终触发EOFException。 - 服务器缺失指令处理分支:客户端发送的
UPDATE_PASSWORD指令在服务器中没有对应的处理逻辑,服务器持续等待后续数据,客户端等待响应,导致阻塞。 - 通信同步问题:部分流程中客户端与服务器的读写顺序虽逻辑正确,但缓冲延迟导致实际通信不同步,引发阻塞。
具体修复步骤
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
相关产品推荐
相关产品推荐

