Это пятый день моего участия в августовском испытании обновлений, подробности о мероприятии:Испытание августовского обновления
Введение
Канал — это мост, соединяющий ByteBuf и Event. Канал в netty предоставляет унифицированный API. Благодаря этому унифицированному API netty может легко подключаться к различным типам передачи, таким как OIO, NIO и т. д. Сегодня эта статья познакомит вас с использованием канала и некоторыми понятиями, связанными с каналом.
Сведения о канале
Что такое канал? Канал — это мост между сетевым вводом и обработкой ввода-вывода. Вы можете использовать канал для оценки текущего состояния, независимо от того, открыт он или подключен, а также для оценки операций ввода-вывода, поддерживаемых текущим каналом.Вы также можете использовать ChannelPipeline для обработки сообщений в канале.
Сначала посмотрите на определение канала:
public interface Channel extends AttributeMap, ChannelOutboundInvoker, Comparable<Channel> {
Вы можете видеть, что Channel — это интерфейс, который наследует три класса: AttributeMap, ChannelOutboundInvoker и Comparable. Comparable указывает, что этот класс можно использовать для сравнения. AttributeMap используется для хранения различных атрибутов канала. ChannelOutboundInvoker в основном отвечает за соединение и запись между Channel и внешним SocketAddress.
Взгляните на методы, определенные в канале:
Видно, что в канале определены различные методы, каковы характеристики этих методов? Далее я объясню вам один за другим.
Асинхронный IO и Cannelfuture
Все операции ввода-вывода в netty являются асинхронными операциями ввода-вывода, что означает, что все операции ввода-вывода возвращаются немедленно. При возврате операции ввода-вывода могут не закончиться, поэтому необходимо вернуть ChannelFuture. Когда операция ввода-вывода имеет результат, ChannelFuture будет уведомлен, чтобы Результат можно забрать.
ChannelFuture — подкласс java.util.concurrent.Future, который помимо получения результата выполнения потока еще и расширяет его, добавляя функции оценки текущего состояния задачи, ожидания выполнения задачи и добавления слушателей.
Другие функции хорошо изучены.Его прорыв заключается в возможности добавления слушателей в ChannelFuture.Перечислим способ добавления слушателей:
Future<V> addListeners(GenericFutureListener<? extends Future<? super V>>... listeners);
Добавленный прослушиватель будет уведомлен после завершения будущего выполнения. Вам не нужно снова вызывать get и ждать окончания future. На самом деле это реализация концепции асинхронного ввода-вывода, вам не нужно вызывать ее активно, просто сообщите мне, когда вы закончите. очень хорошо!
ChannelFuture имеет два состояния: незавершенное или завершенное, которые соответственно представляют состояние выполнения задачи.
Когда IO только начинается, возвращается объект ChannelFuture, и начальное состояние этого объекта не завершено. Обратите внимание, что IO в этом состоянии — это состояние, которое еще не начало работать. Когда ввод-вывод завершится, будь он успешным, неудачным или отмененным, состояние ChannelFuture будет преобразовано в завершенное.
На следующем рисунке показана соответствующая диаграмма состояния ChannelFuture и состояния ввода-вывода:
Если вы хотите отслеживать состояние ввода-вывода, вы можете использовать метод addListener, о котором мы упоминали выше, чтобы добавить ChannelFutureListener в ChannelFuture.
Если вы хотите дождаться завершения ввода-вывода, есть также метод await(), но этот метод будет ждать завершения ввода-вывода.Это синхронный метод, поэтому использовать его не рекомендуется.
Напротив, addListener(GenericFutureListener) — это неблокирующий асинхронный метод, который добавит ChannelFutureListener в ChannelFuture и автоматически уведомит ChannelFutureListener о завершении ввода-вывода, что очень полезно.
Для ChannelHandler, который обрабатывает операции ввода-вывода, чтобы избежать блокировки ввода-вывода, вы не должны вызывать await() в методе ввода-вывода ChannelHandler, что может привести к снижению производительности ChannelHandler из-за блокировки ввода-вывода.
Вот два примера, один из которых является неправильной операцией, а другой - правильной операцией:
// 错误操作
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) {
ChannelFuture future = ctx.channel().close();
future.awaitUninterruptibly();
// 调用其他逻辑
}
// 正确操作
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) {
ChannelFuture future = ctx.channel().close();
future.addListener(new ChannelFutureListener() {
public void operationComplete(ChannelFuture future) {
// 调用其他逻辑
}
});
}
Вы можете сравнить разницу между двумя вышеуказанными способами письма.
Также обратите внимание, что они ждут метода Channerfuture в таком виде как: ждут (долго), ждут (долго, timeunit), awantuniNebraphebraphibe (длинный), или a aboutuniNebraph for (долго, timeunit) может сделать срок годности, следует отметить, что это истек Время выполнения - это время исполнения, а не время ожидания IO, то есть, когда awaque Timeout, IO не может быть выполнен, что приводит к следующим возможным кодам ошибок:
Bootstrap b = ...;
ChannelFuture f = b.connect(...);
f.awaitUninterruptibly(10, TimeUnit.SECONDS);
if (f.isCancelled()) {
// 用户取消了Channel
} else if (!f.isSuccess()) {
// 这里可能会报异常,因为底层的IO可能还没有执行完成
f.cause().printStackTrace();
} else {
// 成功建立连接
}
Приведенный выше код можно изменить на следующий пример:
Bootstrap b = ...;
// 配置连接timeout的时间
b.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 10000);
ChannelFuture f = b.connect(...);
f.awaitUninterruptibly();
// 等待直到底层IO执行完毕
assert f.isDone();
if (f.isCancelled()) {
// 用户手动取消Channel
} else if (!f.isSuccess()) {
f.cause().printStackTrace();
} else {
// 成功建立连接
}
Иерархия каналов
Каналы в netty имеют иерархическую структуру, которую можно получить через свойство parent. Объект, полученный родителем, связан с тем, как был создан канал. Например, если это SocketChannel, принятый ServerSocketChannel, то его родителем является ServerSocketChannel.
освободить ресурсы
Как и все операции ввода-вывода, канал должен быть освобожден после того, как он будет использован, и необходимо вызвать метод close() или close(ChannelPromise).
обработка событий
Канал, отвечающий за установление соединения для установления хорошего подключения, может использоваться для обработки каналов событий, на самом деле, определяемый одним ChannelHandler. ChannelPipine - это мост между каналом и ChannelHandler.
Мы подробно объясним взаимосвязь между ChannelEvent, Channelhandler и ChannelPipeline в следующей главе, так что следите за обновлениями.
Суммировать
Канал существует как ключевой канал в netty. Последнее событие и обработчик работают на основе канала, поэтому канал является основой netty. Что ж, сегодняшнее введение здесь закончено. С нетерпением жду следующих статей.
Эта статья была включена вWoohoo Floyd Press.com/04-Netty-eat…
Самая популярная интерпретация, самая глубокая галантерея, самые краткие уроки и множество трюков, о которых вы не знаете, ждут вас!
Добро пожаловать, чтобы обратить внимание на мой официальный аккаунт: «Программируйте эти вещи», разбирайтесь в технологиях, лучше поймите себя!