溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Netty入門知識點(diǎn)有哪些

發(fā)布時(shí)間:2022-01-06 15:22:13 來源:億速云 閱讀:130 作者:iii 欄目:大數(shù)據(jù)

本篇內(nèi)容介紹了“Netty入門知識點(diǎn)有哪些”的有關(guān)知識,在實(shí)際案例的操作過程中,不少人都會(huì)遇到這樣的困境,接下來就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!

Java NIO

再說Netty 之前先簡單了解下Java 的NIO,因?yàn)镹etty也是為了簡化我們的編碼對Java NIO進(jìn)行了一系列的封裝。

Java NIO 從java領(lǐng)域講就是 NEW I/O ,另一種就是Non-blocking I/O。它是一種同步非阻塞的I/O模型,也是I/O多路復(fù)用的基礎(chǔ)。

在NIO中有三個(gè)非常重要的概念,緩沖區(qū)(Buffer)、通道(Channel)、選擇器(Selector)

緩沖區(qū)(Buffer)
1、基礎(chǔ)概念

緩沖區(qū)本質(zhì)上來說就是一個(gè)數(shù)組,在NIO中,所有的操作都是面向緩沖區(qū)的。讀取數(shù)據(jù)時(shí),是從緩沖區(qū)讀取,寫入數(shù)據(jù)時(shí)也是寫入到緩沖區(qū)。所有NIO的數(shù)據(jù)操作都是操作的緩沖區(qū),而面向流I/O系統(tǒng)中,數(shù)據(jù)是直接寫入到Stream對象中的。

在NIO API中所有的緩沖區(qū)類型都繼承Buffer,我們經(jīng)常用到的就是ByteBuffer,NIO這邊對Java的基本類型都有實(shí)現(xiàn)。

2、基本原理

上面提到過緩沖區(qū)其實(shí)就是一個(gè)數(shù)組,其實(shí)是一個(gè)特殊的數(shù)組,它里面內(nèi)置了一些機(jī)制來幫助我們進(jìn)行數(shù)據(jù)的讀寫,能夠跟蹤和記錄緩沖區(qū)的變化方便我們使用。

在緩沖區(qū)中有三個(gè)重要的屬性進(jìn)行合作完成了緩存區(qū)內(nèi)部狀態(tài)變化的跟蹤:

  • position: 指定下一個(gè)將要被寫入或者讀取的元素索引,它的值由get()/put()方法自動(dòng)更新,在新創(chuàng)建一個(gè)Buffer對象時(shí),position被初始化為0。

  • limit: 指定還有多少數(shù)據(jù)需要取出(在從緩沖區(qū)寫入通道時(shí)),或者還有多少空間可以放入數(shù)據(jù)(在從通道讀入緩沖區(qū)時(shí))

  • capacity:指定了可以存儲(chǔ)在緩沖區(qū)中的最大數(shù)據(jù)容量,實(shí)際上,它指定了底層數(shù)組的大小,或者至少是指定了準(zhǔn)許我們使用的底層數(shù)組的容量.

以上三個(gè)屬性的之間的關(guān)系 :0<=position<=limit<=capacity。也就是說當(dāng)我們創(chuàng)建一個(gè)容量為10的ByteBuffer對象時(shí),初始化的時(shí)候,position設(shè)置為0,limit和capacity設(shè)置為10,在以后使用ByteBuffer對象過程中,capacity的值不會(huì)再發(fā)生變化,而其他兩個(gè)將會(huì)隨著使用而變化。

簡單的寫個(gè)偽代碼:

//1、分配一個(gè)容量為10的緩沖區(qū)
ByteBuffer buffer = ByteBuffer.allocate(10);

//2、然后我們可以執(zhí)行操作將數(shù)據(jù)讀取到buffer
channel.read(buffer);
//3、讀取到buffer后我們需要對buffer 進(jìn)行翻轉(zhuǎn)操作(重點(diǎn))
buffer.flip();

