2014-07-04 53 views
3

多年來我一直在想知道在Java中關閉一個ServerSocket的正確方法是什麼。我的實現總是像這樣工作,他們:Java - 關閉一個沒有例外的ServerSocket?

  1. 創建一個新的ServerSocket(int)。
  2. 在while(true)循環中啓動一個調用其accept()方法的線程。
  3. 當accept()返回(客戶端連接)從客戶端讀取直到它斷開連接時啓動另一個線程。接受線程繼續進行另一個accept()調用。

但是,當我想關閉ServerSocket是因爲我的應用程序正在退出,除了調用它的close()方法(關閉所有客戶端套接字之後)之外,我從未找到另一種方法,導致accept()拋出一個SocketException異常,我接受並從accept線程中的while(true)循環中斷開,導致我的所有線程退出。

我覺得這很醜陋,嚴格來說沒有異常發生,關閉我的ServerSocket是我的程序正常運行的一部分。

是否真的沒有其他方式做到這一點,而不會導致異常被拋出?

謝謝。

+0

似乎沒有辦法:http://stackoverflow.com/questions/9681531 –

+0

可能重複[優雅的關機服務器套接字在Linux](http://stackoverflow.com/questions/9681531/graceful-shutdown-server-插座在Linux的) – laune

回答

1

我從來沒有發現比調用它的close()方法(我已經關閉後,所有客戶端套接字)這樣其他的另一種方式,

您可以設置一個標誌closed = true;並打開虛擬連接喚醒accept()ing線程,在繼續之前檢查該標誌。

導致接受()來拋出SocketException,

一個SocketClosedException其在此預期的行爲。

我趕上,並在接收線程從while(true)循環打破,

如果你抓住它的循環之外,你不需要也打破循環。如果引發異常並且已設置closed = true,則可以放棄該異常。

BTW,我會做

while(!serverSocket.isClosed()) { 

導致我的所有線程退出。

沒有什麼特別的理由需要這樣做,但是如果你願意,你可以選擇這樣做。

我覺得這是醜陋的,嚴格來說沒有什麼異常發生,

異常情況正在發生。什麼沒有發生是一個錯誤。

關閉我的ServerSocket是我的程序正常運行的一部分。

或者你可以說它在運行時並沒有關閉時正常運行。

0

感謝您的評論。

您可以設置一個標誌closed = true;並打開一個虛擬連接來喚醒accept()ing線程,在繼續之前檢查該標誌。

打開一個新的套接字來關閉一個現有的套接字?海事組織是有史以來最嚴重的罪之一。

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,則可以放棄異常。

BTW,我會做

而(!serverSocket.isClosed()){

這樣做是可以的,但我認爲這應該沒有設置標誌和捕獲異常的工作。

出現異常情況。什麼沒有發生是一個錯誤。

或者你可以說它運行正常並且沒有關閉。

我不同意。應用程序退出是正常行爲。他們可能總是這樣做。

爲什麼accept()方法在調用close()時僅返回null?那會容易得多。