Posted on 2008-06-18 01:50
dennis 阅读(2449)
评论(2) 编辑 收藏 所属分类:
java
SocketChannel和ServerSocketChannel,两者的父类是SelectableChannel,它在jdk中的文档有这么段话:
Once registered with a selector, a channel remains registered until it is deregistered.This involves deallocating whatever resources were allocated to the channel by the selector.
A channel cannot be deregistered directly; instead, the key representing its registration must be cancelled. Cancelling a key requests that the channel be deregistered during the selector's next selection operation.
也就是说关闭一个已经注册的SelectableChannel需要两个步骤:
1)取消注册的key,这个可以通过SelectionKey.cancel方法,也可以通过SelectableChannel.close方法,或者中断阻塞在该channel上的IO操作的线程来做到。
2)后续的Selector.selectXXX方法的调用才真正地关闭本地Socket。
因而,如果,如果在取消SelectionKey后没有调用到selector的select方法(因为Client一般在取消key后,
我们都会终止调用select的循环,当然,server关闭一个注册的channel我们是不会终止select循环的),那么本地socket将进入CLOSE-WAIT状态(等待本地Socket关闭)。简单的解决办法是在
SelectableChannel.close方法之后调用Selector.selectNow方法,类似:
Selector sel;
SocketChannel sch;
// …
sch.close();
sel.selectNow();
Nio编程有很多这样细节性的东西需要注意,通常情况下还是利用成熟的框架为妙。