//4、翻轉(zhuǎn)后,就可以從buffer 里面進(jìn)行數(shù)據(jù)讀取了
buffer.get();

//5、重置buffer
buffer.clear();

上面大體上分為了五部分,下面簡單的了解下到底發(fā)生了什么? 1、初始化buffer,分配空間,可以直觀的看到buffer三個(gè)參數(shù)的位置 Netty入門知識點(diǎn)有哪些

2、從通道中讀取一些數(shù)據(jù)到緩沖區(qū),這里我們讀取了4個(gè)數(shù)據(jù),可以看到position此時(shí)為4,而limit為10 Netty入門知識點(diǎn)有哪些

3、當(dāng)我們需要把數(shù)據(jù)從緩沖出輸出時(shí),必須先調(diào)用flip()方法。此方法完成了兩件事:一是把limit值設(shè)置為當(dāng)前position的值。二是設(shè)置position值為0。其實(shí)就是為了告訴我們當(dāng)前數(shù)據(jù)的頭和尾是什么。

Netty入門知識點(diǎn)有哪些

4、通過get()叢緩沖區(qū)讀取數(shù)據(jù),這時(shí)position值會(huì)隨著數(shù)據(jù)讀取增加,而limit保持不變,但position不會(huì)超過limit的值。 Netty入門知識點(diǎn)有哪些

5、在數(shù)據(jù)讀取完成后,我們可以使用clear()方法將buffer狀態(tài)進(jìn)行初始化 Netty入門知識點(diǎn)有哪些

3、緩沖區(qū)分配

在上面例子中我們可以看到分配一個(gè)緩沖區(qū)對象時(shí),會(huì)調(diào)用方法allocate(10),相當(dāng)于創(chuàng)建了一個(gè)指定大小的數(shù)組,并包裝成緩沖區(qū)對象。 分配緩沖區(qū)一般有兩種方式:

//1、分配指定大小緩沖區(qū)
ByteBuffer buffer = ByteBuffer.allocate(10);
//2、包裝現(xiàn)有數(shù)組
byte[] arr = new byte[10];
ByteBuffer buffer2 = ByteBuffer.warp(arr);
4、子緩沖區(qū)

子緩沖區(qū),就是在我們剛才ByteBuffer.allocate(10)分配的空間內(nèi)在劃出一塊區(qū)域獨(dú)立操作,調(diào)用slice() 可創(chuàng)建一個(gè)子緩沖區(qū)。子緩沖區(qū)和當(dāng)前緩沖區(qū)是數(shù)據(jù)共享的,其實(shí)只是給其實(shí)一塊區(qū)域提供了一個(gè)視圖窗口。

5、只讀緩沖區(qū)

看名字就知道,這buffer只能讀取數(shù)據(jù)。我們可以調(diào)用asReadOnlyBuffer()方法,將我們的ByteBuffer 轉(zhuǎn)換為只讀緩沖區(qū),注意,這個(gè)方法不是真的將我們當(dāng)前緩沖區(qū)轉(zhuǎn)換為只讀了,而是返回來一個(gè)和當(dāng)前緩沖區(qū)參數(shù)一樣的緩沖區(qū),并和原緩沖區(qū)數(shù)據(jù)共享,只不過這個(gè)是只讀的。如果原緩沖區(qū)內(nèi)容發(fā)送改變,只讀緩沖區(qū)內(nèi)容也會(huì)發(fā)生變化(簡單理解下就是增加了一個(gè)只讀引用) 偽代碼

ByteBuffer buffer = ByteBuffer.allocate(10);

//創(chuàng)建只讀緩沖區(qū)
ByteBuffer readonly = buffer.asReadOnlyBuffer();
6、直接緩沖區(qū)

