2014-12-25 3 views
1

я разработал сокет канала сервера с использованием кода ниже:Соединение отклонено после подключения 75 клиентов к серверу

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

}

Как вы можете видеть, что я запустить его на localhost порту 9090. Чтобы проверить код для тяжелых соединений, я разработал тестовое приложение, которое каждую секунду запускает новый поток и подключается к серверу. Это код моего тестового приложения:

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

} 

Трассы тест приложений, но только 75 потоков могут подключаться к серверу и все нити после 75-го показывает ниже исключения:

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) 

Есть ли какие-либо ограничения для количество параллельных соединений с сокетом? Или существуют ли ограничения на использование порта 127.0.0.1 и локального хоста? Другая идея состоит в том, что, возможно, приложение java или JVM не может создать более 75 потоков.

Я искал их всех, но не нашел ответа, который показывает мне, что из перечисленного выше является главной проблемой и как я могу исправить код, чтобы проверить приложение с более чем 10000 параллельными потоками?

+0

Это не Ява, ни количество нитей, ни разъемы. В вашей программе Linux работает более 100 клиентских подключений. Вы на окнах? – laune

+0

Да, я на окнах. но как увеличить количество потоков в Windows или Linux. Я использую tagtoning 10000 клиентских потоков. –

+0

Это не количество потоков, которые вызывают проблему, так как вы можете запустить 75-й клиент в своем потоке. Это больше похоже на ограничение ресурса сокета. Боюсь, я не могу помочь вам с Windows. – laune

ответ

0

Избавиться от сна. Селектор уже заблокирован. Сон в сетевом коде просто буквально пустая трата времени. NB (1) Вы надеваете ' t звоните finishConnect() в режиме блокировки, (2) вы aren ' t соединяете потоки с ServerChannel, вы подключаете клиентские сокеты к серверному сокету, (3) код вашего клиента doesn ' t обрабатывает конец потока , и (4) это не эхо-сервер. –   EJP