Java - 关闭没有异常的ServerSocket?

时间:2014-07-04 12:13:02

标签: java multithreading exception connection serversocket

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

  1. 创建一个新的ServerSocket(int)。
  2. 启动一个在while(true)循环中调用其accept()方法的线程。
  3. 当accept()返回(客户端连接)从客户端读取直到它断开连接时,启动另一个线程。接受线程然后继续另一个accept()调用。
  4. 但是当我想要关闭ServerSocket因为我的应用程序正在退出时,除了调用它的close()方法(在我关闭所有客户端套接字之后)之外,我从未找到另一种方法,这会导致接受( )抛出一个SocketException,我抓住它并从接受线程中的while(true)循环中断,导致我的所有线程退出。

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

    在没有引起异常抛出的情况下,真的没有其他办法吗?

    感谢。

2 个答案:

答案 0 :(得分:1)

  

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

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

  

导致accept()抛出SocketException,

SocketClosedException,这是预期的行为。

  

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

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

顺便说一下,我会这样做

while(!serverSocket.isClosed()) {
  

导致我的所有线程退出。

您没有特别需要这样做,但如果您愿意,可以选择这样做。

  

我认为这很难看,严格来说没有例外,

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

  

关闭我的ServerSocket是我程序正常运行的一部分。

或者你可以说当它正在运行而没有关机时它正常运行。

答案 1 :(得分:0)

感谢您的评论。

  

你可以设置一个标志关闭=真;并打开一个虚拟连接来唤醒在继续之前检查该标志的accept()线程。

打开一个新的Socket以关闭现有的Socket?国际海事组织是有史以来最严重的罪行之一。

  

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()){

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

  

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

     

或者你可以说当它正在运行而没有关机时它正常运行。

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

为什么accept()方法在调用close()时才返回null?那会更容易。