《Netty In Action中文版》第五章:Buffers(緩衝),nettyinaction

來源:互聯網
上載者:User

《Netty In Action中文版》第五章:Buffers(緩衝),nettyinaction

        註:本篇內容出自《Netty In Action》一書;

        註:本人原創譯文,轉載請註明出處!

        本章介紹

  • ByteBuf
  • ByteBufHolder
  • ByteBufAllocator
  • 使用這些介面分配緩衝和執行操作
        每當你需要傳輸資料時,它必須包含一個緩衝區。Java NIO API內建的緩衝區類是相當有限的,沒有經過最佳化,使用JDK的ByteBuffer操作更複雜。緩衝區是一個重要的組建,它是API的一部分。Netty提供了一個強大的緩衝區實現用於表示一個位元組序列,並協助你操作原始位元組或自訂的POJO。Netty的ByteBuf相當於JDK的ByteBuffer,ByteBuf的作用是在Netty中通過Channel傳輸資料。它被重新設計以解決JDK的ByteBuffer中的一些問題,從而使開發人員開發網路應用程式顯得更有效率。本章將講述Netty中的緩衝區,並瞭解它為什麼比JDK內建的緩衝區實現更優秀,還會深入瞭解在Netty中使用ByteBuf訪問資料以及如何使用它。

5.1 Buffer API
        Netty的緩衝API有兩個介面:
  • ByteBuf
  • ByteBufHolder
Netty使用reference-counting(引用計數)的時候知道安全釋放Buf和其他資源,雖然知道Netty有效使用引用計數,這都是自動完成的。這允許Netty使用池和其他技巧來加快速度和保持記憶體利用率在正常水平,你不需要做任何事情來實現這一點,但是在開發Netty應用程式時,你應該處理資料儘快釋放池資源。
        Netty緩衝API提供了幾個優勢:
  • 可以自訂緩衝類型
  • 通過一個內建的複合緩衝類型實現零拷貝
  • 擴充性好,比如StringBuffer
  • 不需要調用flip()來切換讀/寫入模式
  • 讀取和寫入索引分開
  • 方法鏈
  • 引用計數
  • Pooling(池)
5.2 ByteBuf - 位元組資料容器
        當需要與遠程進行互動時,需要以位元組碼發送/接收資料。由於各種原因,一個高效、方便、易用的資料介面是必須的,而Netty的ByteBuf滿足這些需求,ByteBuf是一個很好的經過最佳化的資料容器,我們可以將位元組資料有效添加到ByteBuf中或從ByteBuf中擷取資料。ByteBuf有2部分:一個用於讀,一個用於寫。我們可以按順序的讀取資料,並且可以跳到開始重新讀一遍。所有的資料操作,我們只需要做的是調整讀取資料索引和再次開始讀操作。5.2.1 ByteBuf如何在工作?
        寫入資料到ByteBuf後,寫入索引是增加的位元組數量。開始讀位元組後,讀取索引增加。你可以讀取位元組,直到寫入索引和讀取索引處理相同的位置,次數若繼續讀取,則會拋出IndexOutOfBoundsException。調用ByteBuf的任何方法開始讀/寫都會單獨維護讀索引和寫索引。ByteBuf的預設最大容量限制是Integer.MAX_VALUE,寫入時若超出這個值將會導致一個異常。        ByteBuf類似於一個位元組數組,最大的區別是讀和寫的索引可以用來控制對緩衝區資料的訪問。顯示了一個容量為16的ByteBuf:
5.2.2 不同類型的ByteBuf        使用Netty時會遇到3種不同類型的ByteBuf Heap Buffer(堆緩衝區)        最常用的類型是ByteBuf將資料存放區在JVM的堆空間,這是通過將資料存放區在數組的實現。堆緩衝區可以快速分配,當不使用時也可以快速釋放。它還提供了直接存取數組的方法,通過ByteBuf.array()來擷取byte[]資料。        訪問非堆緩衝區ByteBuf的數組會導致UnsupportedOperationException,可以使用ByteBuf.hasArray()來檢查是否支援訪問數組。 Direct Buffer(直接緩衝區)        直接緩衝區,在堆之外直接分配記憶體。直接緩衝區不會佔用堆空間容量,使用時應該考慮到應用程式要使用的最大記憶體容量以及如何限制它。直接緩衝區在使用Socket傳遞資料時效能很好,因為若使用間接緩衝區,JVM會先將資料複製到直接緩衝區再進行傳遞;但是直接緩衝區的缺點是在分配記憶體空間和釋放記憶體時比堆緩衝區更複雜,而Netty使用記憶體池來解決這樣的問題,這也是Netty使用記憶體池的原因之一。直接緩衝區不支援數組訪問資料,但是我們可以間接的訪問資料數組,如下面代碼:
ByteBuf directBuf = Unpooled.directBuffer(16);if(!directBuf.hasArray()){int len = directBuf.readableBytes();byte[] arr = new byte[len];directBuf.getBytes(0, arr);}
訪問直接緩衝區的資料數組需要更多的編碼和更複雜的操作,建議若需要在數組訪問資料使用堆緩衝區會更好。Composite Buffer(複合緩衝區)        複合緩衝區,我們可以建立多個不同的ByteBuf,然後提供一個這些ByteBuf組合的視圖。複合緩衝區就像一個列表,我們可以動態添加和刪除其中的ByteBuf,JDK的ByteBuffer沒有這樣的功能。Netty提供了CompositeByteBuf類來處理複合緩衝區,CompositeByteBuf只是一個視圖,CompositeByteBuf.hasArray()總是返回false,因為它可能包含一些直接或間接的不同類型的ByteBuf。        例如,一條訊息由header和body兩部分組成,將header和body組裝成一條訊息發送出去,可能body相同,只是header不同,使用CompositeByteBuf就不用每次都重新分配一個新的緩衝區。顯示CompositeByteBuf組成header和body:

若使用JDK的ByteBuffer就不能這樣簡單的實現,只能建立一個數組或建立一個新的ByteBuffer,再將內容複寫到新的ByteBuffer中。下面是使用CompositeByteBuf的例子:
CompositeByteBuf compBuf = Unpooled.compositeBuffer();ByteBuf heapBuf = Unpooled.buffer(8);ByteBuf directBuf = Unpooled.directBuffer(16);//添加ByteBuf到CompositeByteBufcompBuf.addComponents(heapBuf,directBuf);//刪除第一個ByteBufcompBuf.removeComponent(0);Iterator<ByteBuf> iter = compBuf.iterator();while(iter.hasNext()){System.out.println(iter.next().toString());}//使用數組訪問資料if(!compBuf.hasArray()){int len = compBuf.readableBytes();byte[] arr = new byte[len];compBuf.getBytes(0, arr);}
CompositeByteBuf是ByteBuf的子類,我們可以像操作BytBuf一樣操作CompositeByteBuf。並且Netty最佳化通訊端讀寫的操作是儘可能的使用CompositeByteBuf來做的,使用CompositeByteBuf不會操作記憶體泄露問題。5.3 ByteBuf的位元組操作
        ByteBuf提供了許多操作,允許修改其中的資料內容或只是讀取資料。ByteBuf和JDK的ByteBuffer很像,但是ByteBuf提供了更好的效能。5.3.1 隨機訪問索引
        ByteBuf使用zero-based-indexing(從0開始的索引),第一個位元組的索引是0,最後一個位元組的索引是ByteBuf的capacity - 1,下面代碼是遍曆ByteBuf的所有位元組:
//create a ByteBuf of capacity is 16ByteBuf buf = Unpooled.buffer(16);//write data to buffor(int i=0;i<16;i++){buf.writeByte(i+1);}//read data from buffor(int i=0;i<buf.capacity();i++){System.out.println(buf.getByte(i));}
注意通過索引訪問時不會推進讀索引和寫索引,我們可以通過ByteBuf的readerIndex()或writerIndex()來分別推進讀索引或寫索引。5.3.2 順序訪問索引
        ByteBuf提供兩個指標變數支付讀和寫操作,讀操作是使用readerIndex(),寫操作時使用writerIndex()。這和JDK的ByteBuffer不同,ByteBuffer只有一個方法來設定索引,所以需要使用flip()方法來切換讀和寫入模式。        ByteBuf一定符合:0 <= readerIndex <= writerIndex <= capacity。
