TCP服务端读取消息失败:客户端无while循环触发Connection reset原因
异常触发原因
这个问题是两个常见的TCP通信低级错误叠加导致的:
PrintWriter默认未开启自动刷新
你在客户端调用out.println("lol")之后,数据并没有直接发送到网络,而是暂存在客户端本地的IO缓冲区里,默认要等缓冲区满、或者主动调用flush()/close()才会真正发出去。- 客户端进程提前异常终止连接
你的客户端写完数据后没有后续逻辑,会直接退出进程,此时操作系统发现TCP连接还有未发送的缓冲数据,不会走正常的四次挥手关闭流程,而是直接向服务端发送RST包强制重置连接。
服务端此时阻塞在reader.readLine()等待数据,收到RST包就会抛出Connection reset异常。
加死循环后正常运行的原因
你把发送逻辑包在while(true)死循环里后:
- 客户端进程不会立刻退出,连接不会被强制重置
- 循环持续调用
out.println()会很快把本地IO缓冲区攒满,触发自动刷新,数据真正发送到服务端,因此服务端可以正常读取。
正确修复方案
不需要给客户端加无意义的死循环,修改客户端代码即可:
Socket socket = new Socket("localhost", 9101); // 构造PrintWriter时开启自动刷新,第二个参数传true PrintWriter out = new PrintWriter(socket.getOutputStream(), true); BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream())); out.println("lol"); // 如果没开自动刷新,需要手动加这行刷缓冲区 // out.flush(); // 通信完成后走正常关闭流程,不要直接让进程结束 socket.close();
如果服务端需要同时处理多个客户端,建议把每个客户端连接的读写逻辑放到独立子线程中执行,避免主线程阻塞无法接收新连接。
内容的提问来源于stack exchange,提问作者Ineversurrender93
相关产品推荐
相关产品推荐

