Java7异步NIO2服务器拒绝连接

4

我使用Java 7 NIO2编写了一个异步socket服务器。

以下是服务器的代码片段。

public class AsyncJava7Server implements Runnable, CounterProtocol, CounterServer{
    private int port = 0;
    private AsynchronousChannelGroup group;
    public AsyncJava7Server(int port) throws IOException, InterruptedException, ExecutionException {
        this.port = port;
    }

    public void run() {
        try {
            String localhostname = java.net.InetAddress.getLocalHost().getHostName();
            group = AsynchronousChannelGroup.withThreadPool(
                 Executors.newCachedThreadPool(new NamedThreadFactory("Channel_Group_Thread")));

            // open a server channel and bind to a free address, then accept a connection
            final AsynchronousServerSocketChannel asyncServerSocketChannel =
                           AsynchronousServerSocketChannel.open(group).bind(
                                 new InetSocketAddress(localhostname, port));

            asyncServerSocketChannel.accept(null, 
                 new CompletionHandler <AsynchronousSocketChannel, Object>() {
                            @Override
                            public void completed(final AsynchronousSocketChannel asyncSocketChannel, 
                                      Object attachment) {
                                    // Invoke simple handle accept code - only takes about 10 milliseconds.
                                    handleAccept(asyncSocketChannel); 
                                    asyncServerSocketChannel.accept(null, this);
            }
                            @Override
                            public void failed(Throwable exc, Object attachment) {
                                System.out.println("***********" + exc  + " statement=" + attachment);  
            }
                 });

这里是客户端代码片段,尝试连接...

public class AsyncJava7Client implements CounterProtocol, CounterClientBridge {
    AsynchronousSocketChannel asyncSocketChannel;

    private String serverName= null;
    private int port;
    private String clientName;

    public AsyncJava7Client(String clientName, String serverName, int port) throws IOException {
        this.clientName = clientName;
        this.serverName = serverName;
        this.port = port;
    }

    private void connectToServer() {
        Future<Void> connectFuture = null;
        try {
            log("Opening client async channel...");
            asyncSocketChannel = AsynchronousSocketChannel.open();

            // Connecting to server
            connectFuture = asyncSocketChannel.connect(new InetSocketAddress("Alex-PC", 9999));
       } catch (Exception ex) {
            ex.printStackTrace();
            throw new RuntimeException(ex);
       }
       // open a new socket channel and connect to the server
       long beginTime  = 0;
       try {
           // You have two seconds to connect. This will throw exception if server is not there.
           beginTime = System.currentTimeMillis();
           Void connectVoid = connectFuture.get(15, TimeUnit.SECONDS);
       } catch (Exception ex) {
           //EXCEPTIONS THROWN HERE AFTER ABOUT 150 CLIENTS
           long endTime = System.currentTimeMillis();
           long timeTaken = endTime - beginTime;
           log("************* TIME TAKEN=" + timeTaken);
           ex.printStackTrace();
           throw new RuntimeException(ex);
       }
 }

我有一个测试任务需要触发客户端。

 @Test
 public void testManyClientsAtSametime() throws Exception {
     int clientsize = 150;
     ScheduledThreadPoolExecutor executor = 
            (ScheduledThreadPoolExecutor) Executors.newScheduledThreadPool(clientsize + 1, 
                new NamedThreadFactory("Test_Thread"));
     AsyncJava7Server asyncJava7Server = startServer();
     List<AsyncJava7Client> clients = new ArrayList<AsyncJava7Client>();
     List<Future<String>> results = new ArrayList<Future<String>>();

     for (int i = 0; i < clientsize; i++) {
         // Now start a client
         final AsyncJava7Client client = 
               new AsyncJava7Client("client" + i, InetAddress.getLocalHost().getHostName(), 9999);
         clients.add(client);
     }

     long beginTime = System.currentTimeMillis();
     Random random = new Random();
     for (final AsyncJava7Client client: clients) {
         Callable<String> callable = new Callable<String>() {
             public String call() {
                 ...
                 ... invoke APIs to connect client to server
                 ...
                 return counterValue;
             }
     };

     long delay = random.nextLong() % 10000;  // somewhere between 0 and 10 seconds.
     Future<String> startClientFuture = executor.schedule(callable, delay, TimeUnit.MILLISECONDS);
     results.add(startClientFuture);
 }

它在大约100个客户端中超级有效。当到达140+时,我会在客户端中遇到大量异常 - 当它尝试连接时。异常是:java.util.concurrent.ExecutionException: java.io.IOException:远程计算机拒绝了网络连接。

我的测试在运行Windows 7的单个笔记本电脑上进行。当它失败时,我检查TCP连接,有大约500-600个连接 - 这是可以接受的。因为我有类似的JDK 1.0 java.net套接字程序,可以处理4,000个TCP连接。

服务器中没有异常或任何可疑的东西。

所以我不知道这里可能出了什么问题。有什么想法吗?


你是否没有正确关闭连接?换句话说,当你刚刚重启电脑和运行测试10次时,140的限制是否相同?随着你不断运行测试,这个限制是否会降低? - assylias
1个回答

4
尝试使用接受后备限制的bind形式,并将其设置为较高的数字。例如:
            final AsynchronousServerSocketChannel asyncServerSocketChannel =
                       AsynchronousServerSocketChannel.open(group).bind(
                             new InetSocketAddress(localhostname, port), 1000);

我不知道win7默认的实现限制是什么,但它可能是拒绝连接的原因。

1
做得好。默认限制为50个连接。你的解决方案有效。谢谢。 - dublintech
@dublintech:快速提问——你在哪里找到默认限制为50的信息?我只是匆匆看了一眼,但没有看到它。 - philwb
通过实验,我发现在你发布之前是50,但不知道你的解决方案。 - dublintech

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接