I wrote a Java NIO Echo Server and want to maximize the number of connections to the server.
The problem is that when I try to connect more than 10k clients the clients get their connections refused:
error Connection Refused : no further information available.
The client program that I use generates a batch of 50 clients per 5 seconds and each client sends data to the server every 5 seconds.
I have added a backlog queue parameter to the server and want to review he server code and find any flaws which may impact scaling.
Server
public class Server implements Runnable {
public final static String ADDRESS = "192.168.1.3";
public final static int PORT = 8511;
public final static long TIMEOUT = 10000;
public int clients;
ByteBuffer readBuffer = ByteBuffer.allocate(1024);
private ServerSocketChannel serverChannel;
private Selector selector;
private Map<SocketChannel,byte[]> dataTracking = new HashMap<SocketChannel, byte[]>();
public Server(){
init();
}
private void init(){
System.out.println("initializing server");
if (selector != null) return;
if (serverChannel != null) return;
try {
selector = Selector.open();
serverChannel = ServerSocketChannel.open();
serverChannel.configureBlocking(false);
serverChannel.socket().bind(new InetSocketAddress(ADDRESS, PORT),5000);
serverChannel.register(selector, SelectionKey.OP_ACCEPT);
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void run() {
System.out.println("Now accepting connections...");
try{
while (!Thread.currentThread().isInterrupted()){
int ready = selector.select();
if(ready==0)
continue;
Iterator<SelectionKey> keys = selector.selectedKeys().iterator();
while (keys.hasNext()){
SelectionKey key = keys.next();
keys.remove();
if (!key.isValid()){
continue;
}
if (key.isAcceptable()){
System.out.println("Accepting connection");
accept(key);
}
if (key.isWritable()){
System.out.println("Writing...");
write(key);
}
if (key.isReadable()){
System.out.println("Reading connection");
read(key);
}
}
}
} catch (IOException e){
e.printStackTrace();
} finally{
closeConnection();
}
}
private void write(SelectionKey key) throws IOException{
SocketChannel channel = (SocketChannel) key.channel();
byte[] data = dataTracking.get(channel);
dataTracking.remove(channel);
int count = channel.write(ByteBuffer.wrap(data));
if(count == 0)
{
key.interestOps(SelectionKey.OP_WRITE);
return;
}
else if(count > 0)
{
key.interestOps(0);
key.interestOps(SelectionKey.OP_READ);
}
}
private void closeConnection(){
System.out.println("Closing server down");
if (selector != null){
try {
selector.close();
serverChannel.socket().close();
serverChannel.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
private void accept(SelectionKey key) throws IOException
{
ServerSocketChannel serverSocketChannel = (ServerSocketChannel) key.channel();
SocketChannel socketChannel = serverSocketChannel.accept();
if(socketChannel == null)
{
throw new IOException();
}
socketChannel.configureBlocking(false);
clients++;
//socketChannel.register(selector, SelectionKey.OP_WRITE|SelectionKey.OP_READ);
SelectionKey skey = socketChannel.register(selector, SelectionKey.OP_READ);
byte[] hello = new String("Hello from server").getBytes();
dataTracking.put(socketChannel, hello);
try
{
write(skey);
}
catch(IOException e)
{
System.out.println("Problem in initial hello from Server "+e);
}
}
private void read(SelectionKey key) throws IOException
{
SocketChannel channel = (SocketChannel) key.channel();
readBuffer.clear();
int length;
try {
length = channel.read(readBuffer);
} catch (IOException e) {
System.out.println("Reading problem, closing connection");
System.out.println("No of clients :"+clients);
key.cancel();
channel.close();
return;
}
if (length == -1){
System.out.println("Nothing was there to be read, closing connection");
channel.close();
key.cancel();
return;
}
readBuffer.flip();
byte[] data = new byte[1000];
readBuffer.get(data, 0, length);
String fromclient = new String(data,0,length,"UTF-8");
System.out.println("Received: "+fromclient);
String dat = fromclient+channel.getRemoteAddress();
data= dat.getBytes();
echo(key,data);
}
private void echo(SelectionKey key, byte[] data) throws IOException
{
SocketChannel socketChannel = (SocketChannel) key.channel();
dataTracking.put(socketChannel, data);
//key.interestOps(SelectionKey.OP_WRITE);
try
{
write(key);
}
catch(IOException e)
{
System.out.println("Problem in echo "+e);
e.printStackTrace();
}
}
public static void main(String [] args)
{
Thread serv = new Thread(new Server());
serv.start();
}
}