当客户端关闭 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 的读取密钥。
在写入状态下,您将得到:连接由对等方重置:套接字写入错误。
如果连接不可恢复,只需处理异常或错误代码以关闭线程。
我在 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 的读取密钥。 在写入状态下,您将得到:连接由对等方重置:套接字写入错误。 如果连接不可恢复,只需处理异常或错误代码以关闭线程。