2012-03-21 123 views
1

我向所有用户发送消息给地图。interestOps抛出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,数据是一个带有mes的byte []数组圣人我读了使用channel.read(缓冲区);

更多信息:

在构造函数中我做出选择

_selector = Selector.open(); 

我运行服务器

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); 
     } 
    } 
} 

我接受连接

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); 
} 

在读功能whene我读MES圣人我有这每个循环。但是,当一个用户,我移动与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 var,现在我保留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) – 2012-03-21 17:57:15

+0

是的,但我不明白。 – user1248092 2012-03-21 18:41:30

+0

关闭通道取消密钥。你自己不需要这样做。 – EJP 2012-03-21 20:53:55

回答

3

听起来像它可能是完全一样记载:

抛出
IllegalArgumentException - 如果集合丝毫不对应于该键的通道支持的操作,即如果set & ~(channel().validOps()) != 0

它很难知道为什么这样的情况下,不知道更多关于有问题的频道虽然...

2

我会说你的用户映射包含ServerSocketChannel以及接受的SocketChannels。您不能在ServerSocketChannel上设置OP_WRITE。

我不知道'残障'是什么意思。

相关问题