Java:多线程服务器中正确关闭套接字

4

我正在尝试创建一个多线程服务器,多个客户端可以连接并得到服务。但是,如果需要,我不确定如何正确释放我的资源。

我的服务器运行一个输入线程(等待用户输入)和一个处理线程(处理连接和用户)。在服务器类中打开ServerSocket并将其传递给处理线程。代码如下:

public class ClientConnector implements Runnable {

private ServerSocket serverSocket;

public ClientConnector(ServerSocket serverSocket) {
    this.serverSocket = serverSocket;
}

@Override
public void run() {
    ExecutorService tcpExecutor = Executors.newCachedThreadPool();

    while (!serverSocket.isClosed()) {
        Socket clientSocket = null;

        try {
            clientSocket = serverSocket.accept();
        } catch (IOException e) {
            System.err.println("could not accept connection");
        }

        if (clientSocket != null) {
            tcpExecutor.execute(new ClientHandler(clientSocket);
        }           
    }   
}
}

如果我想退出,只需在我的服务器类中运行此方法来关闭ServerSocket:

public void exit() {
    try {
        serverSocket.close();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

这将导致下一个serverSocket.accept()调用抛出异常,循环停止,因为套接字已关闭。

我的问题是 - 关闭ServerSocket是否会隐式关闭使用它创建的ClientSocket?还是我应该手动关闭每个打开的ClientSocket?如果是这样,是否有一种简单的方法来做到这一点,而不是在服务器上保存每个连接?


问题在于任何在我们关闭服务器套接字时打开的套接字都是因为它们正被阻塞等待来自客户端的输入。而且它们是一种奇怪的阻塞,甚至无法被中断。即使发送一个空包以解除套接字的阻塞也行不通,因为它们正在等待与第三方建立的已经建立好的连接,你无法在这些连接中插入一个空包。那么,你找到解决方法了吗? - Mike Nakis
2个回答

1

关闭ServerSocket会隐式关闭使用它创建的ClientSockets吗?

不会,对它们没有影响。

或者我应该手动关闭每个打开的ClientSocket吗?

是的,而且在每个处理程序线程中都应该这样做。

如果是这样,有没有一种简单的方法来关闭所有连接,而不必保存在服务器上建立的每个连接?

只需强制执行读取超时并关闭每个超时的套接字即可。这是任何服务器的正常部分。您不必收集套接字或采取任何特殊措施来关闭它们。


0
让客户端处理线程在处理完成后关闭客户端套接字。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接