5.3.3 Discardable bytes廢棄位元組
        我們可以調用ByteBuf.discardReadBytes()來回收已經讀取過的位元組,discardReadBytes()將丟棄從索引0到readerIndex之間的位元組。調用discardReadBytes()方法後會變成如:
        ByteBuf.discardReadBytes()可以用來清空ByteBuf中已讀取的資料,從而使ByteBuf有多餘的空間容納新的資料,但是discardReadBytes()可能會涉及記憶體複製,因為它需要移動ByteBuf中可讀的位元組到開始位置,這樣的操作會影響效能,一般在需要馬上釋放記憶體的時候使用收益會比較大。5.3.4 可讀位元組(實際內容)
        任何讀操作會增加readerIndex,如果讀取操作的參數也是一個ByteBuf而沒有指定目的索引,指定的目的緩衝區的writerIndex會一起增加,沒有足夠的內容時會拋出IndexOutOfBoundException。新分配、封裝、複製的緩衝區的readerIndex的預設值都是0。下面代碼顯示了擷取所有可讀資料:
ByteBuf buf = Unpooled.buffer(16);while(buf.isReadable()){System.out.println(buf.readByte());}
(代碼於原書中有出入,原書可能是基於Netty4之前的版本講解的,此處基於Netty4)5.3.5 可寫位元組Writable bytes
        任何寫的操作會增加writerIndex。若寫操作的參數也是一個ByteBuf並且沒有指定資料來源索引,那麼指定緩衝區的readerIndex也會一起增加。若沒有足夠的可寫位元組會拋出IndexOutOfBoundException。新分配的緩衝區writerIndex的預設值是0。下面代碼顯示了隨機一個int數字來填充緩衝區,直到緩衝區空間耗盡:
Random random = new Random();ByteBuf buf = Unpooled.buffer(16);while(buf.writableBytes() >= 4){buf.writeInt(random.nextInt());}
5.3.6 清除緩衝區索引Clearing the buffer indexs
        調用ByteBuf.clear()可以設定readerIndex和writerIndex為0,clear()不會清除緩衝區的內容,只是將兩個索引值設定為0。請注意ByteBuf.clear()與JDK的ByteBuffer.clear()的語義不同。        顯示了ByteBuf調用clear()之前:
        顯示了調用clear()之後:
        和discardReadBytes()相比,clear()是便宜的,因為clear()不會複製任何記憶體。5.3.7 搜尋操作Search operations
        各種indexOf()方法協助你定位一個值的索引是否符合,我們可以用ByteBufProcessor複雜動態順序搜尋實現簡單的靜態單位元組搜尋。如果你想解碼可變長度的資料,如null結尾的字串,你會發現bytesBefore(byte value)方法有用。例如我們寫一個整合的flash sockets的應用程式,這個應用程式使用NULL結束的內容,使用bytesBefore(byte value)方法可以很容易的檢查資料中的空位元組。沒有ByteBufProcessor的話,我們需要自己做這些事情,使用ByteBufProcessor效率更好。5.3.8 標準和重設Mark and reset
        每個ByteBuf有兩個標註索引,一個儲存readerIndex,一個儲存writerIndex。你可以通過調用一個重設方法重新置放兩個索引之一,它類似於InputStream的標註和重設方法,沒有讀限制。我們可以通過調用readerIndex(int readerIndex)和writerIndex(int writerIndex)移動讀索引和寫索引到指定位置,調用這兩個方法設定指定索引位置時可能拋出IndexOutOfBoundException。5.3.9 衍生的緩衝區Derived buffers
        調用duplicate()、slice()、slice(int index, int length)、order(ByteOrder endianness)會建立一個現有緩衝區的視圖。衍生的緩衝區有獨立的readerIndex、writerIndex和標註索引。如果需要現有緩衝區的全新副本,可以使用copy()或copy(int index, int length)獲得。看下面代碼:
