Posted on 2008-06-18 01:50
dennis 閱讀(2453)
評論(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編程有很多這樣細節性的東西需要注意,通常情況下還是利用成熟的框架為妙。