Netty_ByteBuf的基本用法(一)

Nettys buffer API has two interfaces: 

  • ByteBuf 

  • ByteBufHolder

ByteBuf - The byte data container

Whenever(每当)  you  need  to  interact(相互作用)  with  a  remote  peer  such  as  a  database,  the  communication needs to be done in bytes. For this and other reasons an efficient(高效), convenient, and easy-to-use data structure  is required, and Netty's ByteBuf implementation  meets these requirements and more, making it an ideal data container, optimized(最佳的) for holding and interacting with bytes. ByteBufis a data container that allows you to add/get bytes from it in an efficient way. To make it easier to operate, it uses two indices: one for reading and one for writing. This allows you to read data out of them in a sequential way and "jump" back to read it again. All you need to do is adjust(调整) the reader index and start the read operation again.


How it works

After  something  is  written  to  the ByteBuf, its writerIndex is  increased  by  the  amount  of bytes written. After you start to read bytes, its readerIndexis increased. You can read bytes until  the writerIndex and readerIndex are  at  the  same position.  The  ByteBuf then becomes  unreadable,  so  the  next  read  request  triggers(触发) an IndexOutOfBoundsException similar to what youve seen when trying to read beyond the capacity of an array. Calling any of the buffers methods beginning with "read" or "write" automatically(自动的) advances the  reader  and  writer  indexes  or  you. There  are  also  relative  operations  to set  and  get bytes. These dont move the indexes but operate on the relative(相对的) index that was given. A ByteBuf may  have  a maximum  capacity(容量)  to  set  an  upper  limit(上限)  to  the  maximum  data  it can hold, trying to move the writer index beyond this capacity will result in an exception. The default limit is Integer.MAX_VALUE. 

Figure 5.2 shows how a ByteBufis laid out. 

 Netty_ByteBuf的基本用法(一)_第1张图片

As  Figure  5.1  shows,  a ByteBuf is  similar  to  a  byte  array,  the  most  notable(显著的)  difference  being the  addition  of  the read  and  write  indices  which  can  be used  to control  access  to  the  buffer's data. Youll  learn  more  about  the  operations  that can  be  performed  on  a ByteBuf in  a  later section. For now, keep this in mind and lets review the different types of ByteBufthat youll most likely use. 


Different types of ByteBuf

There are three different types of ByteBuf youll encounter when using Netty (there are more, but these are used internally). You may end up implementing your own, but this is out of scope here. Lets look at the provided types that you are most likely interested in. 

HEAP BUFFERS

The  most  used type is the ByteBuf that stores  its data  in the heap space(堆内存) of the JVM.  This  is done  by  storing  it  in a  backing  array.  This  type  is  fast  to  allocate  and  also  de-allocate  when you're  not  using  a  pool.  It  also  offers  a  way  to directly  access  the  backing  array,  which  may make it easier to interact with legacy(遗留的) code. 

DIRECT BUFFERS

Another ByteBuf implementation  is  the  direct  one.Direct  means  that  it  allocates  the memory  directly,  which  is  outside  the heap. You won't  see  its memory  usage  in  your  heap space. You must take this into account when calculating the maximum amount of memory your application will use and how to limit it, as the max heap size won't be enough. Direct buffers on the  other side  are  optimal(最佳的,最优的) when  its  time  to transfer  data  over  a  socket. In  fact,  if  you  use a nondirect  buffer,  the  JVM will  make  a copy  of  your  buffer  to  a  direct  buffer internally(实质上)  before sending it over the socket. The  down  side  of  direct buffers is  that they're  more expensive  to  allocate(分配)  and  de-allocate compared to heap buffers. This is one of the reasons why Netty supports pooling, which makes this problem disappear. Another possible down side can be that you're no longer able to access the data  via the  backing  array,  so  you'll  need  to  make  a copy  of  the  data  if  it  needs  to  work with legacy code that requires this. The following listing shows how you can get the data in an array and call your method even without the ability to access the backing array directly. 

COMPOSITE BUFFERS

The  last ByteBuf implementation  you  may  be  confronted(面对的)  with  is  the  CompositeByteBuf. This  does  exactly what its  name  says;  it  allows  you  to  compose different ByteBuf instances and provides a view over them. The good thing is you can also add and remove them on-the-fly(在传输过程中), so its kind of like a List. If youve ever worked with the JDK's ByteBuffer you've most likely missed such a feature there. As the CompositeByteBufis just a view over others, the hasArray() method  will  return false  because  it may  contain  several  ByteBuf instances  of both direct and nondirect types. For  example,  a  message  could  be  composed  of  two parts:  header and  body.  In  a modularized application, the two parts could be produced by different modules and assembled later when  the  message  is  sent  out.  Also,  you may  use  the  same  body  all  the  time  and  just change the header. So it would make sense here to not allocate a new buffer every time. This  would  be  a  perfect fit  for  a CompositeByteBuf as  no  memory  copy  will be  needed and the same API could be used as with non-composite buffers. 


Figure  5.2  shows  how  a CompositeByteBuf would  be  used  to  compose(组成)  the  header  and body.

Netty_ByteBuf的基本用法(一)_第2张图片

======END======

你可能感兴趣的:(Netty_ByteBuf的基本用法(一))