Java網(wǎng)絡(luò)編程基礎(chǔ)(一)3分鐘了解linux網(wǎng)絡(luò)IO模型
Kernel Space(內(nèi)核空間)與User Space(用戶空間)
linux為了避免用戶對操作系統(tǒng)的文件胡亂改寫,造成系統(tǒng)崩潰,區(qū)分了內(nèi)核空間與用戶空間。內(nèi)核空間用來存儲操作系統(tǒng)文件與驅(qū)動程序,而用戶空間來跑用戶的應(yīng)用程序。
所有的系統(tǒng)資源都是在內(nèi)核空間進行操作的,包括網(wǎng)卡。所以一次網(wǎng)絡(luò)IO的讀取,遠程的服務(wù)器發(fā)送過來的數(shù)據(jù),到達網(wǎng)卡后,網(wǎng)卡先拷貝到內(nèi)核緩沖區(qū),內(nèi)核緩沖區(qū)再拷貝到用戶空間的內(nèi)核緩沖區(qū)。然后才能被應(yīng)用程序讀取到。網(wǎng)絡(luò)的IO的寫入恰好相反,數(shù)據(jù)從用戶空間的緩沖區(qū)拷貝到內(nèi)核空間的緩沖區(qū),然后內(nèi)核緩沖區(qū)再通過網(wǎng)卡發(fā)送出去。
Socket(套接字)
所有的網(wǎng)絡(luò)協(xié)議都是基于Socket進行通信的,Socket連接可以建立在不同的協(xié)議之上,如TCP、UDP等等。Linux內(nèi)核將所有的外部設(shè)備當(dāng)做文件處理,對一個文件的IO操作,會返回一個文件描述符(fd)。對Socket的IO操作也同樣返回對應(yīng)文件描述符(socketfd)。有了上面的知識,接下來讓我看下IO的五大模型吧。
Blocking IO(阻塞IO)
在Jdk1.4之前,Java的所有Socket通信都用的這個模型。當(dāng)一個進程調(diào)用recvfrom函數(shù)后,它會進入阻塞狀態(tài),這段時間它就在那摸魚傻等,啥正事都不干,直到數(shù)據(jù)返回。

NIO(非阻塞IO)
Jdk1.4開始才引入Nio的包,但是還有很多不足,直到Jdk1.7對Nio類庫進行了升級,才比較完善。NIO比起上面的BIO就變聰明了,它不會一直傻等,它開啟了輪詢,每隔一段時間,就會找內(nèi)核問下:你好了沒有?內(nèi)核空間如果沒好,就會直接給它返回一個錯誤EWOULDBLOCK。NIO進程會重復(fù)調(diào)用recvfrom,一直問下去,直到內(nèi)核返回數(shù)據(jù)為止。

IO multiplexing(IO多路復(fù)用)
不管是BIO還是NIO,你都得盯著內(nèi)核空間查看數(shù)據(jù)好了沒。只有一個連接還好,要是有個成千上萬,系統(tǒng)可能都要發(fā)不起這些盯梢的工資了。所以為了成本考慮,那就只留下一個盯梢的就好。其他的都畢業(yè)向社會輸送人才。這就是IO多路復(fù)用,使用select、epoll等函數(shù)進行阻塞,盯著所有的Socket連接。

Signal-Drive IO(信號驅(qū)動IO模型)
你(應(yīng)用程序)告訴京東快遞(內(nèi)核)快遞柜自取,快遞員在快遞柜塞好你的快遞后,然后給你發(fā)取貨碼(SIGIO)。你收到信號,去取快遞,這個流程就是信號驅(qū)動IO模型。在京東給你發(fā)取貨碼之前,你是自由的,有很多選擇。

Asynchornours IO(異步IO)
你知道我跟上面的信號驅(qū)動IO模型的區(qū)別是什么嗎?你在京東下單買完東西,快速直接送到了你房門口,你只要開門去拿就行。在京東快遞員(內(nèi)核)給你打電話之前,你是自由的,想干啥就干啥。