都知道我們不管怎么創(chuàng)建buffer其實(shí)都在JVM內(nèi)部,在進(jìn)行數(shù)據(jù)傳輸?shù)臅r(shí)候都避免不了,從虛擬機(jī)內(nèi)存拷貝到內(nèi)核空間的復(fù)制操作。而直接緩沖區(qū),就是省略了從用戶空間到內(nèi)核空間拷貝的過程,使用了一個(gè)物理內(nèi)存映射文件來直接對數(shù)據(jù)進(jìn)行操作。在代碼中使用是很簡單的,需調(diào)用allocateDirect()方法,而不是allocate()方法。

Netty入門知識點(diǎn)有哪些

7、內(nèi)存映射(mmap)

內(nèi)存映射是一種讀和寫文件數(shù)據(jù)的方法,比常規(guī)基于流或通道的I/O快的多。簡單點(diǎn)說就是將文件的磁盤扇區(qū)映射到進(jìn)程的虛擬內(nèi)存空間的過程。

選擇器

與傳統(tǒng)Client/Server模式不同,NIO中非阻塞I/O采用了基于Reactor模式的工作方式,I/O調(diào)用不會(huì)被阻塞,而是注冊感興趣的特定I/O事件,如可讀數(shù)據(jù)到達(dá)、新的套接字連接等,在發(fā)生特定事件時(shí),系統(tǒng)再通知我們。NIO中實(shí)現(xiàn)非阻塞I/O的核心對象是Selector,Selector是注冊各種I/O事件的地方,而且當(dāng)那些事件發(fā)生時(shí),就是Seleetor告訴我們所發(fā)生的事件

Netty入門知識點(diǎn)有哪些

從圖中可以看出,當(dāng)有讀或?qū)懙热魏巫缘氖录l(fā)生時(shí),可以從Selector中獲得相應(yīng)的SelectionKey,同時(shí)從SelectionKey中可以找到發(fā)生的事件和該事件所發(fā)生的具體的SelectableChannel,以獲得客戶端發(fā)送過來的數(shù)據(jù)

使用NIO中非阻塞I/O編寫服務(wù)器處理程序,大體上可以分為下面三個(gè)步驟。

  • (1)向Selector對象注冊事件。

  • (2)從Selector中獲取事件。

  • (3)根據(jù)不同的事件進(jìn)行相應(yīng)的處理。

通道

通道就是一個(gè)對象,它可以幫我們進(jìn)行數(shù)據(jù)讀取和寫入,當(dāng)然所有數(shù)據(jù)都是通過操作Buffer對象來處理的。

1、NIO讀取寫入數(shù)據(jù)

讀取數(shù)據(jù)分為三步:

  • (1)從FileInputStream獲取Channel。

  • (2)創(chuàng)建Buffer。

  • (3)將數(shù)據(jù)從Channel讀取到Buffer中。

來看下偽代碼

//獲取文件Channel
FileChannel fc = out.getChannel();
//分配緩沖區(qū)
ByteBuffer buffer = ByteBuffer.allocate(1024);
buffe.put(1);
buffe.put(2);

buffer.flip();

//將數(shù)據(jù)寫入文件
fc.write(buffer);
out.close();
2、多路復(fù)用I/O

什么是多路復(fù)用器? 1、解決IO 狀態(tài)的問題 不解決你的IO 讀寫數(shù)據(jù)的問題。 2、解決用更少的系統(tǒng)調(diào)用,一下詢問所有的IO狀態(tài),不是一次次的詢問IO 的狀態(tài)(與內(nèi)核詢問),減少了用戶態(tài)和內(nèi)核態(tài)切換的過程。

目前流行的多路復(fù)用I/O的實(shí)現(xiàn)主要包括四種:select、poll、epoll、kqueue。如下表所示是它們的一些重要特性的比較。

多路復(fù)用器 Select poll 是阻塞的,其實(shí)就是把文件描述符放在jvm 的內(nèi)存中開辟了一個(gè)數(shù)組,如果是epoll 就是調(diào)用了 epoll_create 放到了內(nèi)核空間。

“Netty入門知識點(diǎn)有哪些”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識可以關(guān)注億速云網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實(shí)用文章!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI