2011-01-16 3 views
1

Привет, ребята, я работаю над серверной программой, предназначенной для масштабирования и обслуживания потенциально тысяч клиентов. Дело в том, что я чувствую, что Apache MINA слишком тяжелый, поэтому я решил не использовать его и вместо этого написал своего собственного слушателя. Я никогда не выполнял операции асинхронного сокета в Java (C# сделал это намного проще, но я действительно предпочел написать этот проект на Java, так как я больше знаком с ним во всем, кроме чтения сокетов), поэтому, пытаясь понять, как использовать поток пула правильно для меня. Я использовал документацию Apache MINA, чтобы понять, как все должно быть сделано. У меня было два вопроса:Помощь, необходимая для асинхронного Java NIO с использованием Executors.newFixedThreadPool

  1. Правильно ли используется пул потоков? Размер потока по умолчанию Apache MINA - это число ядер процессора + 1, но должен ли я использовать пул потоков 3 потоков для моего Core 2 Duo, чтобы принимать тысячи клиентов?
  2. Я знаю, что перераспределение буфера дважды за каждое сообщение, полученное от клиента (каждое сообщение представляет собой два пакета, один заголовок - постоянный 4 байта и пакет контента, длина которого указана в заголовке). Есть ли простой способ использовать буфер фиксированного размера, который проверяет переполнение буфера, так что поведение остается тем же, но буфер не нужно постоянно перераспределять?

Вот как я начинаю слушателя:

ClientListener cl = new ClientListener(1234); 
cl.init(); 
new Thread(cl).start(); 

Вот соответствующий код ClientListener:

private static final int THREADS = Runtime.getRuntime().availableProcessors() + 1; 
private ServerSocket socket; 
private ExecutorService threadPool; 
private int port; 

public ClientListener(int port) { 
    this.port = port; 
    threadPool = Executors.newFixedThreadPool(THREADS); 
} 

public void init() { 
    try { 
     socket = new ServerSocket(port); 
    } catch (IOException ex) { 
    } 
} 

public void run() { 
    while (true) { 
     try { 
      ClientSession s = new ClientSession(socket.accept()); 
      threadPool.execute(s); 
     } catch (IOException ex) { 
     } 
    } 
} 

ClientSession соответствующий код:

private Socket socket; 
private byte[] buffer; 
private boolean isHeader; 

public ClientSession(Socket socket) { 
    this.socket = socket; 
    this.buffer = new byte[4]; 
    this.isHeader = true; 
} 

public void run() { 
    InputStream in; 
    try { 
     in = socket.getInputStream(); 
     out = socket.getOutputStream(); 
    } catch (IOException ex) { 
     return; 
    } 
    while (!socket.isClosed()) { 
     try { 
      int read = in.read(buffer); 
      if (read == -1) 
       break; 
      receive(read); 
     } catch (IOException ex) { 
      break; 
     } 
    } 
} 

private void receive(int readBytes) { 
    if (isHeader) { 
     if (readBytes >= 4) { 
      buffer = new byte[getPacketLength(buffer)]; 
      isHeader = false; 
     } else { 
      System.out.println("Not enough data received from client " + socket.getInetAddress() + " to decode packet."); 
     } 
    } else { 
     if (readBytes >= buffer.length) { 
      processMessage(new LittleEndianByteArrayReader(decryptData(buffer)), this); 
      buffer = new byte[4]; 
      isHeader = true; 
     } else { 
      System.out.println("Not enough data received from client " + socket.getInetAddress() + " to decode packet (needed " + buffer.length + ", received " + readBytes + ")."); 
     } 
    } 
} 

Вы не нужно знать код для getPacketLength, processMessage, decrypt Data и класс LittleEndianByteArrayReader, но я уверен, что цели этих методов/классов очевидны.

+0

что вы торчит, что вы просто глотаете исключения. По крайней мере, зарегистрируйте их. – dogbane

+0

Это всего лишь фрагменты кода. В моем фактическом коде я записываю их с помощью java.util.Logger с подробными сообщениями. –

+0

Вы вообще не используете NIO? Для этого вам понадобится Селектор. –

ответ

0

Сторонники Nevermind. Я понял, что Apache MINA фактически использует NIO, поэтому я запутался. Для обработки запросов с использованием селекторов действительно нужен только один поток. Спасибо за все ваши ответы и извините за путаницу!

+1

Этот ответ должен быть комментарием. – finnw

0

Количество потоков в блокирующем сценарии ввода-вывода должно быть рассчитано по количеству клиентов и времени открытия каждого клиентского соединения. Каждое подключение каждого пользователя требуется на потоке.

С помощью всего трех потоков пользователь может просто заблокировать ваш сервер до таймаута соединения, просто открыв три подключения TCP и не отправляя на сервер никаких данных.

+0

Точно, что я думал, пока не увидел этот сайт об Apache MINA: http: // mina.apache.org/configuring-thread-model.html В разделе «Настроить количество рабочих потоков ввода-вывода» каждый рабочий поток, кроме потока процессора ввода-вывода, имеет только один поток, выполняемый одновременно. Тем не менее, максимальное количество потоков процессора ввода-вывода - это количество ядер процессора + 1, что меня смутило. Возможно, они работают иначе, чем подход, который я собираюсь сделать? –

Смежные вопросы