socketchannel
serversocketchannel
jdk8
channel
概念
如果乙個channel
實現了interrupted
介面,那麼當他被阻塞,並且發生中斷的時候,那麼該channel
將會被中斷,執行緒會丟擲乙個closedbyinterruptexception
異常,如果乙個執行緒的狀態是中斷,他試圖訪問乙個channel
,那麼channel
將立即被關閉。
channel
可以以阻塞(blocking)或者非阻塞(nonblocking)模式執行,非阻塞模式的channel
永遠不會讓呼叫的執行緒休眠,請求的操作要麼立即完成,要麼返回乙個結果表明未進行任何操作,不是所有通道都可以使用非阻塞模式
channel
分為兩類:filechannel
和socket
通道,包括socketchannel
、serversocketchannel
和datagramchannel(udp)
,socket
通道可以直接通過工廠方法建立,但是乙個filechannel
只能通過乙個開啟的randomaccessfile
、fileinputstream
、fileoutputstream
物件上呼叫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,那下次執行緒排程的時候,就有可能寫亂資料
因為讀/寫本身就是阻塞式的,同時只有乙個執行緒可以操作,但是讀/寫都不是執行緒安全的,所以一般乙個通道也都只有乙個執行緒讀,乙個執行緒寫,或者乙個執行緒把讀/寫都做了
read
和write
方法並不一定會操作和bytebuffer
容量相等的資料,這兩個方法會返回這期間操作的位元組數,因此在應用端需要判斷,如果僅僅進行部分傳輸,需要重新進行傳輸,使用hasreminding()
方法判斷是否還有資料
channel
不能被重複利用,乙個開啟的channel
即代表與乙個特定的i/o服務的特定連線,並封裝該連線的狀態。當channel
關閉時,那個連線會丟失,然後channel
將不再連線任何東西。
channel
呼叫通道的close()
方法時,可能會導致在channel
關閉底層i/o服務的過程中線程暫時阻塞(即使channel
處於非阻塞模式)。通道關閉的阻塞行為(如果有的話)是高度取決於作業系統或檔案系統的(socket通道關閉會花費較長時間,具體時耗取決於作業系統的網路實現。在輸出內容被提取時,一些網路協議堆疊可能會阻塞通道的關閉,在通道關閉之後,正在進行的read或者write操作會收到乙個asynchronouscloseexception
)。在乙個通道上多次呼叫close()
方法是沒有壞處的,但是如果第乙個執行緒在close()
方法中阻塞,那麼在它完成關閉通道之前,任何其他呼叫close()
方法都會阻塞,後續在已關閉的channel
上調close()
方法不會產生任何操作,只會立即返回
關閉乙個已經註冊的selectablechannel
需要兩個步驟
socket
和socketchannel
類封裝點對點、有序的網路連線。每個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
是乙個面向流的監聽socket
的selectablechannel
。serversocketchannel
是乙個抽象類,即不能直接例項化,可以通過自身的靜態方法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...