Java实现基础RPC服务器时遭遇连接中止错误求助
Java RPC服务器连接中止问题排查与修复
我正在尝试用Java实现一个基础的RPC服务器,客户端发送操作指令后,服务器从数据库获取数据并返回给客户端,但遇到了java.net.SocketException: An established connection was aborted by the software in your host machine错误,相关代码和错误信息如下:
服务器代码
@Override public void run() { String operationType; int id; while (!socket.isClosed()) { try { operationType = in.readUTF(); if (operationType.equals("Take test!")) { Future future = pool.submit((Callable) () -> { return studentDAO.getTest(1); }); Object obj = future.get(); objOut.writeObject(obj); pool.shutdown(); } //notifyAllUsers(type); } catch (IOException | InterruptedException | ExecutionException ex) { System.out.println(ex.getLocalizedMessage()); close(socket, in, out, objIn, objOut); break; } } }
客户端代码
public void applyChanges(String operation) { new Thread( () -> { try { if (operation.equals("Take test!")) { out.writeUTF(operation); //objOut.writeInt(1); Test test = (Test) objIn.readObject(); System.out.println(test.getTestName()); } } catch (IOException | ClassNotFoundException ex) { close(socket, in, out, objIn, objOut); } }, "applyThread" ).start(); }
错误信息
run: Client accepted! java.net.SocketException: An established connection was aborted by the software in your host machine at java.base/sun.nio.ch.NioSocketImpl.implWrite(NioSocketImpl.java:417) at java.base/sun.nio.ch.NioSocketImpl.write(NioSocketImpl.java:437) at java.base/sun.nio.ch.NioSocketImpl$2.write(NioSocketImpl.java:823) at java.base/java.net.Socket$SocketOutputStream.write(Socket.java:1035) true at java.base/java.io.ObjectOutputStream$BlockDataOutputStream.drain(ObjectOutputStream.java:1901) at java.base/java.io.ObjectOutputStream$BlockDataOutputStream.setBlockDataMode(ObjectOutputStream.java:1810) at java.base/java.io.ObjectOutputStream.writeNonProxyDesc(ObjectOutputStream.java:1304) at java.base/java.io.ObjectOutputStream.writeClassDesc(ObjectOutputStream.java:1249) at java.base/java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1445) at java.base/java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1196) at java.base/java.io.ObjectOutputStream.writeFatalException(ObjectOutputStream.java:1617) Socket closed at java.base/java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:365) at server.ClientHandler.run(ClientHandler.java:63) at java.base/java.lang.Thread.run(Thread.java:833)
问题根源与修复方案
线程池过早关闭
服务器处理完第一个请求就调用pool.shutdown(),这会终止线程池的所有后续任务提交,且可能导致线程池资源异常,间接引发连接中断。应将线程池的关闭逻辑绑定到服务器生命周期(如服务器停止时),而非单次请求后。对象输出流未刷新
服务器写入对象后未调用objOut.flush(),导致数据滞留在缓冲区,客户端长时间等待响应后主动关闭连接,服务器再写入时就会触发连接中止错误。Test类序列化检查
确保Test类实现Serializable接口,否则ObjectOutputStream写入时会抛出序列化异常,也会间接导致连接中断。
修复后的服务器代码
@Override public void run() { String operationType; int id; while (!socket.isClosed()) { try { operationType = in.readUTF(); if (operationType.equals("Take test!")) { Future future = pool.submit((Callable) () -> { return studentDAO.getTest(1); }); Object obj = future.get(); objOut.writeObject(obj); objOut.flush(); // 强制刷新缓冲区,确保数据发送到客户端 // 移除此处的pool.shutdown(),线程池在服务器关闭时统一关闭 } //notifyAllUsers(type); } catch (IOException | InterruptedException | ExecutionException ex) { System.out.println(ex.getLocalizedMessage()); close(socket, in, out, objIn, objOut); break; } } }
内容的提问来源于stack exchange,提问作者Milos
相关产品推荐
相关产品推荐

