Введение
Класс, используемый для переноса информации и связи в netty, называется ByteBuf. Из названия видно, что это буферная область Byte. Итак, каковы характеристики ByteBuf? Посмотри.
Подробное объяснение ByteBuf
Netty предоставляет пакет io.netty.buffer, который определяет различные типы ByteBuf и производные от них типы.
Buffer является базовым классом Netty ByteBuf, который является абстрактным классом, другие классы Buffer в основном получены производным классом, класс также определяет общий тон Netty Buffer.
Давайте сначала посмотрим на определение ByteBuf:
public abstract class ByteBuf implements ReferenceCounted, Comparable<ByteBuf> {
ByteBuf реализует два интерфейса: ReferenceCounted и Comparable. Comparable — это интерфейс, поставляемый с JDK, что означает, что классы можно сравнивать. А ReferenceCounted представляет ссылочную статистику объекта. Когда создается экземпляр ReferenceCounted, его счетчик ссылок = 1. Каждый раз, когда вызывается метод keep(), счетчик будет увеличиваться, а метод release() будет вызываться для уменьшения счетчика. Когда счетчик уменьшится до 0, объект будет освобожден.Если вы попытаетесь получить доступ к освобожденному объекту, будет сообщено об исключении доступа.
Если объект реализует ReferenceCounted, а другие объекты, содержащиеся в этом объекте, также реализуют ReferenceCounted, то, когда count объекта-контейнера = 0, другие объекты внутри него также будут освобождены путем вызова метода release().
Таким образом, ByteBuf — это сопоставимый объект, который может подсчитывать количество ссылок. Он обеспечивает механизм последовательного или случайного доступа к байтам.
Обратите внимание, что хотя JDK имеет свой собственный класс ByteBuffer, ByteBuf в netty является повторной реализацией Byte Buffer. Они не связаны.
Создать усиление
ByTeBuf - это абстрактный класс и не может быть прямо создан напрямую. Хотя подкласс bytebuf может быть использован для создания института, Netty не рекомендует его. Netty рекомендует использовать io.netty.buffer.unpolled для создания баффов. Ungaleded - это класс инструмента, который может выделять пространство, копирование или инкапсулировать операции для BYTEBUF.
Вот пример создания нескольких разных ByteBuf:
import static io.netty.buffer.Unpooled.*;
ByteBuf heapBuffer = buffer(128);
ByteBuf directBuffer = directBuffer(256);
ByteBuf wrappedBuffer = wrappedBuffer(new byte[128], new byte[256]);
ByteBuf copiedBuffer = copiedBuffer(ByteBuffer.allocate(128));
Выше мы видели 4 различных метода построения баффа: обычный бафф, прямой буфер, завернутый буфер и скопированный буфер.
Обычные баффы — это баффы кучи фиксированного размера, а directBuffers — это прямые баффы фиксированного размера. Прямой бафф использует память вне кучи, устраняя необходимость копировать данные в ядро, поэтому он более эффективен, чем обычные баффы.
WrappedBuffer — это инкапсуляция существующих байтовых массивов или байтовых буферов, которую можно рассматривать как представление.При изменении базовых данных данные в обернутом буфере также будут меняться.
Скопированный буфер — это глубокая копия существующих байтовых массивов, байтовых буферов или строк, поэтому он отличается от завернутого буфера Скопированный буфер не разделяет данные с исходными данными.
Бафф произвольного доступа
Друзья, знакомые с коллекциями, должны знать, что для случайного доступа к коллекции к ней нужно обращаться через индекс, то же самое справедливо и для ByteBuf, который можно получить через емкость или емкость, а затем произвольно обращаться к байтам в ней через метод getByte. метод, как показано ниже:
//随机访问
ByteBuf buffer = heapBuffer;
for (int i = 0; i < buffer.capacity(); i ++) {
byte b = buffer.getByte(i);
System.out.println((char) b);
}
Последовательность чтения и записи
Чтение и запись немного сложнее, чем доступ.ByteBuf предоставляет два индекса для определения позиций чтения и записи, а именно readerIndex и WriterIndex.Два индекса управляют позициями чтения и записи соответственно.
Буфер, показанный на рисунке ниже, разделен на три части: байты для отбрасывания, байты для чтения и байты для записи.
+-------------------+------------------+------------------+
| discardable bytes | readable bytes | writable bytes |
| | (CONTENT) | |
+-------------------+------------------+------------------+
| | | |
0 <= readerIndex <= writerIndex <= capacity
На приведенном выше рисунке также показано отношение размера между readerIndex, WriterIndex и емкостью.
Доступные для чтения байты — это реальный контент, к которому можно получить доступ или пропустить, вызвав методы read* или skip*. Когда эти методы вызываются, readerIndex будет увеличиваться синхронно. Если он превышает диапазон доступных для чтения байтов, будет выброшено исключение IndexOutOfBoundsException . По умолчанию читательИндекс=0.
Вот пример перебора читаемых байтов:
//遍历readable bytes
while (directBuffer.isReadable()) {
System.out.println(directBuffer.readByte());
}
Во-первых, решите, следует ли вызывать метод readByte, оценив, доступен ли он для чтения.
Доступные для записи байты — это неопределенная область, ожидающая заполнения. Им можно управлять, вызвав метод write*, и WriterIndex будет обновляться синхронно.Точно так же, если места недостаточно, будет выброшено исключение IndexOutOfBoundsException. По умолчанию вновь выделенный WriterIndex = 0, а WriterIndex обернутого или скопированного буфера = емкость буфера.
Вот пример использования записываемого байта:
//写入writable bytes
while (wrappedBuffer.maxWritableBytes() >= 4) {
wrappedBuffer.writeInt(new Random().nextInt());
}
Отбрасываемые байты — это прочитанные байты.Первоначально его значение = 0. Всякий раз, когда readerIndex перемещается вправо, пространство отбрасываемых байтов будет увеличиваться. Если вы хотите полностью удалить или сбросить отбрасываемые байты, вы можете вызвать метод discardReadBytes(), который удаляет пространство отбрасываемых байтов и помещает лишнее пространство в доступные для записи байты следующим образом:
调用 discardReadBytes() 之前:
+-------------------+------------------+------------------+
| discardable bytes | readable bytes | writable bytes |
+-------------------+------------------+------------------+
| | | |
0 <= readerIndex <= writerIndex <= capacity
调用 discardReadBytes()之后:
+------------------+--------------------------------------+
| readable bytes | writable bytes (got more space) |
+------------------+--------------------------------------+
| | |
readerIndex (0) <= writerIndex (decreased) <= capacity
Обратите внимание, что хотя байтов, доступных для записи, больше, их содержимое неуправляемо, и нет гарантии, что содержимое внутри пусто или не изменилось.
Вызов метода clear() очистит читательИндекс и WriterIndex до нуля.Обратите внимание, что метод очистки только установит значения читательИндекс и писательИндекс, но не очистит содержимое.См. диаграмму ниже:
调用 clear()之前:
+-------------------+------------------+------------------+
| discardable bytes | readable bytes | writable bytes |
+-------------------+------------------+------------------+
| | | |
0 <= readerIndex <= writerIndex <= capacity
调用 clear()之后:
+---------------------------------------------------------+
| writable bytes (got more space) |
+---------------------------------------------------------+
| |
0 = readerIndex = writerIndex <= capacity
поиск
ByteBuf предоставляет функцию поиска по одному байту, например два метода indexOf(int, int, byte) и bytesBefore(int, int, byte).
Если вы хотите искать и обрабатывать обход ByteBuf, вы можете использовать forEachByte(int, int, ByteProcessor), который получает ByteProcessor для сложной обработки.
Другие производные буферные методы
ByteBuf также предоставляет ряд методов для создания производных буферов, а именно:
duplicate()
slice()
slice(int, int)
readSlice(int)
retainedDuplicate()
retainedSlice()
retainedSlice(int, int)
readRetainedSlice(int)
Следует отметить, что эти буферы являются производными на основе существующих буферов, и их базовое содержимое одинаково, отличаются только считывательИндекс, писательИндекс и отмеченный индекс. Таким образом, они обмениваются данными с исходным buf. Если вы хотите создать новый буфер, вы можете использовать метод copy() или вышеупомянутый Unpooled.copiedBuffer.
В предыдущем разделе мы упомянули, что ByteBuf — это ReferenceCounted, и эта функция используется в производном buf. Мы знаем, что при вызове метода keep() счетчик ссылок будет увеличиваться, но для методов дубликат(), slice(), slice(int, int) и readSlice(int), хотя они тоже являются ссылками, сохранение not call(), так что исходные данные будут переработаны после того, как любой Buf вызовет метод release().
Если вам не нужны описанные выше побочные эффекты, вы можете заменить методы на reintedDuplicate(), KeepedSlice(), RetainedSlice(int, int) и readRetainedSlice(int) , которые вызывают метод continue() для добавления ссылки.
и преобразование существующих типов JDK
Ранее упоминалось, что ByteBuf — это переписанный ByteBuffer, это разные реализации. Хотя эти два значения различаются, это не препятствует преобразованию ByteBuf в ByteBuffer.
Конечно, самое простое преобразование — преобразовать ByteBuf в массив байтов byte[]. Чтобы преобразовать в массив байтов, вы можете сначала вызвать hasArray() для оценки, а затем вызвать метод array() для преобразования.
Тот же самый ByteBuf также может быть преобразован в ByteBuffer.Вы можете вызвать nioBufferCount(), чтобы определить количество ByteBuffers, которое может быть преобразовано в ByteBuffers, а затем вызвать nioBuffer() для преобразования.
Возвращенный ByteBuffer является долей или копией существующего буфера, и изменение позиции и предела буфера после возврата не повлияет на исходный буфер.
Наконец, ByteBuf можно преобразовать в строку с помощью метода toString(Charset).
Суммировать
ByteBuf является базовой основой netty, и это объект-носитель передачи данных.Глубоко понимая ByteBuf, вы можете понять идею дизайна netty, что очень хорошо.
Примеры этой статьи могут относиться к:learn-netty4
Эта статья была включена вwww.flydean.com
Самая популярная интерпретация, самая глубокая галантерея, самые краткие уроки и множество трюков, о которых вы не знаете, ждут вас!
Добро пожаловать, чтобы обратить внимание на мой официальный аккаунт: «Программируйте эти вещи», разбирайтесь в технологиях, лучше поймите себя!