第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

首頁 慕課教程 Netty 教程 Netty 教程 Netty ByteBuf傳輸載體

Netty ByteBuf 傳輸載體

1. 前言

在 Netty 里面的數(shù)據(jù)讀寫是以 ByteBuf 為單位進行交互的,ByteBuf 是一個字節(jié)容器,如果了解過 NIO 的同學應該知道,在 NIO 里面也有類型的數(shù)據(jù)載體 ByteBuffer。

2. 學習目的

熟悉掌握 ByteBuf 的原理及 API,則可以自定義通信協(xié)議,并且使用 ByteBuf、序列化等技術實現(xiàn)通信協(xié)議,并且有效解決拆包和粘包問題(后面章節(jié)會詳細分析)。

3. ByteBuf 結構

ByteBuff 的結構主要由四個部分組成,廢棄字節(jié)、可讀字節(jié)、可寫字節(jié)、可擴容字節(jié),具體結構圖如下所示:

圖片描述

通過以上的結構圖,我們可以看出它其實就是一個數(shù)組,在寫數(shù)據(jù)和讀數(shù)據(jù)的時候分別維護兩個指針的移動,分別是 readerIndex 和 writerIndex,在 readerIndex 和 writerIndex 之間的數(shù)據(jù)是有效可讀數(shù)據(jù)。具體分析如下所示:

  1. ByteBuf 的四個核心屬性,分別是 readerIndex(可讀指針位置)、writerIndex(可寫指針位置)、capacity(初始化容量值)、maxCapacity(最大容量值)。其中 readerIndex 和 writerIndex 之間的數(shù)據(jù)是 ByteBuf 的主體數(shù)據(jù);
  2. 讀取數(shù)據(jù)的時候,readerIndex 遞增,一旦 readerIndex 等于 writerIndex 則表示該容器沒有數(shù)據(jù)可讀了。writerIndex-readerIndex 表示有效可讀數(shù)據(jù)的長度;
  3. 寫數(shù)據(jù)的時候,writerIndex 遞增,一旦 writerIndex 等于 capacity 表示容器已經(jīng)滿了,ByteBuf 不能再寫數(shù)據(jù)了,capacity-writerIndex 表示容器還可以寫入的數(shù)據(jù)長度;
  4. 當向 ByteBuf 寫數(shù)據(jù)的時候,如果容量不足,那么這個時候可以進行擴容,直到 capacity 擴容到 maxCapacity,超過 maxCapacity 就會報錯;
  5. 總結,readerIndex<=writerIndex<=capacity<=maxCapacity。

4. 核心 API

方法 描述
capacity() 容量
maxCapacity() 最大容量(當容量最大時,還可以擴容)
readableBytes() 可讀字節(jié)數(shù)
isReadable() 是否可讀
writableBytes() 可寫字節(jié)數(shù)
isWritable() 是否可寫
maxWritableBytes() 最大可寫字節(jié)數(shù)
readerIndex() 讀指針
readerIndex(int) 重置讀指針為某個位置
writerIndex() 寫指針
writeIndex(int) 重置寫指針為某個位置
markReaderIndex() 保存當前讀指針
resetReaderIndex() 回歸之前保存的讀指針
markWriterIndex() 保存當前寫指針
resetWriterIndex 回歸之前保存的寫指針
writeByte(int i) 寫一個字節(jié)
writeBytes(byte[] bytes) 寫一個字節(jié)數(shù)組
readByte() 讀一個字節(jié)
readByte(byte[] bytes) 讀一個字節(jié)數(shù)組(并往參數(shù) bytes 里存放)

以上是 ByteBuf 的核心的 API,很多時候,在編程的時候直接操作 ByteBuf 可能會相對的繁瑣,所以不會直接手工調用這些 API,而是通過封裝編碼和解碼器的方式進行使用,但是編碼、解碼底層就是通過 ByteBuf 去實現(xiàn)的。

5. 核心 API 詳解

5.1 capatiy()

表示 ByteBuf 可以寫入多少個字節(jié),一般在初始化 ByteBuf 時就會指定。

實例:

ByteBuf byteBuf=Unpooled.buffer(10);

5.2 maxCapacity()

表示 ByteBuf 最大可以支持多少字節(jié),如果當 writerIndex=capacity 時,會判斷 capacity 是否等于 maxCapacity,如果小于則擴容。

實例:

//參數(shù)1,容量值
//參數(shù)2,最大容量值
ByteBuf byteBuf = Unpooled.buffer(10,20);

5.3 readalbeBytes()

表示 ByteBuf 當前可讀的字節(jié)數(shù),它的值等于 writerIndex-readerIndex。

源碼:

public int readableBytes() {
    return this.writerIndex - this.readerIndex;
}

5.4 isReadable()

如果 writerIndex 和 readerIndex 相等,則不可讀,isReadable () 方法返回 false。

源碼:

public boolean isReadable(int numBytes) {
    return this.writerIndex - this.readerIndex >= numBytes;
}

5.5 writableBytes()

表示 ByteBuf 當前可寫的字節(jié)數(shù),它的值等于 capacity-writerIndex。

源碼:

public int writableBytes() {
    return this.capacity() - this.writerIndex;
}

5.6 isWritable()

如果 capacity 和 writerIndex 相等,則表示不可寫,isWritable () 返回 false。

源碼:

public boolean isWritable() {
    return this.capacity() > this.writerIndex;
}

