Reputation: 45
I use SocketChannel
to receive TCP stream from server on client side. For example:
Selector selector=Selector.open();
SocketChannel mychannel=SocketChannel.open(new InetSocketAddress(ip,port));
channel.configureBlocking(false);
SelectionKey channelkey=channel.register(selector,SelectionKey.OP_READ);
Then, I can use the selector.select()
method to handle reading problem.
while(true){
if(selector.select()!=0){
Iterator<SelectionKey> it=selector.selectedKeys().iterator();
while(it.hasNext()){
SelectionKey key=it.next();
it.remove();
if(key.isReadable()){
if(key.equals(channelkey)){
//concrete handle
...
}
}
}
}
}
With concrete handle,considering I'd like to use InputStream(I wanna read stream line) to receive tcp stream from server side,there are two methods.One is using channel.socket()
, another is to use Channels. Here I use channel.socket()
, for example:
SocketChannel channel = (SocketChannel) key.channel();
key.cancel();
channel.configureBlocking(true);
InputStream ins = Channels.newInputStream(channel);
InputStreamReader is = new InputStreamReader(ins,"utf-8");
BufferedReader in = new BufferedReader(is);
String res = in.readLine();
while (!res.equals("")) {
System.out.println(res);
res = in.readLine();
}
......①
OK, now I finish reading tcp stream for one time.In order to continue to using selector, I should set channel blocking mode to false.
channel.configureBlocking(false);
The question is,the key that combines channel and selector has been canceled.I want to register mychannel again.What should I do? It seems that if I use mychannel.register(selector, SelectionKey.OP_READ)
again on ①, it throws Exception
.
My run() method code is as follows:
try {
if (selector.select(getTimeout()) != 0) {
Iterator<SelectionKey> it = selector.selectedKeys().iterator();
while (it.hasNext()) {
SelectionKey key = it.next();
if (key.isReadable()) {
SocketChannel channel = (SocketChannel) key.channel();
key.cancel();
channel.configureBlocking(true);
InputStream ins = Channels.newInputStream(channel);
InputStreamReader is = new InputStreamReader(ins,"utf-8");
BufferedReader in = new BufferedReader(is);
String res = in.readLine();
while (!res.equals("")) {
System.out.println("========" + res);
res = in.readLine();
}
channel.configureBlocking(false);
System.out.println(key.isValid());
proxykey=channel.register(selector, SelectionKey.OP_READ);
}
it.remove();
}
}
} catch (IOException ex) {
ex.printStackTrace();
}
The Exception it throws is:
Exception in thread "Thread-0" java.nio.channels.CancelledKeyException
at sun.nio.ch.SelectionKeyImpl.ensureValid(Unknown Source)
at sun.nio.ch.SelectionKeyImpl.interestOps(Unknown Source)
at java.nio.channels.spi.AbstractSelectableChannel.register(Unknown Source)
at java.nio.channels.SelectableChannel.register(Unknown Source)
at AgentThread.run(AgentThread.java:185)
Upvotes: 1
Views: 4668
Reputation: 311008
SelectionKey.cancel()
doesn't take full effect until the next select()
, for various arcane reasons. You could try calling selectNow()
after the cancel, or maybe better just before the re-registration.
Upvotes: 1