4

I have written a async socketserver using java 7 nio2.

Here is a snipper of the Server.

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);  
            }
                 });

and here is a snippet of the client code which tries to connect...

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);
       }
 }

I have a test which fires off clients.

 @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);
 }

It works super for about 100 clients. At about 140+ I get a load of exceptions in the client - when it tries to connect. The exception is: java.util.concurrent.ExecutionException: java.io.IOException: The remote computer refused the network connection.

My test is on a single laptop running windows 7. When it bombs out I check the TCP connections and there about 500 - 600 connections -that's ok. AS I have similiar JDK 1.0 java.net socket programs that can handle 4,000 TCP connections.

No exceptions or anything dodgy looking in server.

So I am at a loss as to what could be wrong here. any ideas?

dublintech
  • 16,815
  • 29
  • 84
  • 115
  • Could it be that you don't close the connections properly? In other words, is the limit of 140 or so the same when you have just restarted your computer and when you have run your test 10 times? Does that limit go down as you keep running the test? – assylias Oct 31 '12 at 10:19

1 Answers1

4

Try using the form of bind that accepts a backlog limit and set that to a higher number. For example:

            final AsynchronousServerSocketChannel asyncServerSocketChannel =
                       AsynchronousServerSocketChannel.open(group).bind(
                             new InetSocketAddress(localhostname, port), 1000);

I don't know what the win7 implementation limit is by default but can be a cause of refused connections.

philwb
  • 3,805
  • 19
  • 20