2011-01-16 15 views
1

皆さん、私はうまく拡張し、何千ものクライアントに役立つサーバープログラムを開発しています。問題は、Apache MINAがあまりにも重すぎて、私はそれを使わないことにして、代わりに自分のクライアントリスナーを書いたと感じています。私は実際にはJavaで非同期のソケット操作を行ったことはありませんでした。(C#はそれをはるかに簡単にしましたが、私はソケット読み込みの他にすべてをよく知っていたので、スレッドプールは正しく私にとっては難しいです。 Apache MINAのドキュメントを使って、どのようにしたらよいかを知ることができました。Executors.newFixedThreadPoolを使用した非同期Java NIOのヘルプ

  1. スレッドプールが正しく使用されていますか? Apache MINAのデフォルトのスレッドサイズはCPUコアの数+1ですが、何千ものクライアントを受け入れるためにCore 2 Duo用のスレッドスレッドプールを3つ使用する必要がありますか?
  2. 私は、クライアントから受信したメッセージごとにバッファを2回再割り当てすることを知っています(各メッセージは2パケット、1つのヘッダーは定数4バイト、長さはヘッダーに指定された内容パケットです)。バッファーオーバーランをチェックする固定サイズのバッファーを使用する簡単な方法はありますか?そのため、バッファーは常に同じですが、バッファーは絶えず再割り当てする必要はありませんか?

は、ここで私はリスナーを起動方法は次のとおりです。

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 + ")."); 
     } 
    } 
} 

あなたがいないここ

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

はClientListenerに関連するコードですgetPacketLength、processMessage、decryptのコードを知る必要があるデータ、およびクラスLittleEndianByteArrayReaderがありますが、私はこれらのメソッド/クラスの目的が明らかであることを確信しています。

+0

あなたが例外を飲み込んでいるということです。少なくともログに記録する。 – dogbane

+0

これはコードスニペットです。実際のコードでは、詳細なメッセージとともにjava.util.Loggerを使用してログを記録します。 –

+0

あなたはNIOをまったく使用していませんか?そのためにセレクタが必要です。 –

答えて

0

Nevermind guys。私はApache MINAが実際にNIOを使用していることに気づきました。なぜなら、私は混乱しています。セレクタを使用してリクエストを処理するには、実際にはスレッドが1つだけ必要です。すべてのあなたの答えをありがとう、混乱についてごめんなさい!

+1

この回答はコメントにする必要があります。 – finnw

0

ブロッキングIOシナリオのスレッド数は、クライアント数と各クライアント接続が開かれる時間によって計算する必要があります。 各ユーザーの各接続にはスレッドが必要です。

3つのスレッドだけで、3つのTCP接続を開き、サーバーにデータを送信しないで、接続タイムアウトまでサーバーをブロックできます。

+0

Apache MINAに関するこのサイトを見るまで、まさに私が思ったこと:http:// mina.apache.org/configuring-thread-model。html「I/Oワーカースレッドの数を設定する」セクションの下で、I/Oプロセッサスレッドを除くすべてのワーカースレッドには、一度に1つのスレッドしか実行されません。しかし、I/Oプロセッサスレッドの最大量はCPUコアの数+1であり、混乱しました。おそらく、彼らは私が進めているアプローチとは違った働きをするでしょうか? –

関連する問題