NIO筆記 二 之Channel

2021-09-20 15:21:50 字數 4575 閱讀 4934

socketchannel

serversocketchannel

jdk8

channel概念

如果乙個channel實現了interrupted介面,那麼當他被阻塞,並且發生中斷的時候,那麼該channel將會被中斷,執行緒會丟擲乙個closedbyinterruptexception異常,如果乙個執行緒的狀態是中斷,他試圖訪問乙個channel,那麼channel將立即被關閉。

channel可以以阻塞(blocking)或者非阻塞(nonblocking)模式執行,非阻塞模式的channel永遠不會讓呼叫的執行緒休眠,請求的操作要麼立即完成,要麼返回乙個結果表明未進行任何操作,不是所有通道都可以使用非阻塞模式

channel分為兩類:filechannelsocket通道,包括socketchannelserversocketchanneldatagramchannel(udp)socket通道可以直接通過工廠方法建立,但是乙個filechannel只能通過乙個開啟的randomaccessfilefileinputstreamfileoutputstream物件上呼叫getchannel()方法來獲取

//socket通道

socketchannel sc = socketchannel.

open()

;serversocketchannel ssc = serversocketchannel.

open()

;datagramchannel dc = datagramchannel.

open()

;//檔案通道

randomaccessfile raf =

newrandomaccessfile

("somefile"

,"r");

filechannel fc = raf.

getchannel()

;

正常情況下,乙個寫操作會在全部資料寫入後返回,但是在某些特殊的通道(socket的非阻塞模式)中,因為緩衝區滿,資料有可能部分寫入或者沒有寫入。所以從這裡來說,通道的寫不是執行緒安全的,因為有可能想寫入10b的資料,但是只寫入了5b,那下次執行緒排程的時候,就有可能寫亂資料

因為讀/寫本身就是阻塞式的,同時只有乙個執行緒可以操作,但是讀/寫都不是執行緒安全的,所以一般乙個通道也都只有乙個執行緒讀,乙個執行緒寫,或者乙個執行緒把讀/寫都做了

readwrite方法並不一定會操作和bytebuffer容量相等的資料,這兩個方法會返回這期間操作的位元組數,因此在應用端需要判斷,如果僅僅進行部分傳輸,需要重新進行傳輸,使用hasreminding()方法判斷是否還有資料

channel不能被重複利用,乙個開啟的channel即代表與乙個特定的i/o服務的特定連線,並封裝該連線的狀態。當channel關閉時,那個連線會丟失,然後channel將不再連線任何東西。

channel呼叫通道的close()方法時,可能會導致在channel關閉底層i/o服務的過程中線程暫時阻塞(即使channel處於非阻塞模式)。通道關閉的阻塞行為(如果有的話)是高度取決於作業系統或檔案系統的(socket通道關閉會花費較長時間,具體時耗取決於作業系統的網路實現。在輸出內容被提取時,一些網路協議堆疊可能會阻塞通道的關閉,在通道關閉之後,正在進行的read或者write操作會收到乙個asynchronouscloseexception)。在乙個通道上多次呼叫close()方法是沒有壞處的,但是如果第乙個執行緒在close()方法中阻塞,那麼在它完成關閉通道之前,任何其他呼叫close()方法都會阻塞,後續在已關閉的channel上調close()方法不會產生任何操作,只會立即返回

關閉乙個已經註冊的selectablechannel需要兩個步驟

socketsocketchannel類封裝點對點、有序的網路連線。每個socketchannel物件建立時都是和乙個對等的socket物件關聯的。

連線過程

op_connect事件,表示連線通道連線就緒或者發生了錯誤,會被加到ready中.即這個事件發生時不能簡單的認為連線成功了,要使用finishconnect()判斷

//新建立的channel都是未連線的

socketchannel channel = socketchannel.

open()

;//設定該socketchannel以非阻塞方式工作

channel.

configureblocking

(false);

/**呼叫connect進行連線

* 在阻塞模式下,執行緒在連線建立好或超時之前會保持阻塞

* 非阻塞模式下,沒有超時引數,會發起連線請求,並且立即返回,如果是true,則說明連線已經建立(本地環迴連線);如果不能連線,立即返回false,並且非同步的繼續嘗試連線,這時候isconnectpending()會返回true(連線等待狀態),

**/channel.

connect

(addr)

;while

(!sc.

finishconnect()

)//註冊連線事件,連線就會就緒

channel.

register

(selector, selectionkey.op_connect)

;//連線成功finishconnect()返回true

if(key.

isvalid()

&& key.

isconnectable()

)else

}

serversocketchannel是乙個面向流的監聽socketselectablechannelserversocketchannel是乙個抽象類,即不能直接例項化,可以通過自身的靜態方法open()建立例項,open()方法作用是開啟服務端socket通道,新建立的服務端socket通道最初是未繫結的,在接收連線之前,必須通過它的bind()方法將其繫結到具體的位址和埠

靜態open方法

public

static serversocketchannel open()

throws ioexception

accept()方法的作用是接收通道socket的連線。如果serversocketchannel是非阻塞模式,那麼accept()方法將直接返回null。如果是阻塞模式,在新的連線可用或者發生i/o錯誤之前會無限地阻塞。
@test

public

void

testblockserver()

throws exception

啟動輸出:

true

start:

1551490993132

使用telnet 127.0

.0.1

8888 後輸出:

end:

1551490999952

@test

public

void

testnotblockserver()

throws exception

else

serversocketchannel.

close()

;}

輸出:

true

false

begin:

1551452354670

end:

1551452354673

null

socket option

@test

public

void

testchanneloption()

throws exception

NIO邊看邊記 之 channel(二)

通道channel就像流。通道中的資料總是先讀到到buffer中 對於buffer來說是乙個寫操作 再從buffer中寫到另乙個通道總 相對於buffer來說是乙個讀操作 channel主要分為兩類 檔案channel和網路channel,細分為4種。filechanel 從普通檔案中讀寫資料 da...

java之NIO通道Channel的使用

1.利用通道完成檔案的複製 非直接緩衝區 test public void test1 catch filenotfoundexception e catch ioexception e finally catch ioexception e if inchannel null catch ioex...

NIO學習筆記二 Channels

這一章主要是對nio的channels進行說明。1 channels與io stream的區別。主要區別如下 2 channel 主要實現。主要實現類如下 3 channel 的簡單例子。以下是使用channel讀取檔案內容的簡單例子 public static void readfile stri...