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
相关产品推荐
相关产品推荐

