NIO的SelectableChannel關(guān)閉的一個(gè)問題
Posted on 2008-06-18 01:50 dennis 閱讀(2458) 評(píng)論(2) 編輯 收藏 所屬分類: java 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.
也就是說關(guān)閉一個(gè)已經(jīng)注冊(cè)的SelectableChannel需要兩個(gè)步驟:
1)取消注冊(cè)的key,這個(gè)可以通過SelectionKey.cancel方法,也可以通過SelectableChannel.close方法,或者中斷阻塞在該channel上的IO操作的線程來做到。
2)后續(xù)的Selector.selectXXX方法的調(diào)用才真正地關(guān)閉本地Socket。
因而,如果,如果在取消SelectionKey后沒有調(diào)用到selector的select方法(因?yàn)镃lient一般在取消key后, 我們都會(huì)終止調(diào)用select的循環(huán),當(dāng)然,server關(guān)閉一個(gè)注冊(cè)的channel我們是不會(huì)終止select循環(huán)的),那么本地socket將進(jìn)入CLOSE-WAIT狀態(tài)(等待本地Socket關(guān)閉)。簡(jiǎn)單的解決辦法是在 SelectableChannel.close方法之后調(diào)用Selector.selectNow方法,類似:
Selector sel;
SocketChannel sch;
// …
sch.close();
sel.selectNow();
Nio編程有很多這樣細(xì)節(jié)性的東西需要注意,通常情況下還是利用成熟的框架為妙。