套接字关闭后无法发送

时间:2018-01-24 12:28:28

标签: java

我正在尝试打开一个连接并保持打开,直到我决定关闭它。 它适用于第一个sendStdinToConsole,但当我再次调用该函数时,我得到:

  

java.net.SocketException:套接字关闭后无法发送:套接字写入错误

我从不打电话给close()。为什么要关闭?

基本上,当我点击连接按钮时,我只想execConsole一次。每次我点击另一个按钮,它都会向WebSocket发送一个输入,直到我断开它为止。

 private HttpHijack ws = null;

public HttpHijack execConsole(String containerName, String command, String user) {
    Settings settings = Settings.getSettings();
    DockerClient dockerClient = dockerClient();
    Container container = getContainer(containerName);
    ExecCreateCmdResponse execCreateCmdResponse = dockerClient.execCreateCmd(container.getId()).withAttachStdout(true).withAttachStdin(true).withTty(false).withAttachStderr(true).withCmd(command).withUser(user).exec();
    HashMap<String, String> headers = new HashMap<>();
    headers.put("Content-Type", "application/json");


    try {
        ws = new HttpHijack(new URI("http://" + settings.getDockerIP() + ":" + settings.getDockerPort() + "/exec/" + execCreateCmdResponse.getId() + "/start"));
    } catch (URISyntaxException e) {
        e.printStackTrace();
    }
    String payload = "{\"Detach\": false,\"Tty\": true}";
    try {
        ws.post(headers, payload);
    } catch (IOException e) {
        e.printStackTrace();
    }
    return ws;
}

public String sendStdinToConsole(String stdin) {
    InputStream input = null;

    try {

        input = ws.send(stdin);
    } catch (IOException e) {
        e.printStackTrace();
    }

    String response = null;
    try {
        response = IOUtils.readLines(input).toString();
    } catch (IOException e) {
        e.printStackTrace();
    }
    System.out.println(response);

    return response;
}

HIJACK CLASS

public class HttpHijack {

private static final Logger log = LoggerFactory.getLogger(HttpHijack.class);

private URI uri;

private Socket socket;

private boolean handshakeCompleted;

private InputStream chin;

private OutputStream chout;

public HttpHijack(URI url) {
    uri = url;
}

public void post(Map<String, String> headers, String payload) throws java.io.IOException {
    String host = uri.getHost();
    String path = uri.getPath();
    if (path.equals("")) {
        path = "/";
    }

    String query = uri.getQuery();
    if (query != null) {
        path = path + "?" + query;
    }

    socket = createSocket();

    chout = socket.getOutputStream();
    StringBuffer extraHeaders = new StringBuffer();
    if (headers != null) {
        for (Entry<String, String> entry : headers.entrySet()) {
            extraHeaders.append(entry.getKey() + ": " + entry.getValue() + "\r\n");
        }
    }

    StringBuffer request = new StringBuffer();
    request.append("POST " + path + " HTTP/1.1\r\n");
    request.append("Upgrade: tcp\r\n");
    request.append("Connection: Upgrade\r\n");
    request.append("Host: " + host + "\r\n");

    if (headers != null) {
        for (Entry<String, String> entry : headers.entrySet()) {
            request.append(entry.getKey() + ": " + entry.getValue() + "\r\n");
        }
    }

    request.append("Content-Length: " + payload.length() + "\r\n");

    request.append("\r\n");
    request.append(payload);

    chout.write(request.toString().getBytes());
    chout.flush();

    chin = socket.getInputStream();
    BufferedReader reader = new BufferedReader(new InputStreamReader(chin));
    String header = reader.readLine();
    if (!header.equals("HTTP/1.1 101 UPGRADED")) {
        throw new IOException("Invalid handshake response: " + header);
    }

    do {
        header = reader.readLine();
        log.info("header: {}", header);
    } while (!header.equals(""));

    handshakeCompleted = true;
}

private Socket createSocket() throws java.io.IOException {
    String scheme = uri.getScheme();
    String host = uri.getHost();

    int port = uri.getPort();
    if (port == -1) {
        if (scheme.equals("https")) {
            port = 443;
        } else if (scheme.equals("http")) {
            port = 80;
        } else {
            throw new IllegalArgumentException("Unsupported scheme");
        }
    }

    if (scheme.equals("https")) {
        SocketFactory factory = SSLSocketFactory.getDefault();
        return factory.createSocket(host, port);
    } else {
        return new Socket(host, port);
    }
}

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();
    // looks like "exit" can't explicitly close the session,
    // shutdown output stream to force close it
    // so that stdout/stderr can be consumed via inputstream
    socket.shutdownOutput();

    return socket.getInputStream();
}

public void close() throws java.io.IOException {
    chin.close();
    chout.close();
    socket.close();
}

}

2 个答案:

答案 0 :(得分:0)

您在socket.shutdownOutput功能结束时执行了send()。然后,您尝试再次发送sendStdinToConsole(),但输出仍将关闭。或者在哪里再次启用输出?

答案 1 :(得分:0)

您尝试连接的终端设备未启用 telnet。