2012-10-19 147 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)所致。尝试在连接到服务器之前以毫秒为单位给出时间间隔。像增加连接一样。当我运行测试负载时,我通过给出一些时间间隙来解决它。