Socket异常排查:未调用close却触发Cannot send after socket shutdown错误
问题分析与解决方案
我一眼就看到了问题的根源——你在HttpHijack类的send方法里,每次调用都会执行socket.shutdownOutput(),这直接把Socket的输出流给关了,后续自然没法再发数据了!
具体原因拆解
socket.shutdownOutput()这个方法的作用是永久禁用当前套接字的输出流,一旦调用,哪怕你没主动调用close(),这个Socket也再也无法写入任何数据了。你代码里的注释提到“关闭输出流来强制结束会话,方便读取stdout/stderr”,但这个操作是一次性的,执行完就彻底破坏了Socket的复用性,所以第二次调用sendStdinToConsole时,尝试写入就会抛出Cannot send after socket shutdown异常。
解决方案
根据你的需求(保持连接多次发送输入),这里有两种可行的调整方案:
方案1:移除shutdownOutput(),调整输入流读取逻辑
如果需要保持Socket连接多次发送命令,必须删掉send方法里的socket.shutdownOutput()。但要注意,Docker的exec会话在Tty模式下(你payload里设置了Tty: true),输入流不会自动关闭,所以要调整读取逻辑来实时获取输出:
修改HttpHijack的send方法:
public InputStream send(String command) throws java.io.IOException { if (!handshakeCompleted) { throw new IllegalStateException("Handshake not complete"); } chout.write(command.getBytes("UTF-8")); chout.flush(); // 移除socket.shutdownOutput(),保留Socket的输出能力 return socket.getInputStream(); }
然后修改sendStdinToConsole的读取逻辑,循环读取实时输出(可以根据业务场景添加退出条件,比如读取到特定字符串或者设置超时):
public String sendStdinToConsole(String stdin) { InputStream input = null; try { input = ws.send(stdin); BufferedReader reader = new BufferedReader(new InputStreamReader(input)); StringBuilder responseBuilder = new StringBuilder(); String line; // 循环读取输出,直到会话结束或手动断开 while ((line = reader.readLine()) != null) { responseBuilder.append(line).append("\n"); System.out.println(line); } return responseBuilder.toString(); } catch (IOException e) { e.printStackTrace(); } return null; }
方案2:仅在结束会话时调用shutdownOutput()
如果你希望只有发送exit这类结束命令时才关闭输出流,可以给send方法加个判断:
public InputStream send(String command) throws java.io.IOException { if (!handshakeCompleted) { throw new IllegalStateException("Handshake not complete"); } chout.write(command.getBytes("UTF-8")); chout.flush(); // 只有发送退出命令时才关闭输出流 if ("exit".equals(command.trim())) { socket.shutdownOutput(); } return socket.getInputStream(); }
额外注意点
- 你的
execConsole方法里设置了withTty(false),但payload里又写了"Tty": true,这会造成配置冲突,建议保持一致。Tty模式会直接影响输入输出的处理逻辑,比如是否需要处理终端控制字符、换行符格式等。 - 记得在主动断开连接时调用
ws.close(),及时释放Socket资源,避免资源泄漏。
内容的提问来源于stack exchange,提问作者qweq
相关产品推荐
相关产品推荐

