1

I had developed a server channel socket using below code:

public class EchoServer {
private static final int BUFFER_SIZE = 1024;

private final static int DEFAULT_PORT = 9090;

private long numMessages = 0;

private long loopTime;

private InetAddress hostAddress = null;

private int port;

private Selector selector;

// The buffer into which we'll read data when it's available
private ByteBuffer readBuffer = ByteBuffer.allocate(BUFFER_SIZE);

int timestamp=0;

public EchoServer() throws IOException {
    this(DEFAULT_PORT);
}

public EchoServer(int port) throws IOException {
    this.port = port;
    hostAddress = InetAddress.getByName("127.0.0.1");
    selector = initSelector();
    loop();
}

private Selector initSelector() throws IOException {
    Selector socketSelector = SelectorProvider.provider().openSelector();

    ServerSocketChannel serverChannel = ServerSocketChannel.open();
    serverChannel.configureBlocking(false);

    InetSocketAddress isa = new InetSocketAddress(hostAddress, port);
    serverChannel.socket().bind(isa);
    serverChannel.register(socketSelector, SelectionKey.OP_ACCEPT);
    return socketSelector;
}

private void loop() {
    for (;true;) {
        try {
            selector.select();
            Iterator<SelectionKey> selectedKeys = selector.selectedKeys()
                    .iterator();
            while (selectedKeys.hasNext()) {
                SelectionKey key = selectedKeys.next();
                selectedKeys.remove();
                if (!key.isValid()) {
                    continue;
                }
                 // Check what event is available and deal with it
                if (key.isAcceptable()) {
                    accept(key);
                } else if (key.isWritable()) {
                    write(key);
                }
            }
            Thread.sleep(3000);
            timestamp+=3;
        } catch (Exception e) {
            e.printStackTrace();
            System.exit(1);
        }



    }
}

private void accept(SelectionKey key) throws IOException {

    ServerSocketChannel serverSocketChannel = (ServerSocketChannel) key.channel();

    SocketChannel socketChannel = serverSocketChannel.accept();
    socketChannel.configureBlocking(false);
    socketChannel.setOption(StandardSocketOptions.SO_KEEPALIVE, true);
    socketChannel.setOption(StandardSocketOptions.TCP_NODELAY, true);
  //  socketChannel.register(selector, SelectionKey.OP_READ);
    socketChannel.register(selector, SelectionKey.OP_WRITE);

    System.out.println("Client is connected");
}

private void write(SelectionKey key) throws IOException {
    SocketChannel socketChannel = (SocketChannel) key.channel();
    ByteBuffer dummyResponse = ByteBuffer.wrap(("ok:" + String.valueOf(timestamp)) .getBytes("UTF-8"));

    socketChannel.write(dummyResponse);
    if (dummyResponse.remaining() > 0) {
        System.err.print("Filled UP");
    }
    System.out.println("Message Sent");
 //   key.interestOps(SelectionKey.OP_READ);
}

}

As you can see I run it on localhost port 9090. In order to testing the code for heavy connections I developed a test app that each second run a new thread and connect to the server. This is the code of my test app:

    public class Main {

    /**
     * @param args
     */
    public static void main(String[] args) {
        int i = 0;
        try {
            while (i < 10000) {
                RunnableDemo temp = new RunnableDemo("Thread-"
                        + String.valueOf(i));
                temp.start();
                i++;
                Thread.sleep(1000);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

class RunnableDemo implements Runnable {
    private Thread t;
    private String threadName;

    InetAddress host = null;
    int port = 9090;

    RunnableDemo(String name) {
        threadName = name;
        System.err.println("Creating " + threadName);

    }

    public void run() {
        System.err.println("Running " + threadName);
        try {
            SocketChannel socketChannel = SocketChannel.open();

            socketChannel.connect(new InetSocketAddress(host, port));

            while (!socketChannel.finishConnect())
                ;

            System.out.println("Thread " + threadName + " Connected");
            ByteBuffer buffer = ByteBuffer.allocate(1024);
            while (true) {
                if (socketChannel.read(buffer) > 0) {
                    buffer.flip();
                    byte[] bytes = new byte[buffer.limit()];
                    buffer.get(bytes);  
                    System.out.println(threadName+ ":" + new String(bytes));
                    buffer.clear();
                }
            }

        } catch (Exception e) {
            System.out.println("Thread " + threadName + " interrupted.");
            e.printStackTrace();
        }
        System.out.println("Thread " + threadName + " exiting.");
    }

    public void start() {
        System.out.println("Starting " + threadName);
        try {
            host = InetAddress.getByName("127.0.0.1");
            if (t == null) {
                t = new Thread(this, threadName);
                t.start();
            }
        } catch (UnknownHostException e) {
            e.printStackTrace();
        }
    }

}

The test application runs but only 75 threads can connect to the server and all thread after 75th shows below exception:

java.net.ConnectException: Connection refused: connect
at sun.nio.ch.Net.connect0(Native Method)
at sun.nio.ch.Net.connect(Unknown Source)
at sun.nio.ch.Net.connect(Unknown Source)
at sun.nio.ch.SocketChannelImpl.connect(Unknown Source)
at net.behboodi.client.RunnableDemo.run(Main.java:48)
at java.lang.Thread.run(Unknown Source)

Is there any limits for number of concurrent connections to the socket? Or is there any limits on using port 127.0.0.1 and local host? The other idea is that maybe a java app or JVM can not create more than 75 thread.

I searched about them all, but do not find any answer that show me what of the above reasons is my main problem and how can I fixed the code so that I can test the app with more than 10000 concurrent thread?

user207421
  • 305,947
  • 44
  • 307
  • 483
Husein Behboudi Rad
  • 5,434
  • 11
  • 57
  • 115
  • It's not Java, neither by number of threads nor by socket connections. You program runs well over 100 client connections on a Linux system. Are you on windows? – laune Dec 25 '14 at 16:25
  • Yes I am on windows. but how can I extend the number of threads in windows or linux. I am tagetting 10000 client threads. – Husein Behboudi Rad Dec 25 '14 at 16:46
  • It's not the number of threads that's causing the problem since you can start the 75th client in its own thread. It looks more like a socket resource limit to me. I'm afraid I can't help you with Windows. – laune Dec 25 '14 at 17:57
  • 1
    What OS version are you actually running it on? – Martin James Dec 25 '14 at 21:21
  • 2
    Get rid of the sleep. The Selector already blocks. Sleeping in network code is just literally a waste of time. NB (1) You don't call `finishConnect()` in blocking mode, (2) you aren't connecting threads to a ServerChannel, you are connecting client sockets to a server socket, (3) your client code doesn't handle end of stream, and (4) this is not an echo server. – user207421 Dec 25 '14 at 21:46
  • @Martin , I am using windows 8 – Husein Behboudi Rad Dec 26 '14 at 08:36
  • @EJP, your comment was right. I removed the finishConnect and now it is working right. If you make it an answer other users can use it better. Thanks. – Husein Behboudi Rad Dec 27 '14 at 11:15

1 Answers1

0

Get rid of the sleep. The Selector already blocks. Sleeping in network code is just literally a waste of time. NB (1) You don't call finishConnect() in blocking mode, (2) you aren't connecting threads to a ServerChannel, you are connecting client sockets to a server socket, (3) your client code doesn't handle end of stream, and (4) this is not an echo server. – EJP

Armali
  • 18,255
  • 14
  • 57
  • 171