2012-03-21 7 views
1

私はマップ内のすべてのユーザーにメッセージを送信します。interestOps throw IllegalArgumentException

for (User u : _userMap.values()) { 
     u.getMessages().add(data); 

     u.getKey().interestOps(SelectionKey.OP_WRITE); 
    } 

が、私はこの機能を実行するwhene私はこのラインスレッド "メイン" java.lang.IllegalArgumentExceptionが

例外を参照してくださいエラー

u.getKey().interestOps(SelectionKey.OP_WRITE); 

のgetKeyを作ります()はSelectionKeyを返し、getMessagesはArrayListを返し、dataはmesを持つbyte []配列です私はchannel.read(buffer)を使って読みました。

MORE INFO:私は、サーバー

public void startServer() throws IOException { 
    while (true) { 
     _selector.select(); 

     Iterator<SelectionKey> keys = _selector.selectedKeys().iterator(); 

     while (keys.hasNext()) { 
      SelectionKey key = keys.next(); 
      keys.remove(); 

      if (!key.isValid()) 
       continue; 
      if (key.isAcceptable()) 
       accept(key); 
      else if (key.isReadable()) 
       read(key); 
      else if (key.isWritable()) 
       write(key); 
     } 
    } 
} 

を実行して、私はセレクタ

_selector = Selector.open(); 

作るコンストラクタで

私が読んwhene私は、読み取り機能で接続

private void accept(SelectionKey key) throws IOException { 
    ServerSocketChannel serverChannel = (ServerSocketChannel) key.channel(); 
    SocketChannel channel = serverChannel.accept(); 
    channel.configureBlocking(false); 

    User u = new User(key); 
    _userMap.put(channel, u); 

    channel.register(_selector, SelectionKey.OP_READ); 
} 

を受け入れますmes私はこれをループ毎に持っています。しかし、私は1人のユーザーであり、私はinterestOpsをループの後ろに置くだけでそれを動かす。

 //u.getKey().interestOps(SelectionKey.OP_WRITE); 
    } 
    key.interestOps(SelectionKey.OP_WRITE); 

完全な読み取りおよび書き込み機能:

private void read(SelectionKey key) throws IOException { 
    SocketChannel channel = (SocketChannel) key.channel(); 

    ByteBuffer buffer = ByteBuffer.allocate(2048); 
    int read = -1; 

    try { 
     read = channel.read(buffer); 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 

    if (read == -1) { 
     _userMap.remove(channel); 

     channel.close(); 
     key.cancel(); 

     return; 
    } 

    byte[] data = new byte[read]; 

    System.arraycopy(buffer.array(), 0, data, 0, read); 

    /// WYSyŁA DO WSZYSTKICH. usunąć 

    for (User u : _userMap.values()) { 
     u.getMessages().add(data); 

     u.getKey().interestOps(SelectionKey.OP_WRITE); 
    } 
    //key.interestOps(SelectionKey.OP_WRITE); 

    /////// 
} 

private void write(SelectionKey key) throws IOException { 
    SocketChannel channel = (SocketChannel) key.channel(); 

    ArrayList<byte[]> msg = _userMap.get(channel).getMessages(); 
    Iterator<byte[]> i = msg.iterator(); 

    while (i.hasNext()) { 
     byte[] item = i.next(); 
     i.remove(); 

     channel.write(ByteBuffer.wrap(item)); 
    } 

    key.interestOps(SelectionKey.OP_READ); 
} 

SOLUTION:

私は今、自分の質問に答えるので、ここでそれを置くことはできません。

とSelectionKeyの中方法がある受け入れます少し身障者。私はそれをreadメソッドで新しいキーに置き換えようとしました。だからUserクラスでは、SelectionKey変数をこれ以上保持しないので、今はSocketChannelを保持します。 SocketChannelはkeyFor方法を持っているので、私はセレクタを持ってwheneそれはおそらく正確に文書化されているようだように私は

 u.getChannel().keyFor(_selector).interestOps(SelectionKey.OP_WRITE); 
+1

javadoc:http:// docsを読んだことがありますか?oracle.com/javase/6/docs/api/java/nio/channels/SelectionKey.html#interestOps(int) –

+0

はい、それはわかりません。 – user1248092

+0

チャンネルを閉じると、キーがキャンセルされます。あなたはそれを自分で行う必要はありません。 – EJP

答えて

3

は、サウンドのキーを取得することができます


IllegalArgumentException
をスローします - セット内のビットがない場合このキーのチャネルでサポートされている操作、すなわち、set & ~(channel().validOps()) != 0

なぜだと思いますか?

2

あなたのユーザーマップには、ServerSocketChannelとAccepted SocketChannelsが含まれていると言います。 ServerSocketChannelにOP_WRITEを設定することはできません。

「身体障害者」とは何を意味するのか分かりません。

関連する問題