java - 如何取消阻塞在 ServerSocket.accept() 上阻塞的线程?

标签 java sockets

我有一个带有这段代码的服务器线程:

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;
}

我希望关闭可以解锁正在等待 server.accept() 的线程,否则我必须在服务器关闭之前等待连接。

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

有什么想法吗?

最佳答案

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

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

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

事实证明,这在使用 SSL 时是一个非常大的痛苦。 JSSE 套接字不是从 InterruptibleChannel 创建的,也不会响应线程上的简单中断。


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

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

如果这不能满足通知要求,则可能需要在非阻塞模式下使用 NIO 的 ServerSocketChannel 进行返工。

关于java - 如何取消阻塞在 ServerSocket.accept() 上阻塞的线程?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1510403/

相关文章:

JAVA 10 - java.sql.SQLException : No suitable driver found for jdbc:mysql://localhost:3306/error

javascript - nodejs socket.io mysql 在套接字引用上缺少错误处理程序

C编程-> wpa_supplicant连接-> udp广播发送到 "Network Unreachable"

java - 无法在/WEB-INF/urlrewrite.xml 找到 urlrewrite conf 文件

我可以使用 inet_pton 为我的 TCP 套接字服务器设置文本地址,例如 "device1.local"吗?

linux - 不能同时监听 IPv4 和 IPv6(地址已被使用)

c++ - udp 服务器向特定客户端发送数据,直到收到任何 recvfrom

JAVA:当我尝试访问另一个类文件时,为什么总是收到错误:找不到符号?

库存程序的 Java 代码第 3 部分无法编译

java - ArrayList 构造器