netty研究四ByteBuf

天行健,君子以自強不息。

Java NIO 提供了ByteBuffer 作爲它的字節容器,但是這個類使⽤起來過於複雜,⽽且也有些繁瑣。Netty 的 ByteBuffer 替代品是 ByteBuf,⼀個強⼤的實現,既解決了JDK API 的侷限性,⼜爲⽹絡應⽤程序的開發者提供了更好的API。

從結構上來說,ByteBuf 由⼀串字節數組構成。數組中每個字節⽤來存放信息。

ByteBuf 提供了兩個索引,⼀個⽤於讀取數據,⼀個⽤於寫⼊數據。這兩個索引通過在字節數組中移動,來定位需要讀或者寫信息的位置。

當從 ByteBuf 讀取時,它的 readerIndex(讀索引)將會根據讀取的字節數遞增。

同樣,當寫 ByteBuf 時,它的 writerIndex(寫索引)也會根據寫⼊的字節數進⾏遞增。

如果 readerIndex 超過了 writerIndex 的時候,Netty 會拋出 IndexOutOf-BoundsException 異常。

ByteBuf的讀取操作

package cn.lyy.myrcp.server.cn.lyy.test;

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

public class ByteBufTest01 {
    public static void main(String[] args) {
        ByteBuf byteBuf = Unpooled.copiedBuffer("hello liuyuanyuan,hello World", CharsetUtil.UTF_8);
        System.out.println("byteBuf的容量爲: "+byteBuf.capacity());
        System.out.println("byteBuf的可讀容量爲: "+ byteBuf.readableBytes());
        System.out.println("byteBuf的可寫容量爲: "+byteBuf.writableBytes());

        //方法一內部通過移動readIndex進行讀取
        while(byteBuf.isReadable()){
            System.out.print((char) byteBuf.readByte());
        }


    }
}

 

其他2種讀取方法

package cn.lyy.myrcp.server.cn.lyy.test;

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

public class ByteBufTest01 {
    public static void main(String[] args) {
        ByteBuf byteBuf = Unpooled.copiedBuffer("hello liuyuanyuan,hello World", CharsetUtil.UTF_8);
        System.out.println("byteBuf的容量爲: "+byteBuf.capacity());
        System.out.println("byteBuf的可讀容量爲: "+ byteBuf.readableBytes());
        System.out.println("byteBuf的可寫容量爲: "+byteBuf.writableBytes());

        /*//方法一內部通過移動readIndex進行讀取
        while(byteBuf.isReadable()){
            System.out.print((char) byteBuf.readByte());
        }*/

        /*//:通過下標直接讀取
        for (int i=0; i< byteBuf.readableBytes() ; i++ ) {
                 System.out.print((char)byteBuf.getByte(i));
             }*/
        // 法三:轉化爲byte[]讀取
         byte[] bytes = byteBuf.array();
         for (byte b : bytes) {
             System.out.print((char)b);
        }

    }
}

寫入操作

package cn.lyy.myrcp.server.cn.lyy.test;

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

public class ByteBufTest02 {
    public static void main(String[] args) {
        //構造空的字節緩衝區,初始⼤⼩10,最20
        ByteBuf byteBuf= Unpooled.buffer(10,20);
        System.out.println("byteBuf的容量爲:"+byteBuf.capacity());
        System.out.println("byteBuf的可讀容量爲:"+byteBuf.readableBytes());
        System.out.println("byteBuf的可寫容量爲:"+byteBuf.writableBytes());
        for (int i=0; i<5; i++) {
            byteBuf.writeInt(i); //int類型,int4個字節
        }
        System.out.println("ok");
        System.out.println("byteBuf的容量爲:"+byteBuf.capacity());
        System.out.println("byteBuf的可讀容量爲:"+byteBuf.readableBytes());
        System.out.println("byteBuf的可寫容量爲:"+byteBuf.writableBytes());
        while (byteBuf.isReadable()) {
            System.out.print(byteBuf.readInt());
        }
    }
}

⼊站處理流程中,如果對原消息不做處理,調⽤ ctx.fireChannelRead(msg) 把原消息往下傳,由流⽔線最後⼀棒 TailHandler 完成⾃動釋放。

如果截斷了⼊站處理流⽔線,則可以繼承 SimpleChannelInboundHandler ,完成⼊站ByteBuf ⾃動釋放。出站處理過程中,申請分配到的 ByteBuf,通過 HeadHandler 完成⾃動釋放。

⼊站處理中,如果將原消息轉化爲新的消息並調⽤ ctx.fireChannelRead(newMsg)往下傳,那必須 把原消息release掉;

⼊站處理中,如果已經不再調⽤ ctx.fireChannelRead(msg) 傳遞任何消息,也沒有繼承SimpleChannelInboundHandler 完成⾃動釋放,那更要把原消息release掉;

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章