1. 程式人生 > >Java網路程式設計--Netty中的ByteBuf

Java網路程式設計--Netty中的ByteBuf

ByteBuf的操作

ByteBuf有三個重要的屬性:capacity容量,readerIndex讀取位置,writerIndex寫入位置 提供了readerIndex和weiterIndex兩個變數指標來支援順序讀和寫操作

下圖顯示了一個緩衝區是如何被兩個指標分割成三個區域的:

img

程式碼示例:

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;

import java.util.Arrays;

public class ByteBufDemo {
  public static void main(String[] args) {
    // 1.建立一個非池化的ByteBuf,大小為10個位元組
    ByteBuf buf = Unpooled.buffer(10);
    System.out.println("原始ByteBuf為:" + buf.toString());
    System.out.println("1.ByteBuf中的內容為:" + Arrays.toString(buf.array()) + "\n");

    // 2.寫入一段內容
    byte[] bytes = {1, 2, 3, 4, 5};
    buf.writeBytes(bytes);
    System.out.println("寫入的bytes為:" + Arrays.toString(bytes));
    System.out.println("寫入一段內容後ByteBuf為:" + buf.toString());
    System.out.println("2.ByteBuf中的內容為:" + Arrays.toString(buf.array()) + "\n");

    // 3. 讀取一段內容
    byte b1 = buf.readByte();
    byte b2 = buf.readByte();
    System.out.println("讀取的bytes為:" + Arrays.toString(new byte[] {b1, b2}));
    System.out.println("讀取一段內容後ByteBuf為:" + buf.toString());
    System.out.println("3.ByteBuf中的內容為:" + Arrays.toString(buf.array()) + "\n");

    // 4.將讀取的內容丟棄
    buf.discardReadBytes();
    System.out.println("將讀取的內容丟棄後ByteBuf為:" + buf.toString());
    System.out.println("4.ByteBuf中的內容為:" + Arrays.toString(buf.array()) + "\n");

    // 5.清空讀寫指標
    buf.clear();
    System.out.println("清空讀寫指標後ByteBuf為:" + buf.toString());
    System.out.println("5.ByteBuf中的內容為:" + Arrays.toString(buf.array()) + "\n");

    // 6.再次寫入一段內容,比第一段內容少
    byte[] bytes2 = {1, 2, 3};
    buf.writeBytes(bytes2);
    System.out.println("寫入的bytes為:" + Arrays.toString(bytes2));
    System.out.println("寫入一段內容後ByteBuf為:" + buf.toString());
    System.out.println("6.ByteBuf中的內容為:" + Arrays.toString(buf.array()) + "\n");

    // 7.將ByteBuf清零
    buf.setZero(0, buf.capacity());
    System.out.println("清零後ByteBuf為:" + buf.toString());
    System.out.println("7.ByteBuf中的內容為:" + Arrays.toString(buf.array()) + "\n");

    // 8.再次寫入一段超過容量的內容
    byte[] bytes3 = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
    buf.writeBytes(bytes3);
    System.out.println("寫入的bytes為:" + Arrays.toString(bytes));
    System.out.println("寫入一段內容後ByteBuf為:" + buf.toString());
    System.out.println("8.ByteBuf中的內容為:" + Arrays.toString(buf.array()) + "\n");
  }
}

ButeBuf動態擴容

capacity預設值:256位元組,最大值:Integer.MAX_VALUE (2G)

writeXXX方法呼叫時,通過AbstractByteBuf.ensureWritable0()方法進行檢查 容量計算方法:AbstractByteBufAllocator.calculateNewCapacity

根據capacity的最小值要求,對應有兩套計算方法: 沒超過4兆:從64位元組開始,每次遞增一倍,直至計算出來的newCapacity滿足新容量最小要求 示例:當前大小256,已寫250,繼續寫10位元組的資料,需要的最小容量要求是261,則新容量為64x2x2x2=512

超過4兆:新容量=新容量最小要求/4兆x4兆+4兆 示例:當前大小為3兆,已寫3兆,繼續寫2兆,需要的最小容量大小為5兆,則新容量是8兆(不能超過最大值)

4兆的來源:一個固定的閾值AbstractByteBufAllocator.CALCULATE_THRESHOLD

ByteBuf的實現

img

在使用中都是通過ByteBufAllocator分配器進行申請,同時具備有記憶體管理功能

PooledByteBuf物件,記憶體 複用

