使用InputStreamReader/OutputStreamWriter实现C/S JSON交互遇阻求助
问题原因与解决方案
这个问题我遇过好多次啦,核心是客户端和服务器互相阻塞形成了死锁,咱们一步步拆解:
为什么会卡住?
- 首先看客户端代码:你调用
out.write(obj.toJSONString())之后,把out.flush()注释掉了。OutputStreamWriter自带缓冲区,默认不会立刻把数据发送到服务器,而是暂时存在客户端本地的缓冲区里。 - 服务器端的
parser.parse(in)方法会一直尝试从输入流读取完整的JSON数据,但因为客户端没把缓冲区里的JSON发过来,服务器就一直卡在这里等待数据。 - 与此同时,客户端写完数据后立刻执行
parser.parse(in),开始等待服务器的响应——两边都在等对方先行动,直接形成了死锁。 - 而当你移除客户端读取响应的代码时,客户端进程运行结束,JVM会自动关闭Socket的输出流,这时候缓冲区里的JSON数据才会被强制发送到服务器,所以服务器能正常处理请求。
怎么修复?
只需要做两个关键修改:
1. 客户端发送完JSON后强制刷新输出流
必须调用out.flush(),把缓冲区里的JSON数据立刻发送到服务器,这样服务器才能接收到请求并开始处理:
try (OutputStreamWriter out = new OutputStreamWriter(client.getOutputStream(), StandardCharsets.UTF_8)) { InputStreamReader in = new InputStreamReader(client.getInputStream(), StandardCharsets.UTF_8); out.write(obj.toJSONString()); out.flush(); // 这行必须加上,把数据推送到服务器 JSONParser parser = new JSONParser(); Object response = parser.parse(in); JSONObject jsonObj = (JSONObject) response; String resp = (String) jsonObj.get("response"); System.out.println(resp); }
2. 可选:告知服务器请求已发送完成
有些JSON解析库的parse(Reader)方法会一直读取直到流遇到EOF(结束标记),所以客户端在flush之后,可以关闭Socket的输出方向,告诉服务器“我不会再发数据了”,这样服务器的解析器就能确认JSON已经完整,顺利完成解析:
out.flush(); client.shutdownOutput(); // 关闭输出,保留输入流用于读取响应
服务器端的代码已经做了out.flush()发送响应,这部分是没问题的,不需要修改。
内容的提问来源于stack exchange,提问作者Alice
相关产品推荐
相关产品推荐

