【问题标题】:Java - closing a ServerSocket without Exceptions?Java - 无异常关闭 ServerSocket?
【发布时间】:2014-08-25 18:41:49
【问题描述】:

多年来,我一直想知道在 Java 中关闭侦听 ServerSocket 的正确方法是什么。我的实现总是这样工作,他们:

  1. 创建一个新的 ServerSocket(int)。
  2. 在 while (true) 循环中启动一个调用其 accept() 方法的线程。
  3. 当 accept() 返回(客户端连接)时启动另一个线程,该线程从客户端读取直到断开连接。然后,accept 线程继续另一个 accept() 调用。

但是当我因为我的应用程序正在退出而想关闭 ServerSocket 时,除了调用它的 close() 方法(在我关闭所有客户端套接字之后)之外,我从未找到其他方法,这会导致 accept( ) 抛出一个 SocketException,我捕获它并从接受线程中的 while (true) 循环中中断,导致我的所有线程退出。

我认为这很难看,严格来说没有发生异常,关闭我的ServerSocket是我程序正常操作的一部分。

真的没有其他方法可以在不引发异常的情况下做到这一点吗?

谢谢。

【问题讨论】:

标签: java multithreading exception connection serversocket


【解决方案1】:

除了调用它的 close() 方法(在我关闭所有客户端套接字之后)之外,我从未找到其他方法,

您可以设置一个标志closed = true; 并打开一个虚拟连接以唤醒在继续之前检查标志的accept()ing 线程。

这会导致accept()抛出一个SocketException,

一个 SocketClosedException,这是这里的预期行为。

我抓住了它并从接受线程中的 while (true) 循环中中断,

如果你在循环外捕获它,你不需要也跳出循环。如果抛出异常并且您设置了closed = true,则可以丢弃该异常。

顺便说一句,我会做的

while(!serverSocket.isClosed()) {

导致我的所有线程退出。

您没有特别的理由需要这样做,但您可以根据需要选择这样做。

我觉得这很丑,严格来说没有异常发生,

发生了异常情况。没有发生的是错误。

关闭我的 ServerSocket 是我的程序正常操作的一部分。

或者你可以说它在运行而不是关闭时运行正常。

【讨论】:

    【解决方案2】:

    感谢您的评论。

    你可以设置一个标志 closed = true;并打开一个虚拟连接以唤醒 accept()ing 线程,该线程在继续之前检查标志。

    打开一个新的 Socket 来关闭一个现有的? IMO 这是有史以来最严重的罪行之一。

    一个 SocketClosedException,这是这里的预期行为。

    其实它并没有抛出一个SocketClosedException而是一个SocketException,如下代码:

    try {
        final ServerSocket ss = new ServerSocket(1234);
        new Thread(new Runnable() {
    
            @Override
            public void run() {
                try {
                    ss.accept();
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            }
    
        }).start();
        ss.close();
    } catch (Exception ex) {
        ex.printStackTrace();
    }
    

    产生以下输出:

    java.net.SocketException: Socket is closed
    at java.net.ServerSocket.accept(ServerSocket.java:494)
    at Main$1.run(Main.java:12)
    at java.lang.Thread.run(Thread.java:744)
    

    如果你在循环外捕获它,你不需要也跳出循环。如果抛出异常并且你设置了 closed = true 你可以丢弃异常。

    顺便说一句,我会这样做

    while(!serverSocket.isClosed()) {

    这可行,但我认为这应该可以在不设置标志和捕获异常的情况下工作。

    发生了异常情况。没有发生的是错误。

    或者你可以说它在运行而不是关闭时运行正常。

    我不同意。应用程序退出是正常行为。他们可能总是这样做。

    为什么在调用 close() 时,accept() 方法不只返回 null?那会容易得多。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-05-28
      • 2014-07-20
      • 2016-02-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-18
      相关资源
      最近更新 更多