2 1 NIO網路通訊

2021-09-27 03:13:54 字數 4157 閱讀 3921

selector的應用

② 非阻塞nio的demo (基於serversocketchannel)

③ 非阻塞nio的demo (基於datagramchannel)

前文【1.1】nio 和 bio 對比分析,引出 nio 介紹了他們的區別,該篇介紹

如何使用nio進行網路通訊.

nio中,執行緒通常將非阻塞 io 的空閒時間用於在其他管道上執行 io 操作,所以單獨的執行緒可以管理多個輸入和輸出通道。

public

class

blockingnio

//因為此時伺服器不知道客戶端是否已經傳送完畢,故服務端一直在處於 read(),造成阻塞

schannel.

shutdownoutput()

;//4. 接受伺服器的響應訊息

int len =0;

while

((len = schannel.

read

(buf))!=

-1)//5. 關閉通道 try catch finally

inchannel.

close()

; schannel.

close()

;}@test

//服務端

public

void

server()

throws ioexception

//6. 傳送反饋給客戶端

buf.

put(

"服務端接收資料成功"

.getbytes()

);buf.

flip()

; schannel.

write

(buf)

;//把緩衝區的資料寫入到accept()得到的客戶端管道

//7. 關閉通道

schannel.

close()

; outchannel.

close()

; sschannel.

close();}}

客戶端流程

1. 客戶端獲取通道 (繫結遠端伺服器 ip、port),獲取檔案管道,並建立緩衝區

2. 讀取本地檔案到繫結指定檔案的輸入管道,並將緩衝區資料寫入到客戶端管道

服務端流程

1. 獲取伺服器通道和繫結最終生成檔案管道。

2. 服務端管道繫結客戶端的連線 (指定客戶端的埠)

3. 分配緩衝區

4. 接收客戶端的資料,並儲存到本地(緩衝區)

非阻塞 io 的核心 —> 選擇器 (selector) 是 selectablechannle 物件的多路復用器,selector允許單執行緒處理多個 channel。如果你的應用開啟了多個連線(通道),但每個連線的流量都很低,使用selector就會很方便。

selector selector = selector.

open()

;

channel.

configureblocking

(false);

selectionkey selectionkey = channel.

register

(selector, selectionkey.op_read)

;

監聽的事件狀態選擇與組合可以用「位或」操作符將常量連線起來

int interestset = selectionkey.op_read | selectionkey.op_write;
注: 與selector一起使用時,channel必須處於非阻塞模式下。這意味著不能將filechannel與selector一起使用,因為filechannel不能切換到非阻塞模式。而套接字通道都可以。

當向selector註冊channel時,register()方法會返回乙個selectionkey物件。這個物件代表了註冊到該selector的通道,也包含了一些你感興趣的屬性:

如果你對「讀就緒」的通道感興趣,select()方法會返回讀事件已經就緒的那些通道。 方法

描述int select()

返回的 int 值表示自上次呼叫select()方法後就緒的通道數

(不懂:阻塞到至少有乙個通道在你註冊的事件上就緒了)

select(long timeout)

和select()一樣,除了最長會阻塞timeout毫秒(引數)。

selectnow()

不會阻塞,不管什麼通道就緒都立刻返回

(譯者注:此方法執行非阻塞的選擇操作。

如果自從前一次選擇操作後,沒有通道變成可選擇的,

則此方法直接返回零)

selectionkey物件代表了註冊到該selector的通道。可以通過selector的selectedkeyset()方法訪問這些sk物件。

set selectedkeys = selector.

selectedkeys()

;iterator keyiterator = selectedkeys.

iterator()

;while

(keyiterator.

hasnext()

)else

if(key.

isconnectable()

)else

if(key.

isreadable()

)else

if(key.

iswritable()

) keyiterator.

remove()

;}

該迴圈遍歷已選擇鍵集中的每個鍵,並檢測各個鍵所對應的通道的就緒事件。

selector不會自己從已選擇鍵集中移除selectionkey例項。必須在處理完通道時自己移除。下次該通道變成就緒時,selector會再次將其放入已選擇鍵集中。

selector.wakeup()方法可以使呼叫select()方法的執行緒從阻塞狀態返回。

如果有其它執行緒呼叫了wakeup()方法,但當前沒有執行緒阻塞在select()方法上,下個呼叫select()方法的執行緒會立即"醒來 (wake up)"。

用完selector後呼叫其close()方法會關閉該selector,且使註冊到該selector上的所有selectionkey例項無效。通道本身並不會關閉。

經過上面的channel分析,我們對①的**做出改進:

客戶端

@test

public

void

client()

throws ioexception schannel.

close()

;//5. 關閉通道

}

服務端

@test

public

void

server()

throws ioexception

else

if(sk.

isreadable()

)}//if

keyiterator.

remove()

;//15. 取消選擇鍵 selectionkey

}//while

}//while

}

selectionkey.channel()方法返回的通道需要轉型成你要處理的型別,如serversocketchannel或socketchannel等。

public

class

testnonblockingnio2

dc.close()

;}@test

public

void

receive()

throws ioexception

} it.

remove()

;}}}

selectablechannle 的結構如下圖:

NIO 的非阻塞式網路通訊

若註冊時不止監聽乙個事件,則可以使用 位或 操作符連線。方 法描 述int interestops 獲取感興趣事件集合 int readyops 獲取通道已經準備就緒的操作的集合 selectablechannel channel 獲取註冊通道 selector selector 返回選擇器 boo...

NIO的非阻塞式網路通訊

虛擬記憶體被作業系統劃分成兩塊 核心空間和使用者空間,核心空間是核心 執行的地方,使用者空間是使用者程式 執行的地方。當程序執行在核心空間時就處於核心態,當程序執行在使用者空間時就處於使用者態。服務端會判斷核心位址空間有沒有資料,如果沒有資料的話,此時的服務端就處於等待狀態。後來,我們想到使用多執行...

C 網路通訊

c 網路通訊 一 伺服器端程式 10.17 1.建立伺服器端socket 1 使用socket類 建立伺服器socket物件 socket objs new socket 引數 使用ipendpoint類設定伺服器ip位址和埠號 或使用dns類 ipaddress serip ipaddress.p...