2012-02-17 6 views
1

セレクタの使用に問題があります。NIOセレクタの使い方は?

チャネルを管理するために、サーバー側のセレクタでクライアント/サーバー接続を作成しようとするテストコードを書きました。問題は、セレクタが読み込み元のチャネルを選択し、読み込み操作が処理されたときに、実際にデータが読み込まれないことです。

この質問を投稿した投稿者:another forumまだ回答がありません。

サーバー:

static class Server implements Runnable { 
    Selector sel; 

    @Override 
    public void run() { 
     try { 
      ServerSocketChannel server = ServerSocketChannel.open(); 
      server.socket().bind(new InetSocketAddress(5555)); 
      server.configureBlocking(false); 
      sel = Selector.open(); 
      server.register(sel, SelectionKey.OP_ACCEPT); 

      boolean running = true; 
      while(running) { 
       int count = sel.select(); 
       if(sel.isOpen() && count > 0) { 
        Set<SelectionKey> keyset = sel.selectedKeys(); 
        synchronized(keyset) { 
         Iterator<SelectionKey> i = keyset.iterator(); 
         while(i.hasNext()) { 
          SelectionKey key = i.next(); 
          i.remove(); 
          processKey(key); 
         } 
        } 
       } else if(!sel.isOpen()) 
        running = false; 
      } 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 

    private void processKey(SelectionKey key) { 

     if(key.isValid() && key.isAcceptable()) { 
      try { 
       SocketChannel chan = ((ServerSocketChannel)key.channel()).accept(); 
       chan.configureBlocking(false); 
       chan.register(sel, SelectionKey.OP_READ); 
      } catch (IOException e) { 
       e.printStackTrace(); 
      } 
     } 

     if(key.isValid() && key.isReadable()) { 
      System.out.println("Read starting..."); 
      SocketChannel chan = (SocketChannel) key.channel(); 
      ByteBuffer buff = ByteBuffer.allocate(1024); 
      try { 
       while((chan.read(buff))>=0) { 
        buff.flip(); 
        System.out.println("read some"); 
        buff.clear(); 
       } 
       chan.close(); 
       System.out.println("Read complete"); 
      } catch (IOException e) { 
       e.printStackTrace(); 
      } 
     } 
    } 
} 

クライアント:ここ

static class Client implements Runnable { 
    @Override 
    public void run() { 
     try { 
      SocketChannel chan = SocketChannel.open(); 
      chan.connect(new InetSocketAddress("localhost", 5555)); 
      while(!chan.finishConnect()); 
      ByteBuffer buff = ByteBuffer.allocate(1024); 
      for(int i=0;i<1000;i++) { 
       buff.flip(); 
       chan.write(buff); 
       buff.compact(); 
      } 
      chan.close(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 
} 

は、完全なソースコードのpastebinです。どんな洞察も高く評価されます。

+1

あなたはデータを書いているようには見えません。 (サーバーとクライアントを起動する間に競争もあります) –

+0

空のバイトを書き込もうとしています。 ITはまだデータを正しく書き込む必要がありますか?クライアントコードを開始する前にThread.sleep()を使用しようとしましたが、それは役に立ちませんでした。 – bgroenks

+1

しかし、決してバッファーを埋めることはありません。 'limit(int)'の呼び出しはそれを行うべきだと私は思います。 (免責事項:私は実際に何十年もの間、賢明なNIOプログラミングを行っていない) –

答えて

1

問題はあなたのクライアントにあります。これは、Tomによって暗示されるように、何も書きません。 ここに何が起こるかです:

ByteBuffer buff = ByteBuffer.alloacate(1024); // ==> position=0, limit=1024 

その後:

buff.flip(); // ==> position=0, limit=0 

このフリップ()のためにjavdaocに指定されているようです:制限を現在の位置に設定されている」とし、位置がゼロに設定されます" ですから、少なくともにあなたが例えば、バッファにいくつかのデータを置くことをシミュレートする必要があります:あなたは可能性がありますので、一度にすべての1024のバイトを書き込みます

for(int i=0;i<1000;i++) { 
    buff.position(1024); // put 1024 bytes of data in the buffer 
    buff.flip(); 
    ... 
} 

はさらに、(をchan.write保証はありません)ループでそれをしたい:

for (int i=0;i<1000;i++) { 
    buf.position(1024); 
    buff.flip(); 
    while (buff.hasRemaining()) { 
    chan.write(buff); 
    buff.compact(); 
    } 
}