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

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

Netty ByteBuf 傳輸載體

1. 前言

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

2. 學(xué)習(xí)目的

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

3. ByteBuf 結(jié)構(gòu)

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

圖片描述

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

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

4. 核心 API

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

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

5. 核心 API 詳解

5.1 capatiy()

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

實(shí)例:

ByteBuf byteBuf=Unpooled.buffer(10);

5.2 maxCapacity()

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

實(shí)例:

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

5.3 readalbeBytes()

表示 ByteBuf 當(dāng)前可讀的字節(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 當(dāng)前可寫的字節(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ù)寫不進(jìn)去的話,Netty 會(huì)自動(dòng)擴(kuò)容 ByteBuf,直到擴(kuò)容到底層的內(nèi)存大小為 maxCapacity,而 maxWritableBytes () 就表示可寫的最大字節(jié)數(shù),它的值等于 maxCapacity-writerIndex。

源碼:

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

5.8 readerIndex()

readerIndex () 表示返回當(dāng)前的讀指針 readerIndex,ByteBuf 會(huì)維護(hù)一個(gè)變量 readerIndex。

源碼:

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

5.9 readerIndex(int)

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

源碼:

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 () 表示返回當(dāng)前的寫指針 writerIndex。

源碼:

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

5.11 writeIndex(int)

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

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 () 表示把當(dāng)前的讀指針保存起來,其實(shí)類似數(shù)據(jù)庫事務(wù)的當(dāng)前狀態(tài)標(biāo)記。

源碼:

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

5.13 resetReaderIndex()

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

源碼:

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

5.14 markWriterIndex()

表示把當(dāng)前的寫指針保存起來。

源碼:

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),表示一次寫入一個(gè)字節(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),表示寫入一個(gè)字節(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 (),表示一次讀取一個(gè)字節(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);//往目標(biāo)dst里面寫數(shù)據(jù)
    this.readerIndex += length;//指針增加
    return this;
}

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

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

6. 小結(jié)

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

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