// get a Charset of UTF-8Charset utf8 = Charset.forName("UTF-8");// get a ByteBufByteBuf buf = Unpooled.copiedBuffer("Netty in Action rocks!", utf8);// sliceByteBuf sliced = buf.slice(0, 14);// copyByteBuf copy = buf.copy(0, 14);// print "Netty in Action rocks!"System.out.println(buf.toString(utf8));// print "Netty in Act"System.out.println(sliced.toString(utf8));// print "Netty in Act"System.out.println(copy.toString(utf8));
5.3.10 讀/寫操作以及其他一些操作
        有兩種主要類型的讀寫操作:
  • get/set操作以索引為基礎,在給定的索引設定或擷取位元組
  • 從當前索引開始讀寫,遞增當前的寫索引或讀索引
        ByteBuf的各種讀寫方法或其他一些檢查方法可以看ByteBuf的源碼,這裡不贅述了。5.4 ByteBufHolder
        ByteBufHolder是一個輔助類,是一個介面,其實作類別是DefaultByteBufHolder,還有一些實現了ByteBufHolder介面的其他介面類。ByteBufHolder的作用就是協助更方便的訪問ByteBuf中的資料,當緩衝區沒用了後,可以使用這個輔助類釋放資源。ByteBufHolder很簡單,提供的可供訪問的方法也很少。如果你想實現一個“訊息對象”承載儲存在ByteBuf,使用ByteBufHolder是一個好主意。        儘管Netty提供的各種緩衝區實作類別已經很容易使用,但Netty依然提供了一些使用的工具類,使得建立和使用各種緩衝區更加方便。下面會介紹一些Netty中的緩衝區工具類。5.4.1 ByteBufAllocator
        Netty支援各種ByteBuf的池實現,來使Netty提供一種稱為ByteBufAllocator成為可能。ByteBufAllocator負責分配ByteBuf執行個體,ByteBufAllocator提供了各種分配不同ByteBuf的方法,如需要一個堆緩衝區可以使用ByteBufAllocator.heapBuffer(),需要一個直接緩衝區可以使用ByteBufAllocator.directBuffer(),需要一個複合緩衝區可以使用ByteBufAllocator.compositeBuffer()。其他方法的使用可以看ByteBufAllocator源碼及注釋。        擷取ByteBufAllocator對象很容易,可以從Channel的alloc()擷取,也可以從ChannelHandlerContext的alloc()擷取。看下面代碼:
ServerBootstrap b = new ServerBootstrap();b.group(group).channel(NioServerSocketChannel.class).localAddress(new InetSocketAddress(port)).childHandler(new ChannelInitializer<SocketChannel>() {@Overrideprotected void initChannel(SocketChannel ch) throws Exception {// get ByteBufAllocator instance by Channel.alloc()ByteBufAllocator alloc0 = ch.alloc();ch.pipeline().addLast(new ChannelInboundHandlerAdapter() {@Overridepublic void channelActive(ChannelHandlerContext ctx) throws Exception {//get ByteBufAllocator instance by ChannelHandlerContext.alloc()ByteBufAllocator alloc1 = ctx.alloc();ctx.writeAndFlush(buf.duplicate()).addListener(ChannelFutureListener.CLOSE);}});}});
        Netty有兩種不同的ByteBufAllocator實現,一個實現ByteBuf執行個體池將分配和回收成本以及記憶體使用量降到最低;另一種實現是每次使用都建立一個新的ByteBuf執行個體。Netty預設使用PooledByteBufAllocator,我們可以通過ChannelConfig或通過引導設定一個不同的實現來改變。更多細節在後面講述。
5.4.2 Unpooled
        Unpooled也是用來建立緩衝區的工具類,Unpooled的使用也很容易。Unpooled提供了很多方法,詳細方法及使用可以看API文檔或Netty源碼。看下面代碼:
//建立複合緩衝區CompositeByteBuf compBuf = Unpooled.compositeBuffer();//建立堆緩衝區ByteBuf heapBuf = Unpooled.buffer(8);//建立直接緩衝區ByteBuf directBuf = Unpooled.directBuffer(16);
5.4.3 ByteBufUtil
        ByteBufUtil提供了一些靜態方法,在操作ByteBuf時非常有用。ByteBufUtil提供了Unpooled之外的一些方法,也許最有價值的是hexDump(ByteBuf buffer)方法,這個方法返回指定ByteBuf中可讀位元組的十六進位字串,可以用於偵錯工具時列印ByteBuf的內容,十六進位字串相比位元組而言對使用者更友好。5.5 Summary
        本章主要學習Netty提供的緩衝區類ByteBuf的建立和簡單實用以及一些操作ByteBuf的工具類。
安徽省人事廳職稱電腦考試報名

[頂]四川省電腦等級考試一級考試大綱

1、 電腦基本常識:電子電腦的發展及特點、電子電腦的分類及應用
2、 電腦中資訊的表示:進位計數制的概念;二、八、十和十六進位的表示及相互轉
換;數、字元的編碼錶示(ASCII 碼及漢字國標碼、區位碼、
內碼、外碼);電腦資訊表示單位:位、位元組、字;儲存
容量的概念
3、 電腦系統的組成:電腦硬體系統的組成,各部分分類及功能;電腦軟體系統;
電腦系統中軟、硬體的關係;電腦的工作過程;電腦的
主要效能指標(字長、內外儲存空間容量、運算速度等)
4、 電腦網路基本知識:電腦網路的定義、功能、分類;Intrernet 基礎知識及應用 (
電子郵件、檔案傳輸、WWW 等;IP 位址與網域名稱系統的基本
概念)
5、 多媒體技術基本知識:多媒體技術的基本概念、主要應用領域
6、 電腦病毒常識:電腦病毒的定義及其防治

第二章 DOS 作業系統

本章重點內容提要:
1、 Dos 的基本組成及引導啟動
2、 檔案的概念,檔案的命名規則,檔案目錄(目錄的樹型結構、路徑、目前的目錄、絕
對路徑、相對路徑)
3、 Dos 的常用命令:DIR , CD , MD , COPY , DEL , REN , FORMAT , TYPE , XCOPY ,
DELTREE
4、 系統設定檔CONFIG.SYS 的功能及設定(FILES , BUFFERS , DEVICE)
5、 批處理概念及自動批次檔

第三章 Windows 作業系統

本章重點內容:
1、Windows95 的特點
2、Windows95 圖形化使用者介面的組成與操作(案頭、視窗、對話方塊、表徵圖、開始菜單與任務
欄)
3、Windows95 的管理功能:
①“我的電腦”與“資源管理員”功能及操作
②電腦資源的瀏覽
③檔案及檔案夾的建立、拷貝、尋找、移動、刪除及重新命名
④磁碟管理
4、Windows95 線上說明

第四章 中文文文書處理系統Word97

本章重點內容提要:
1、 文檔的基本操作(建立、開啟、關閉、儲存)
2、 文字編輯的基本操作(游標移動;字元及字塊的插入、改寫、刪除、移動、複製;
字串的尋找與替換)
3、 文檔的排版(頁面、段落、字元的格式調整)
4、 樣式及模板的使用
5、 表格、圖形

第五章 中文試算表Excel97

本章重點內容提要:
1、 試算表的基本概念
2、 工作表的建立和編輯
3、 使用公式與函數(自動加總,SUM,AVERAGE,COUNT,MAX,MIN)
4、 活頁簿的概念及多工作表間的相互操作
5、 圖表製作
6、 資料處理(記錄的排序、篩選、分類匯總)

附:一級考試要求

1、 掌握電腦的基礎知識
2、 瞭解電腦系統的基本組成及其工作過程
3、 瞭解微機作業系統的功能並具有使用微機作業系統的基本能力
4、 掌握各種漢字IME,掌握文書處理的基本知識,具有一種文書處理軟體的使用能力
5、 掌握試算表的基本知識具有使用試算表的基本能力
6、 瞭解電腦網路基本知識
7、 掌握電腦安全使用知識...餘下全文>>
 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.