当客户端关闭 TCP 连接时中断服务器线程

Interrupt server thread when client closes TCP connection

我在 Java 中有一个多线程 TCP 服务器,它允许来自多个客户端的连接并为每个连接的客户端启动一个新的 ServerThread:

服务器Class:

while (!Thread.currentThread().isInterrupted()) {
    try {
        // Create a new thread for each incoming connection.
        Socket clientSocket = serverSocket.accept();
        ServerThread serverThread = new ServerThread(clientSocket, this);
        serverThread.run();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

特定超时后,客户端关闭其套接字。如何中断与客户端连接的 ServerThread? clientsocket.isClosed()!clientSocket.isConnected() 由于某种原因不起作用。

最后,我通过以下代码片段得到了它(解决方案是资源块中的套接字和无尽的in.readLine() == null):

服务器class

public void run() {
    while (!Thread.currentThread().isInterrupted()) {
        try {
            // Create a new thread for each incoming connection.
            Socket clientSocket = serverSocket.accept();
            ServerThread serverThread = new ServerThread(clientSocket, this);
            serverThread.start();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

服务器线程class:

public void run() {
    try (Socket socket = clientSocket; // Enable auto-close for socket...
         PrintWriter out = ...; BufferedReader in = ...;) {

        ...

        while (!clientSocket.isClosed() && !isInterrupted()) {
            if (in.readLine() == null) {
                break;
            }
        }
        System.err.println("Client with port " + clientSocket.getPort() + " closed connection to server.");
    } catch (IOException e) {
        e.printStackTrace();
    }
}

客户端class:我使用与ServerThread中相同的资源块尝试class

如果客户端在没有发送显式 FIN 的情况下不干净地关闭了 TCP 套接字(例如,如果客户端崩溃),那么服务器将不知道它,直到它下一次尝试向客户端发送数据包(此时客户端将发送一个 RST 数据包来告诉服务器套接字已关闭)。

假设您可以控制客户端和服务器代码,检查连接的最稳健方法是在两者之间实施心跳机制,以便它们定期 ping 一小段数据以检查连接的有效性连接。

Keep alive 套接字选项是观察持续 TCP 连接的标准方式。 如果您的服务器在中止期间处于阻塞读取操作,您将得到 java.io.IOException:读取失败。在异步情况下,您将收到带 -1 的读取密钥。 在写入状态下,您将得到:连接由对等方重置:套接字写入错误。 如果连接不可恢复,只需处理异常或错误代码以关闭线程。