Monday, April 30, 2012

interestOps throws IllegalArgumentException

I wand send a message to all User in map.



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

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


but whene I run this function I see




Exception in thread "main" java.lang.IllegalArgumentException




this line make error



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


getKey() returns SelectionKey, getMessages returns ArrayList, data is a byte[] array with message I read using channel.read(buffer);



MORE INFO:



In a constructor I make Selector



_selector = Selector.open();


I run server



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


I accept connection



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


In read function whene I read message I have this for each loop. But whene is one user and I move line with interestOps just behind loop it works.



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


Full read and write function:



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:



I can't answer my own question now, so put it here:



SelectionKey in accept method is a little handicapped. I tried to replace it with new key in read method and it works. So in User class I don't keep SelectionKey var any more, now I keep SocketChannel. SocketChannel have keyFor method, so whene I have selector I can get key



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




No comments:

Post a Comment