Java 如何取消阻止ServerSocket.accept()上被阻止的线程?

Java 如何取消阻止ServerSocket.accept()上被阻止的线程?,java,sockets,Java,Sockets,我有一个带有以下代码的服务器线程: public void run() { try { ServerSocket server; EneaLog.printLog("Server is running."); server = new ServerSocket(this.portnumber); while (true) { new EneaServerConnection(server.accep

我有一个带有以下代码的服务器线程:

public void run() {
    try {
        ServerSocket server;
        EneaLog.printLog("Server is running.");
        server = new ServerSocket(this.portnumber);

        while (true) {
            new EneaServerConnection(server.accept(), this.project,stopped).start();
            if (stopped) {
                EneaLog.printLog("Server safe-shutdown completed.");
                EneaLog.printLog("Hi!");
                server.close();
                return;
            }
        }
    } catch (IOException ex) {
        Logger.getLogger(EneaServer.class.getName()).log(Level.SEVERE, null, ex);
        project.getExceptionHandler().handler(ex);
    }
}
还有一种关机方法,如下所示:

public void shutdown() {
    EneaLog.printLog("Server shutdown NOW!");
    stopped = true;
}
我希望关机可以解除阻止正在服务器上等待的线程。accept()否则我必须在服务器关机之前等待连接

我不能在shutdown()中执行server.close(),因为我必须向注册的客户端发出服务器即将关闭的信号

有什么想法吗?

你试过了吗

如果此线程在I/O中被阻塞 在可中断状态下的操作 频道,则频道将 关闭,线程的中断状态 将设置,线程将 接收ClosedByInterruptException

如果此线程在 然后选择线程的中断 将设置状态并返回 立即从选择中删除 操作,可能为非零 值,就像选择器的 已调用唤醒方法


我试着设计我的代码,这样它就可以被中断“关闭”。这主要是因为Java并发包中的
Executor
框架使用
interrupt
来取消正在运行的任务。此外,“shutdown”任务不必知道任务的任何内部被终止

但是,对
accept
的调用不会响应中断,除非是使用
ServerSocket
构造函数创建的服务器会忽略中断,我还没有找到重新配置的方法

如果无法更改创建服务器的代码,请安排另一个线程在服务器套接字上调用
close
。这也会在
accept
上阻塞的线程中引发异常,无论使用何种方法创建服务器套接字

在使用SSL时,这是一个非常大的难题。JSSE套接字不是从
interruptablechannel
创建的,不会响应线程上的简单中断


我刚刚注意到,问题是服务器不能在没有通知客户端的情况下关闭。成功中断套接字将导致其关闭

在调用
accept
时,这不应该是一个问题,因为如果服务器套接字在accept中被阻塞,则客户端不会连接。这应该只是表示当前连接的
Socket
实例的问题


如果这不符合通知要求,则可能需要在非阻塞模式下重新使用NIO的
ServerSocketChannel

您应该能够从另一个线程关闭套接字。

中断(与取消依赖于取消点的方式相同,它依赖于中断点)和关闭都不起作用(accept不响应于关闭其文件描述符)。您必须与accept进行通信(尝试sendto,并发出关闭通知)以通知它不继续接受。至少在linux上是这样;不知道在其他平台上是什么样子。

我也遇到过同样的问题。我的工作解决方案包括关闭ServerSocket对象(ServerSocket.close());执行此操作将导致accept()方法抛出SocketException,这就是您要执行的操作


Vincent

您需要在要中断的线程(即被阻止的线程)上调用它。嗯,回答得好。。也许我会改变解决问题的方法。我使用try-catch在客户端管理服务器关闭。我想知道您是否可以让服务器从一个单独的线程创建另一个客户端套接字,一旦accept()取消阻止它,现在取消阻止的循环可以以某种方式立即询问该客户端套接字..知道它是自己的客户端套接字。。。并设置一个标志以退出无止境循环。从未尝试过,但可能需要考虑一下,但听起来您需要修改服务器代码的能力。如果您有,只需使用
服务器socketchannel
。您最终如何解决此问题?很多人说close会起作用,但在我运行linux的情况下,close不起作用。