PooledThreadCache:PooledByteBufAllocator例項維護的一個執行緒變數 多種分類的MemoryRegionCache陣列用作記憶體快取,MemoryRegionCache內部是連結串列,佇列裡面存Chuck。PoolChuck裡面維護了記憶體引用,記憶體複用的做法就是把buf的memory指向chuck的memory PooledByteBufAllocator.ioBuffer運作過程梳理:

img

零拷貝機制

Netty的零拷貝機制,是一種應用層的實現,和底層JVM,作業系統記憶體機制並無過多關聯。

  1. CompositeByteBuf,將多個ByteBuf合併為一個邏輯上的ByteBuf,避免了各個ByteBuf之間的拷貝

img

  1. wrapedBuffer()方法,將byte[]陣列包裝成ByteBuf物件

img

  1. slice()方法,將一個ByteBuf物件切割成多個ByteBuf物件

img

程式碼示例:

public class ZeroCopyTest {

  public static void main(String[] args) {
    ByteBuf buffer1 = Unpooled.buffer(7);
    buffer1.writeByte(7);
    ByteBuf buffer2 = Unpooled.buffer(7);
    buffer2.writeByte(13);
    CompositeByteBuf compositeByteBuf = Unpooled.compositeBuffer();
    CompositeByteBuf newBuf = compositeByteBuf.addComponents(true, buffer1, buffer2);
    System.out.println("CompositeByteBuf:" + newBuf);

    byte[] bytes = {1, 2, 3};
    ByteBuf wrappedBuffer = Unpooled.wrappedBuffer(bytes);
    System.out.println("wrappedBuffer:" + wrappedBuffer.getByte(2));
    bytes[2] = 7;
    System.out.println("wrappedBuffer:" + wrappedBuffer.getByte(2));

    ByteBuf buf = Unpooled.wrappedBuffer("Netty".getBytes());
    ByteBuf slice = buf.slice(1, 2);
    slice.unwrap();
    System.out.println("slice:" + slice);
  }
}

相關推薦

Java網路程式設計--NettyByteBuf

ByteBuf的操作 ByteBuf有三個重要的屬性:capacity容量,readerIndex讀取位置,writerIndex寫入位置 提供了readerIndex和weiterIndex兩個變數指標來支援順序讀和寫操作 下圖顯示了一個緩衝區是如何被兩個指標分割成三個區域的: 程式碼示例: impor

Java網路程式設計--Netty的責任鏈

Netty中的責任鏈 設計模式 - 責任鏈模式 責任鏈模式(Chain of Responsibility Pattern)是一種是行為型設計模式,它為請求建立了一個處理物件的鏈。其鏈中每一個節點都看作是一個物件,每個節點處理的請求均不同,且內部自動維護一個下一節點物件。當一個請求從鏈式的首端發出時,會沿著

Java網路程式設計--Netty入門

Netty簡介 Netty是一個高效能,高可擴充套件性的非同步事件驅動的網路應用程式框架,它極大的簡化了TCP和UDP客戶端和伺服

java網路程式設計常用的類