5.7 maxWritableBytes()

capacity 和 writerIndex 相等,并不代表不能繼續(xù)往 ByteBuf 寫數(shù)據(jù)了。如果發(fā)現(xiàn)往 ByteBuf 中寫數(shù)據(jù)寫不進去的話,Netty 會自動擴容 ByteBuf,直到擴容到底層的內存大小為 maxCapacity,而 maxWritableBytes () 就表示可寫的最大字節(jié)數(shù),它的值等于 maxCapacity-writerIndex。

源碼:

public int maxWritableBytes() {
    return this.maxCapacity() - this.writerIndex;
}

5.8 readerIndex()

readerIndex () 表示返回當前的讀指針 readerIndex,ByteBuf 會維護一個變量 readerIndex。

源碼:

int readerIndex;
public int readerIndex() {
    return this.readerIndex;
}

5.9 readerIndex(int)

readerIndex (int) 表示設置讀指針,比如說可以回滾到某個指針位置。

源碼:

public ByteBuf readerIndex(int readerIndex) {
        if (readerIndex >= 0 && readerIndex <= this.writerIndex) {
            //給readerIndex賦值
            this.readerIndex = readerIndex;
            return this;
        } else {
            throw new IndexOutOfBoundsException("....");
        }
    }

5.10 writeIndex()

writeIndex () 表示返回當前的寫指針 writerIndex。

源碼:

public int writerIndex() {
    return this.writerIndex;
}

5.11 writeIndex(int)

writeIndex (int) 表示設置寫指針,比如說可以回滾到某個指針位置。

public ByteBuf writerIndex(int writerIndex) {
        if (writerIndex >= this.readerIndex && writerIndex <= this.capacity()) {
            //給writerIndex賦值
            this.writerIndex = writerIndex;
            return this;
        } else {
            throw new IndexOutOfBoundsException("...");
        }
    }

5.12 markReaderIndex()

markReaderIndex () 表示把當前的讀指針保存起來,其實類似數(shù)據(jù)庫事務的當前狀態(tài)標記。

源碼:

public ByteBuf markReaderIndex() {
    //使用markedReaderIndex保存當前讀指針
    this.markedReaderIndex = this.readerIndex;
    return this;
}

5.13 resetReaderIndex()

resetReaderIndex () 表示把當前的讀指針恢復到之前保存的值,類似數(shù)據(jù)庫事務回歸到某個狀態(tài)。

源碼:

public ByteBuf resetReaderIndex() {
    this.readerIndex(this.markedReaderIndex);
    return this;
}

5.14 markWriterIndex()

表示把當前的寫指針保存起來。

源碼:

public ByteBuf markWriterIndex() {
    this.markedWriterIndex = this.writerIndex;
    return this;
}

5.15 resetWriterIndex()

切塊之前保存的寫指針 writerIndex。

源碼:

public ByteBuf resetWriterIndex() {
    this.writerIndex = this.markedWriterIndex;
    return this;
}

5.16 writeByte(byte b)

writeByte (byte b),表示一次寫入一個字節(jié),writerIndex++。

源碼:

public ByteBuf writeByte(int value) {
    this.ensureAccessible();
    this.ensureWritable0(1);
    
    //writerIndex指針自增
    this._setByte(this.writerIndex++, value);
    return this;
}

5.17 writeBytes(byte[] src)

writeBytes (byte [] src),表示寫入一個字節(jié)數(shù)組,writerIndex=writerIndex+src.length。

源碼:

public ByteBuf writeBytes(byte[] src) {
    this.writeBytes((byte[])src, 0, src.length);
    return this;
}

public ByteBuf writeBytes(byte[] src, int srcIndex, int length) {
    this.ensureAccessible();
    this.ensureWritable(length);
    this.setBytes(this.writerIndex, src, srcIndex, length);
    this.writerIndex += length; //writerIndex指針增加
    return this;
}

5.18 readByte()

readByte (),表示一次讀取一個字節(jié),readerIndex++。

源碼:

public byte readByte() {
    this.checkReadableBytes0(1);
    int i = this.readerIndex;
    byte b = this._getByte(i);//讀取數(shù)據(jù)
    this.readerIndex = i + 1; //指針自增
    return b;
}

5.19 readBytes(byte[] dst)

readBytes (byte [] dst),表示把 ByteBuf 里面的數(shù)據(jù)讀取到 dst,readerIndex=readerIndex+dst.length。

源碼:

public ByteBuf readBytes(byte[] dst) {
    this.readBytes((byte[])dst, 0, dst.length);
    return this;
}

public ByteBuf readBytes(byte[] dst, int dstIndex, int length) {
    this.checkReadableBytes(length);
    this.getBytes(this.readerIndex, dst, dstIndex, length);//往目標dst里面寫數(shù)據(jù)
    this.readerIndex += length;//指針增加
    return this;
}

讀寫 API 類似的 API 還有 getBytes、getByte () 與 setBytes ()、setByte () 系列

區(qū)別就是 get/set 不會改變讀寫指針,而 read/write 會改變讀寫指針,這點在解析數(shù)據(jù)的時候千萬要注意。

6. 小結

本節(jié)內容主要講解了 ByteBuf,需要掌握的內容如下:

  1. 理解并且牢記 ByteBuf 結構圖;
  2. 基于讀寫指針、容量、最大可擴容容量,衍生出一系列的讀寫方法,要注意 read/write 與 get/set 的區(qū)別;