2011-01-26 10 views
3

私は小さなJavaサーバータイプのアプリケーションに複数の接続を許可しようとしています。それは正常に動作しますが、1つの接続が開き、次にハングすると、後続のすべての接続がハングします。私は、スレッドが属するのトラックを維持しながら、独自のスレッドでは、約20の同時のものまで、それぞれの接続を処理については移動するかどうかはわかりませんと、私がこれまで持っているコードがあるなどどのクライアント:このノンブロッキングサーバーをマルチスレッドにするにはどうすればよいですか?

private void init() { 
    try { 
     // Create the server socket channel 
     ServerSocketChannel server = ServerSocketChannel.open(); 
     // nonblocking I/O 
     server.configureBlocking(false); 
     // host-port 
     server.socket().bind(new InetSocketAddress(host, port)); 
     System.out.println("Server connected on " + host + ":" + port); 
     // Create the selector 
     Selector selector = Selector.open(); 
     // Recording server to selector (type OP_ACCEPT) 
     server.register(selector, SelectionKey.OP_ACCEPT); 
     // Infinite server loop 
     for (;;) { 
      // Waiting for events 
      selector.select(); 
      // Get keys 
      Set keys = selector.selectedKeys(); 
      Iterator i = keys.iterator(); 
      // For each keys... 
      while (i.hasNext()) { 
       SelectionKey key = (SelectionKey) i.next(); 
       // Remove the current key 
       i.remove(); 
       // if isAccetable = true 
       // then a client required a connection 
       if (key.isAcceptable()) { 
        // get client socket channel 
        SocketChannel client = server.accept(); 
        // Non Blocking I/O 
        client.configureBlocking(false); 
        // recording to the selector (reading) 
        client.register(selector, SelectionKey.OP_READ); 
        continue; 
       } 
       // then the server is ready to read 
       if (key.isReadable()) { 
        SocketChannel client = (SocketChannel) key.channel(); 
        // Read byte coming from the client 
        int BUFFER_SIZE = 32; 
        ByteBuffer buffer = ByteBuffer.allocate(BUFFER_SIZE); 
        try { 
         client.read(buffer); 
        } catch (Exception e) { 
         // client is no longer active 
         e.printStackTrace(); 
         continue; 
        } 
        buffer.flip(); 
        Charset charset = Charset.forName("ISO-8859-1"); 
        CharsetDecoder decoder = charset.newDecoder(); 
        CharBuffer charBuffer = decoder.decode(buffer); 
        Handler dataHandler = new Handler(); 
        client.write(ByteBuffer.wrap(dataHandler.processInput(charBuffer.toString()).getBytes())); 
        client.socket().close(); 
        continue; 
       } 
      } 
     } 
    } catch (IOException ex) { 
     Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex); 
    } 
} 
+0

ルック。より効率的にすることもできます。 –

答えて

1

My Solution i NettyとExecutorは、ThreadPoolを作成します。 ハンドラdo Nettyのパイプラインを追加するだけで、Executor witch ChannelBufferをパラメータとして呼び出すことができます。 すべてのクライアント要求が別のスレッドによって処理されます。私はちょうどそれがはるかに簡単になり、10Kの接続にスケールアップすることができ、NIOをブロック使用して、クライアントごとに1つのスレッドを持っているでしょうexamples

+0

nettyを見ていただきありがとうございます: ) – zcourts

+0

最終的にネットで行きました。かなりうまく収まっているように見えますが、APIに入るための学習曲線はどれほど険しいのでしょうか? – zcourts

+0

あなたは基本的なサーバーを1分で作ることができますが、それがどのように機能するかを知るためには、ネットの情報源に深く関心があります。それは私にとって良いレッスンでした:私はハンドラのビルドについて読むことをお勧めします - デコーダ/エンコーダ。私はサーバーをいくつかのクラスをパイプラインに追加するだけです。 HTTP、SSL、あなたが欲しいものは何でも: –

3

ソケットサーバーを作成する必要があるときはいつでも、低レベルのJVMクラスを使用することは避けてください。なぜなら、すべての根本的な詳細を処理する必要があるからです。

代わりにApache Minaを使用します。これは、高性能ノンブロッキング・マルチスレッド・ソケット・サーバーを作成するためのJavaライブラリーです。

Minaを使用することの利点は、コードをモジュール化し、メンテナンス性を向上させるclean architecture(IoFilters、プロトコルデコーダ)を強制することです。

+0

非常に有望な音...私は見て、戻ってきます。 私は実際にApacheプロジェクトの詳細を覚えておく必要があります。 – zcourts

2

学習の練習として実際にNIOサーバーを作成しない場合は、Nettyを使用することをお勧めします。 Peterが述べたMinaのように、それはまた高性能サーバを書くためのライブラリです。

私は最近、自分のNIOコードをこのライブラリに使用することになりました。私のコードをもっときれいにしました。

+0

あまりにも多くのオーバーヘッドがなくても簡単に人生を作れるようなものはすべてありますので、私はチェックアウトのネタも手に入れます – zcourts

関連する問題