java網路程式設計中常用的類 1、InetAddress 用於封裝計算機的IP地址和DNS(Domain Name System域名系統)(沒有埠資訊) InetAddress沒有構造器,要得到物件只能通過靜態方法實現 /** * 使用getLocalHost的方法建立InetA

JAVA 網路程式設計(6) Netty TCP 示例

maven使用的netty版本如下: <dependency> <groupId>io.netty</groupId> <artifactId>netty-all</artifactId> &

Java網路程式設計】:Netty實現OIO和NIO

承接上文:https://blog.csdn.net/hxcaifly/article/details/85274664 前言 單純地使用Java JDK來實現網路NIO是一件開發成本非常高的事情。然而,Netty 為它所有的傳輸實現提供了一個通用API,這使得這種

JAVA 網路程式設計(7) Netty 處理Http協議 示例

maven中使用netty的版本為: <dependency> <groupId>io.netty</groupId> <artifactId>netty-all</artifactId> &

Java網路程式設計Netty拆包和黏包-yellowcong

Netty中,解決拆包和黏包中,解決方式有三種 1、在每個包尾部,定義分隔符,通過回車符號,或者其他符號來解決 2、通過定義每個包的大小,如果包不夠就空格填充 3、自定義協議的方式,將訊息分為訊息頭和訊息體,在訊息頭中表示出訊息的總長度,

java網路程式設計Netty實戰資料通訊(七)

Netty最佳實戰資料通訊 1 分析       我們需要了解下在真正專案應用中如何去考虛Netty的使用,大體上對於一引數設定都是根據伺服器效能決定的。這個不是最主要的。       我們要考慮的問題是兩臺機器(甚至多臺)使用Netty的怎樣進行通訊,我

Java 網路程式設計 Java網路程式設計

說道網路程式設計,瞭解socket程式設計,分為TCP和UPD,對於具體實現細節,就不知道。希望學完這一塊,自己能夠獨立完成一個socket的編寫。  關於網際網路WEB相關的知識點,後面開始總結,今天不在此作介紹。 Socket套接字:網路上具有唯一標識的IP地址和埠組合在一起才能構成唯一能識

java網路程式設計Netty流資料的傳輸處理(五)

Netty流資料的傳輸處理 Socket Buffer的缺陷       對於例如TCP/IP這種基於流的傳輸協議實現,接收到的資料會被儲存在socket的接受緩衝區內。不幸的是,這種基於流的傳輸緩衝區並不是一個包佇列,而是一個位元組佇列。這意味著,即使

Java網路程式設計與NIO詳解4:淺析NIO包的Buffer、Channel 和 Selector

Java NIO:Buffer、Channel 和 Selector轉自https://www.javadoop.com/post/nio-and-aio本文將介紹 Java NIO 中三大元件 Buffer、Channel、Selector 的使用。本來要一起介紹非阻塞 I

java網路程式設計—NIO與Netty(一)

java BIO 流 流是一個連續的寫入\讀取 的資料流。將網路、硬碟、記憶體中的資料寫入程式中稱為InputStream,方向相反輸出則稱為OutputStream 顯然,流具有方向性! InputStream 對於java IO包的

java網路程式設計實現伺服器和客戶端一對一的聊天

如果有多個客戶端接入,都可以傳送訊息給伺服器,但伺服器只和最後一個客戶聊天。,如果要實現群聊的話,只要把所有的socket儲存到集合中,有客戶輸入時遍歷socket得到輸出流並把訊息廣播給各個客戶端就行了。 四個讀寫的執行緒類都是一樣的,可以進行封裝,這裡就不封裝了。 Se

java網路程式設計_IO模型

理解java的BIO、NIO、AIO的原理: 一、UNIX程式設計中的五種IO模型: 1. 阻塞IO 外賣小哥去商家取外賣,到了麻辣燙店,商家還沒做好, 外賣小哥雖然還有其他單子要送,但是不得不焦急地等著商家; 2. 非阻塞IO 外賣小哥去商家取外賣

Java網路程式設計基礎部分

轉載:文章來源 網路通訊協議 網路通訊協議有很多種,目前應用最廣泛的是TCP/IP協議(Transmission Control Protocal/Internet Protoal傳輸控制協議/英特網互聯協議),它是一個包括TCP協議和IP協議,UDP(User Datagram Protoco

20180827-Java網路程式設計

  Java 網路程式設計 網路程式設計是指編寫執行在多個裝置(計算機)的程式,這些裝置都通過網路連線起來。 java.net包中J2SE的API包含有類和介面,它們提供低層次的通訊細節。你可以直接使用這些類和介面,來專注於解決問題,而不用關注通訊細節。 java.net包中提供了兩種常見的

Java網路程式設計的基本網路概念

  前言 自己網路這方面的知識很是薄弱,每次面試被問到這部分都會卡殼,所以很尷尬,然後最近也是有些時間了,就趕緊把自己的不足補充一下。雖然最近也在看設計模式,但是總看設計模式也容易煩,所以就並行學習,看看設計模式,然後再看看這網路程式設計。 網路 首先熟悉一下, 什麼是網路,網路是幾乎可以實

java 網路程式設計——TCP 的三次握手和四次揮手

文章目錄 TCP報頭 三次握手 未連線佇列 四次揮手 狀態詳解 在TCP/IP協議中,TCP協議提供可靠的連線服務,採用三次握手建立一個連線. TCP報頭 埠號:用來標識

深入Java網路程式設計與NIO(二)

Java NIO 與 Netty NIO NIO的特性/NIO與IO區別: 1)IO是面向流的,NIO是面向緩衝區的; 2)IO流是阻塞的,NIO流是不阻塞的; 3)NIO有選擇器,而IO沒有。 讀資料和寫資料方式: 從通道進行資料讀取 :建立一個緩衝區,然後請求通道讀取資料。