搞懂Netty(二)- ByteBuf

本文介绍了Netty中的ByteBuf,它是对JavaNIOByteBuffer的增强,支持更丰富的功能如动态扩容、零拷贝传输和自定义buffer类型。文章还讨论了数据包拆分和合并的高效处理方式,展示了Netty在网络程序开发中的优势。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

数据的载体

在这里插入图片描述

在这里插入图片描述

这一篇,我们将学习Netty提供提供的核心功能以及它如何基于此构建出的完整的网络程序开发栈。要牢记上面这幅图。

1. Rich Byte Buffer

如果直接翻译过来就是富字节数组,你如果觉得这个名字很陌生,应该听过html叫做富文本吧。那么html为什么叫做富文本呢?
这个富字节数组Netty中是有专门的抽象表示的,叫ByteBuf。它是Java NIO中的ByteBuffer的升级版。所以它叫Rich Byte Buffer。下面,我们先来看一看Java NIO中的ByteBuffer

1.1 ByteBuffer

我们知道在IO程序中,如果一堆数据一个一个传输效率太低了,把它们集中起来一起传输效率会提高很多,所以应该用一种数据结构承载这些数据。很容易想到数组,再通用一些,就是字节数组Byte Array。那么Java NIO为什么又弄出来个ByteBuffer呢。这再一次体现了Java的一切接对象的设计哲学。把原生Byte Array这种面向过程的数据结构,抽象出来成为面向对象的ByteBuffer。就可以往里面加入许多功能,把一些buffer相关的操作以及操作后的状态聚合在一起,需要替换另外一个缓存技术时,整体直接替换。这不就是高内聚,低耦合的设计原则吗。那么这种抽象的数据结构长什么样子呢?
ByteBuffer里面,定义了4个属性,记录各种操作后的状态,比如在写日志文件时,第一次写完,第二次要接着第一次写,内部要有指针指向第一次结束的位置,要不然每次都从开头写,日志只有最新的记录,那日志就没有意义了。
在这里插入图片描述

  • Capacity: Buffer 可以承载的最大数据量
  • Limit: 读写的界限
  • Position: 当前读写到的位置
  • Mark: 可选地,可以记录一个位置,Position 以后可以恢复到这个位置
    详细的用法参考ByteBuffer官方文档
    那么这个对比普通的字节数据有什么好处呢?
  1. 支持比较
    它既然抽象出来成为类,所以它可以重写equals方法,自然就可以支持比较了。
  2. 任意字节顺序(大端和小段)
    ByteBuffer允许你以任意的字节顺序读写数据,像大端和小端。网络中的字节顺序就是大端。
  3. 读写有类型的数据
    ByteBuffer提供了可以直接读写指定类型数据的方法。例如putInt()putDoublegetInt()等。
  4. 动态扩容
    ByteBuffer在创建之后,不行传统数组,容量就固定了,还可以扩容。
  5. 线程安全
    ByteBuffer提供了线程安全的操作方法。
  6. 可以访问堆外内存
    java程序是运行在JVM上的,JVM也是一个程序,它运行时用的空间是向操作系统申请的,java程序运行时用的空间一般都是是向JVM申请的,受JVM控制的。有一般就有特殊,java程序可以直接向操作系统申请空间,从而对该空间的利用不收JVN的管理。当然,这样的话,这块内存的回收应该就只能由程序员自己管理了,否则就会导致内存泄露。

1.2 ByteBuf

Netty使用它自己的ByteBuffer-ByteBuf,而不用Java NIO的ByteBuffer,因为它更具优势。

  • 你可以根据需要定义自己的buffer类型
  • 可以实现零拷贝传输
  • 它可以动态扩容
  • 不再需要调用flip()
  • 它比ByteBuffer速度快
    更多的信息参考netty api doc
1.2.1 包的拆分和合并

在网络通信层之间,数据要进行包的拆分和合并。例如,如果到来的数据是被分成多个包的话,使用前,需要合并数据包。传统的方式,是先创建一个新的buffer,然后把每个buffer的数据拷贝到新的buffer中。
Netty支持零拷贝,它内部用指针指向需要拷贝的数据,从而避免拷贝数据。

requestPart1 = buffer1.slice(OFFSET_PAYLOAD, buffer1.readableBytes() - OFFSET_PAYLOAD);
requestPart2 = buffer2.slice(OFFSET_PAYLOAD, buffer2.readableBytes() - OFFSET_PAYLOAD);
request = unpooled.wrappedBuffer(requestPart1, requestPart2);

在这里插入图片描述

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值