Это 11-й день моего участия в августовском испытании обновлений. Узнайте подробности события:Испытание августовского обновления
Введение
После предыдущей серии статей мы уже знаем принцип работы netty, а также представили базовый процесс построения сервиса netty и способ написания обработчика сообщений. Сегодня эта статья познакомит вас с более сложным примером — текстовым чатом.
Рабочий процесс чата
Сегодня я хочу представить вам текстовый чат.Для текстового чата сначала необходимо установить сервер для обработки соединения каждого клиента.Для клиента необходимо установить соединение с сервером, а затем ввести информацию чата на сервер. После того, как сервер получит информацию о чате, он ответит на сообщение и вернет сообщение клиенту, тем самым завершив процесс чата.
текстовый процессор
В предыдущей статье мы упомянули, что передача netty поддерживает только тип ByteBuf, который не поддерживается для строк, непосредственно вводимых в чате, и строки необходимо кодировать и декодировать.
Представленные ранее классы кодирования и декодирования называются ObjectDecoder и ObjectEncoder. Сегодня мы представляем еще два StringDecoder и StringEncoder, которые работают со строками.
StringEncoder намного проще, чем ObjectEncoder, потому что для объектов нам также нужно установить размер массива Byte в начале массива Byte, чтобы гарантировать правильное чтение всех данных объекта. Для String это относительно просто, вам нужно только убедиться, что все данные, прочитанные за один раз, являются строками.
StringEncoder наследуется от MessageToMessageEncoder, и его основной код кодирования выглядит следующим образом:
protected void encode(ChannelHandlerContext ctx, CharSequence msg, List<Object> out) throws Exception {
if (msg.length() == 0) {
return;
}
out.add(ByteBufUtil.encodeString(ctx.alloc(), CharBuffer.wrap(msg), charset));
}
Как видно из приведенного выше кода, ядро фактически вызывает метод ByteBufUtil.encodeString для преобразования String в ByteBuf.
Для кодирования строк также необходимо определить диапазон кодирования.Например, нам нужно знать, сколько строк нужно кодировать за раз.Вообще говоря, мы определяем конец введенной строки с помощью возврата каретки.
Netty также предоставляет такой очень удобный класс под названием DelimiterBasedFrameDecoder, Передавая разные разделители, мы можем разделить ввод на разные фреймы для обработки строки строк.
new DelimiterBasedFrameDecoder(8192, Delimiters.lineDelimiter()))
Позвольте мне еще раз взглянуть на основной код StringDecoder, StringDecoder наследуется от MessageToMessageDecoder:
protected void decode(ChannelHandlerContext ctx, ByteBuf msg, List<Object> out) throws Exception {
out.add(msg.toString(charset));
}
При вызове метода toString объекта ByteBuf BuyteBuf преобразуется в строку и выводится в канал.
Инициализировать обработчик канала
Когда initChannel, нам нужно добавить допустимый обработчик в ChannelPipeline. Для этого примера вам нужно добавить StringDecoder, StringEncoder, DelimiterBasedFrameDecoder и собственный обработчик, который фактически обрабатывает сообщение.
Мы поместили операции инициализации Pipeline в новый класс ChatServerInitializer, который наследуется от ChannelInitializer, а его основной метод initChannel выглядит следующим образом:
public void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
// 添加行分割器
pipeline.addLast(new DelimiterBasedFrameDecoder(8192, Delimiters.lineDelimiter()));
// 添加String Decoder和String Encoder,用来进行字符串的转换
pipeline.addLast(DECODER);
pipeline.addLast(ENCODER);
// 最后添加真正的处理器
pipeline.addLast(SERVER_HANDLER);
}
ChatServerInitializer добавляется в childHandler в Bootstrap:
childHandler(new ChatServerInitializer())
реальная логика обработки сообщений
С помощью приведенной выше логики нам, наконец, нужно сосредоточиться только на реальной логике обработки сообщений.
Наша логика здесь заключается в том, чтобы закрыть канал, когда клиент вводит «до свидания», в противном случае отправить сообщение обратно клиенту.
Его основная логика заключается в следующем:
public void channelRead0(ChannelHandlerContext ctx, String request) throws Exception {
// 如果读取到"再见"就关闭channel
String response;
// 判断是否关闭
boolean close = false;
if (request.isEmpty()) {
response = "你说啥?\r\n";
} else if ("再见".equalsIgnoreCase(request)) {
response = "再见,我的朋友!\r\n";
close = true;
} else {
response = "你是不是说: '" + request + "'?\r\n";
}
// 写入消息
ChannelFuture future = ctx.write(response);
// 添加CLOSE listener,用来关闭channel
if (close) {
future.addListener(ChannelFutureListener.CLOSE);
}
}
Установите, закрывать ли кнопку, оценивая вход и выход клиента.Закрытие канала здесь реализовано путем добавления ChannelFutureListener.CLOSE в ChannelFuture.
ChannelFutureListener.CLOSE — это ChannelFutureListener, который закрывает канал после его выполнения, на самом деле это очень элегантный способ закрытия.
ChannelFutureListener CLOSE = new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture future) {
future.channel().close();
}
};
Для клиента ядром является чтение ввода из командной строки.Здесь InputStreamReader используется для получения ввода командной строки, а BufferedReader используется для его буферизации.
Затем запишите ввод командной строки в канал, вызвав ch.writeAndFlush, и, наконец, прослушайте ввод командной строки.Если вы слушаете «до свидания», подождите, пока сервер закроет канал.Основной код выглядит следующим образом.
// 从命令行输入
ChannelFuture lastWriteFuture = null;
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
for (;;) {
String line = in.readLine();
if (line == null) {
break;
}
// 将从命令行输入的一行字符写到channel中
lastWriteFuture = ch.writeAndFlush(line + "\r\n");
// 如果输入'再见',则等待server端关闭channel
if ("再见".equalsIgnoreCase(line)) {
ch.closeFuture().sync();
break;
}
}
// 等待所有的消息都写入channel中
if (lastWriteFuture != null) {
lastWriteFuture.sync();
}
Суммировать
После приведенного выше введения создается простой чат. Мы продолжим изучать более сложные приложения в будущем, надеюсь, вам понравится.
Примеры этой статьи могут относиться к:learn-netty4
Эта статья была включена вWoohoo. Floyd Press.com/10-Netty-eat…
Самая популярная интерпретация, самая глубокая галантерея, самые краткие уроки и множество трюков, о которых вы не знаете, ждут вас!
Добро пожаловать, чтобы обратить внимание на мой официальный аккаунт: «Программируйте эти вещи», разбирайтесь в технологиях, лучше поймите себя!