您好,登錄后才能下訂單哦!
本篇內容介紹了“Netty入門知識點有哪些”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!
再說Netty 之前先簡單了解下Java 的NIO,因為Netty也是為了簡化我們的編碼對Java NIO進行了一系列的封裝。
Java NIO 從java領域講就是 NEW I/O ,另一種就是Non-blocking I/O。它是一種同步非阻塞的I/O模型,也是I/O多路復用的基礎。
在NIO中有三個非常重要的概念,緩沖區(Buffer)、通道(Channel)、選擇器(Selector)
緩沖區本質上來說就是一個數組,在NIO中,所有的操作都是面向緩沖區的。讀取數據時,是從緩沖區讀取,寫入數據時也是寫入到緩沖區。所有NIO的數據操作都是操作的緩沖區,而面向流I/O系統中,數據是直接寫入到Stream對象中的。
在NIO API中所有的緩沖區類型都繼承Buffer,我們經常用到的就是ByteBuffer,NIO這邊對Java的基本類型都有實現。
上面提到過緩沖區其實就是一個數組,其實是一個特殊的數組,它里面內置了一些機制來幫助我們進行數據的讀寫,能夠跟蹤和記錄緩沖區的變化方便我們使用。
在緩沖區中有三個重要的屬性進行合作完成了緩存區內部狀態變化的跟蹤:
position: 指定下一個將要被寫入或者讀取的元素索引,它的值由get()/put()方法自動更新,在新創建一個Buffer對象時,position被初始化為0。
limit: 指定還有多少數據需要取出(在從緩沖區寫入通道時),或者還有多少空間可以放入數據(在從通道讀入緩沖區時)
capacity:指定了可以存儲在緩沖區中的最大數據容量,實際上,它指定了底層數組的大小,或者至少是指定了準許我們使用的底層數組的容量.
以上三個屬性的之間的關系 :0<=position<=limit<=capacity。也就是說當我們創建一個容量為10的ByteBuffer對象時,初始化的時候,position設置為0,limit和capacity設置為10,在以后使用ByteBuffer對象過程中,capacity的值不會再發生變化,而其他兩個將會隨著使用而變化。
簡單的寫個偽代碼:
//1、分配一個容量為10的緩沖區 ByteBuffer buffer = ByteBuffer.allocate(10); //2、然后我們可以執行操作將數據讀取到buffer channel.read(buffer); //3、讀取到buffer后我們需要對buffer 進行翻轉操作(重點) buffer.flip(); //4、翻轉后,就可以從buffer 里面進行數據讀取了 buffer.get(); //5、重置buffer buffer.clear();
上面大體上分為了五部分,下面簡單的了解下到底發生了什么? 1、初始化buffer,分配空間,可以直觀的看到buffer三個參數的位置
2、從通道中讀取一些數據到緩沖區,這里我們讀取了4個數據,可以看到position此時為4,而limit為10
3、當我們需要把數據從緩沖出輸出時,必須先調用flip()方法。此方法完成了兩件事:一是把limit值設置為當前position的值。二是設置position值為0。其實就是為了告訴我們當前數據的頭和尾是什么。
4、通過get()叢緩沖區讀取數據,這時position值會隨著數據讀取增加,而limit保持不變,但position不會超過limit的值。
5、在數據讀取完成后,我們可以使用clear()方法將buffer狀態進行初始化
在上面例子中我們可以看到分配一個緩沖區對象時,會調用方法allocate(10),相當于創建了一個指定大小的數組,并包裝成緩沖區對象。 分配緩沖區一般有兩種方式:
//1、分配指定大小緩沖區 ByteBuffer buffer = ByteBuffer.allocate(10); //2、包裝現有數組 byte[] arr = new byte[10]; ByteBuffer buffer2 = ByteBuffer.warp(arr);
子緩沖區,就是在我們剛才ByteBuffer.allocate(10)分配的空間內在劃出一塊區域獨立操作,調用slice() 可創建一個子緩沖區。子緩沖區和當前緩沖區是數據共享的,其實只是給其實一塊區域提供了一個視圖窗口。
看名字就知道,這buffer只能讀取數據。我們可以調用asReadOnlyBuffer()方法,將我們的ByteBuffer 轉換為只讀緩沖區,注意,這個方法不是真的將我們當前緩沖區轉換為只讀了,而是返回來一個和當前緩沖區參數一樣的緩沖區,并和原緩沖區數據共享,只不過這個是只讀的。如果原緩沖區內容發送改變,只讀緩沖區內容也會發生變化(簡單理解下就是增加了一個只讀引用) 偽代碼
ByteBuffer buffer = ByteBuffer.allocate(10); //創建只讀緩沖區 ByteBuffer readonly = buffer.asReadOnlyBuffer();
都知道我們不管怎么創建buffer其實都在JVM內部,在進行數據傳輸的時候都避免不了,從虛擬機內存拷貝到內核空間的復制操作。而直接緩沖區,就是省略了從用戶空間到內核空間拷貝的過程,使用了一個物理內存映射文件來直接對數據進行操作。在代碼中使用是很簡單的,需調用allocateDirect()方法,而不是allocate()方法。
內存映射是一種讀和寫文件數據的方法,比常規基于流或通道的I/O快的多。簡單點說就是將文件的磁盤扇區映射到進程的虛擬內存空間的過程。
與傳統Client/Server模式不同,NIO中非阻塞I/O采用了基于Reactor模式的工作方式,I/O調用不會被阻塞,而是注冊感興趣的特定I/O事件,如可讀數據到達、新的套接字連接等,在發生特定事件時,系統再通知我們。NIO中實現非阻塞I/O的核心對象是Selector,Selector是注冊各種I/O事件的地方,而且當那些事件發生時,就是Seleetor告訴我們所發生的事件
從圖中可以看出,當有讀或寫等任何注冊的事件發生時,可以從Selector中獲得相應的SelectionKey,同時從SelectionKey中可以找到發生的事件和該事件所發生的具體的SelectableChannel,以獲得客戶端發送過來的數據
使用NIO中非阻塞I/O編寫服務器處理程序,大體上可以分為下面三個步驟。
(1)向Selector對象注冊事件。
(2)從Selector中獲取事件。
(3)根據不同的事件進行相應的處理。
通道就是一個對象,它可以幫我們進行數據讀取和寫入,當然所有數據都是通過操作Buffer對象來處理的。
讀取數據分為三步:
(1)從FileInputStream獲取Channel。
(2)創建Buffer。
(3)將數據從Channel讀取到Buffer中。
來看下偽代碼
//獲取文件Channel FileChannel fc = out.getChannel(); //分配緩沖區 ByteBuffer buffer = ByteBuffer.allocate(1024); buffe.put(1); buffe.put(2); buffer.flip(); //將數據寫入文件 fc.write(buffer); out.close();
什么是多路復用器? 1、解決IO 狀態的問題 不解決你的IO 讀寫數據的問題。 2、解決用更少的系統調用,一下詢問所有的IO狀態,不是一次次的詢問IO 的狀態(與內核詢問),減少了用戶態和內核態切換的過程。
目前流行的多路復用I/O的實現主要包括四種:select、poll、epoll、kqueue。如下表所示是它們的一些重要特性的比較。
多路復用器 Select poll 是阻塞的,其實就是把文件描述符放在jvm 的內存中開辟了一個數組,如果是epoll 就是調用了 epoll_create 放到了內核空間。
“Netty入門知識點有哪些”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。