2012-10-19 73 views
10

我正在使用套接字運行一些測試,而且我遇到了一些奇怪的行爲:即使客戶端套接字在下一個套接字打開之前關閉,ServerSocket將在第50個客戶端套接字連接到套接字後拒絕連接,即使在連接之間添加延遲。Java ServerSocket連接限制?

以下程序是我的實驗代碼,它在當前狀態下不會拋出異常並正常終止。但是,如果Socket[] clients的陣列大小增加到50以上,則在第50次連接後試圖連接的任何客戶端套接字都會被服務器套接字拒絕。

問題:爲什麼50套接字連接被服務器套接字拒絕的計數?

public static void main(String[] args) { 
    try (ServerSocket server = new ServerSocket(2123)) { 
     Socket[] clients = new Socket[50]; 
     for (int i = 0; i < clients.length; i++) { 
      clients[i] = new Socket("localhost", 2123); 
      System.out.printf("Client %2d: " + clients[i] + "%n", i); 
      clients[i].close(); 
     } 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
} 

我已經運行在那裏另外50座連接到另一臺本地服務器的測試,並與發生在打開和關閉100座沒有問題,所以我推斷,它的服務器套接字拒絕連接,而不是一些開放客戶端套接字的限制,但我一直無法發現爲什麼服務器套接字限制爲50個連接,即使它們沒有同時連接。

回答

12

這一切都在JavaDoc

傳入連接指示的最大隊列長度(連接請求)如果在隊列已滿的連接指示到達被設置爲50,則連接被拒絕。

顯然你的ServerSocket永遠不會接受任何連接,只是監聽。您必須調用accept(),並開始處理連接或增加backlog隊列大小:

new ServerSocket(port, 100) 
+2

當客戶端套接字關閉時,隊列中的連接不會被刪除嗎? – Vulcan

+1

@Vulcan顯然不是。 – EJP

+1

@EJP是的,但他們爲什麼不呢?對我來說,閉合​​套接字仍然排隊等待連接似乎很奇怪。我想服務器套接字無法知道客戶端套接字是封閉的。 – Vulcan

2

這裏有一個工作的例子,按照@ TomaszNurkiewicz的回答是:

import java.net.*; 
import java.util.concurrent.atomic.AtomicBoolean; 

public class SockTest{ 
public static void main(String[] args) { 
    final AtomicBoolean shouldRun = new AtomicBoolean(true); 
    try { 
     final ServerSocket server = new ServerSocket(2123); 
     Thread serverThread = new Thread(){ 
      public void run() { 
       try { 
       while(shouldRun.get()) { 
       Socket s = server.accept(); 
       s.close(); 
      Thread.sleep(1); 
       } 
       } catch(Exception ex) { 
       ex.printStackTrace(); 
       } 
      } 
     }; 
     serverThread.start(); 
     Socket[] clients = new Socket[150]; 
     for (int i = 0; i < clients.length; i++) { 
      clients[i] = new Socket("localhost", 2123); 
      System.out.printf("Client %2d: " + clients[i] + "%n", i); 
      clients[i].close(); 
     } 
     shouldRun.set(false); 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } finally { 
     shouldRun.set(false); 
    } 

    } 
} 
+0

謝謝;在我看到@ TomaszNurkiewicz的回答之後,我實際上創建了一個類似的例子,但並沒有像你的那樣乾淨地完成(我忘了AtomicBoolean,並用相同的功能做了我自己的臨時類)。 +1 – Vulcan

0

兩件事情你可能看看

  1. 服務器不接受連接。
  2. 服務器無法在同一時間迎合太多的連接。這可能是由於積壓增加(超過50)所致。嘗試在連接到服務器之前以毫秒爲單位給出時間間隔。像增加連接一樣。當我運行測試負載時,我通過給出一些時間間隙來解決它。