Netty-字节缓冲区ByteBuf

Netty 的 ByteBuffer 替代品是 ByteBuf,一个强大的实现,既解决了 JDK API 的局限性,又为网络应用程序的开发者提供了更好的 API。

1、ByteBuf与ByteBuffer的对比

ByteBuffer的缺点: 
(1)ByteBuffer的字节数组是被定义成final的,也就是长度固定。一旦分配完成就不能扩容和收缩,灵活性低,而且当待存储的对象字节很大可能出现数组越界,用户使用起来稍不小心就可能出现异常。

9a04c9393698ea63a0890ff4b7a06606c81.jpg

(2)ByteBuffer只用了一个position指针来标识位置,读写模式切换时需要调用flip()函数和rewind()函数,使用起来需要非常小心,不然很容易出错误。

ByteBuf的优点: 
(1)ByteBuf是吸取ByteBuffer的缺点之后重新设计,存储字节的数组是动态的,最大是Integer.MAX_VALUE。这里的动态性存在write操作中,write时得知buffer不够时,会自动扩容。

(2) ByteBuf的读写索引分离,使用起来十分方便。此外ByteBuf还新增了很多方便实用的功能。

 

2、ByteBuf的结构

ef9befb90386f01f46b10befa393024875e.jpg

ByteBuf通过两个指针协助读写操作,读操作使用readerIndex,写操作使用writerIndex。

readerIndex、writerIndex初始值是0,写入数据时writerIndex增加,读取数据时readerIndex增加,但是readerIndex不会超过writerIndex。

读取之后,0-readerIndex之间的空间视为discard的,调用discardReadByte方法可以释放这一部分空间,作用类似于ByteBuffer的compact方法。

readerIndex-writerIndex之间的数据是可读的,等价于ByteBuffer中position~limit之间的数据。

writerIndex-capacity之间的空间是可写的,等价于ByteBuffer中limit~capacity之间的空间。

读只影响readerIndex、写只影响writerIndex,读写之间不需要调整指针位置,所以相较于NIO的ByteBuffer,可以极大的简化读写操作。

 

3、ByteBuf 分配

Netty 提供了一个简单的称为Unpooled 的工具类,它提供了静态的辅助方法来创建未池化的ByteBuf实例。

784f67fa8057dd4a9352ed83ed54a08c7ab.jpg

4、示例程序

    @Test
    public void test(){
        ByteBuf byteBuf = Unpooled.buffer(32);
        System.out.println(String.format("初始状态 readerIndex:%s,writerIndex:%s,capacity:%s",
                byteBuf.readerIndex(),byteBuf.writerIndex(),byteBuf.capacity()));
        byteBuf.writeBytes("hello".getBytes());
        System.out.println(String.format("写入hello readerIndex:%s,writerIndex:%s,capacity:%s",
                byteBuf.readerIndex(),byteBuf.writerIndex(),byteBuf.capacity()));

        ByteBuf helloBuf = Unpooled.buffer(5);
        //读取到helloBuf中
        byteBuf.readBytes(helloBuf);
        //将helloBuf中所有的字节转为字符串
        System.out.println("读取到的数据:"+helloBuf.toString(CharsetUtil.UTF_8));
        System.out.println(String.format("读取hello后 readerIndex:%s,writerIndex:%s,capacity:%s",
                byteBuf.readerIndex(),byteBuf.writerIndex(),byteBuf.capacity()));

        //再次写入
        byteBuf.writeBytes("abcdef".getBytes());
        System.out.println(String.format("写入abcdef后 readerIndex:%s,writerIndex:%s,capacity:%s",
                byteBuf.readerIndex(),byteBuf.writerIndex(),byteBuf.capacity()));

        //丢弃之前读过的字节
        byteBuf.discardReadBytes();
        System.out.println(String.format("discardReadBytes后 readerIndex:%s,writerIndex:%s,capacity:%s",
                byteBuf.readerIndex(),byteBuf.writerIndex(),byteBuf.capacity()));

        //清空缓存区
        byteBuf.clear();
        System.out.println(String.format("clear readerIndex:%s,writerIndex:%s,capacity:%s",
                byteBuf.readerIndex(),byteBuf.writerIndex(),byteBuf.capacity()));
    }

 

da6b1637b6ad32015812e4f295dbf83b999.jpg

分析

1、写入hello后

a58ad29adc3fe09b3d8b3c2581b9384b104.jpg

2、读取hello的数据后

68b234714643d8ab45f70dd125d544561ff.jpg

3、再次写入abcdef

bb9b9c1e90c3ef8f1c45c02bdb9a196f5a1.jpg

4、丢弃到已读过的字节hello

a1739fd7aef1917ee592ce624d3ae69ad61.jpg

5、clear后清空缓冲区

01176a355d5bf738fa2f3937ad81ba55199.jpg

 

ByteBuf的相关api介绍:

a1c9349858c4de639dd2cc3588e1c19e891.jpg

ea7bcc905e55191777f195924f9b29a5798.jpg

 

302fce0d0ead10b2031699acf6b23162e71.jpg

 

e98681537d9edd88e0f70420448e6e4384f.jpg

4893f64e6c371a5d3c13aa32fc337a428f6.jpg

b6a61392ece9f81fcb78d329f0e24c1bcdf.jpg

更多api的使用可以查看ByteBuf提供的相关方法或者netty的文档。

 

转载于:https://my.oschina.net/suzheworld/blog/3007077

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值