Netty中分隔符和定长解码器的应用

2024-06-23 12:32

本文主要是介绍Netty中分隔符和定长解码器的应用,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一.使用DelimiterBasedFrameDecoder自动完成以分隔符作为结束标志的解码

1.1 DelimiterBasedFrameDecoder服务端开发

1.1.1 EchoServer实现

import io.netty.bootstrap.ServerBootstrap;

import io.netty.buffer.ByteBuf;

import io.netty.buffer.Unpooled;

import io.netty.channel.ChannelFuture;

import io.netty.channel.ChannelInitializer;

import io.netty.channel.ChannelOption;

import io.netty.channel.EventLoopGroup;

importio.netty.channel.nio.NioEventLoopGroup;

importio.netty.channel.socket.SocketChannel;

import io.netty.channel.socket.nio.NioServerSocketChannel;

importio.netty.handler.codec.DelimiterBasedFrameDecoder;

importio.netty.handler.codec.LineBasedFrameDecoder;

importio.netty.handler.codec.string.StringDecoder;

import io.netty.handler.logging.LogLevel;

import io.netty.handler.logging.LoggingHandler;

/*

 * 利用DelimiterBasedFrameDecoder完成以分隔符作为码流结束的标识

 */

public class EchoServer {

        

         publicvoid bind(int port) throws Exception{

                   //配置服务端的NIO线程组

                   EventLoopGroupbossGroup =new NioEventLoopGroup();

                   EventLoopGroupworkerGroup =new NioEventLoopGroup();

         try{

                   //用于启动NIO服务器的辅助启动类,降低服务端的开发复杂度

                   ServerBootstrapb=new ServerBootstrap();

                   b.group(bossGroup,workerGroup).

                   channel(NioServerSocketChannel.class)

                   .option(ChannelOption.SO_BACKLOG,100)

                   .handler(newLoggingHandler(LogLevel.INFO))

                   .childHandler(newChannelInitializer<SocketChannel>() {

                            @Override

                            publicvoid initChannel(SocketChannel ch) throws Exception{

                                     ByteBufdelimiter=Unpooled.copiedBuffer("$_".getBytes());

                                     ch.pipeline().addLast(

                                                        newDelimiterBasedFrameDecoder(1024,delimiter)); // 单条消息最大长度:1024

                                     ch.pipeline().addLast(newStringDecoder());

                                     ch.pipeline().addLast(newEchoServerHandler());

                            }

                            });

                           

                  

                   //绑定端口,同步等待成功

                   ChannelFuturef=b.bind(port).sync();

                   //等待服务端监听端口关闭

                   f.channel().closeFuture().sync();

        

                  

         }catch (Exception e) {

                   //TODO: handle exception

         }finally{

                   //优雅退出,释放线程池资源

                   bossGroup.shutdownGracefully();

                   workerGroup.shutdownGracefully();

         }

        

         }

 

        

         publicstatic void main(String[] args) throws Exception{

                   intport=8080;

                   if(args!=null&&args.length>0){

                            try{

                                     port=Integer.valueOf(args[0]);

                            }catch (NumberFormatException e) {

                                     //TODO: handle exception

                            }

                   }

                   newEchoServer().bind(port);

         }}

1.1.2 EchoServerHandler实现

import io.netty.buffer.ByteBuf;

import io.netty.buffer.Unpooled;

import io.netty.channel.ChannelHandlerAdapter;

import io.netty.channel.ChannelHandlerContext;

/*

 * 利用LineBasedFrameDecoder解决TCP粘包问题

 */

public classEchoServerHandler extends ChannelHandlerAdapter{

     

   int counter =0;

   @Override

   public voidchannelRead(ChannelHandlerContext ctx,Object msg)throwsException{

     

      Stringbody=(String)msg;

      System.out.println("This is"+++counter+"times receive client: ["+body+"]" );

      body+="$_";

         ByteBufecho=Unpooled.copiedBuffer(body.getBytes());

         ctx.writeAndFlush(echo);

   }

 

  

   @Override

   public voidexceptionCaught(ChannelHandlerContext ctx,Throwable cause){

      cause.printStackTrace();

      ctx.close();  // 发生异常,关闭链路

   }

}

1.2 DelimitedBasedFrameDecoder客户端开发

1.2.1 EchoClient实现

import client.TimeClient;

import io.netty.bootstrap.Bootstrap;

import io.netty.buffer.ByteBuf;

import io.netty.buffer.Unpooled;

import io.netty.channel.ChannelFuture;

import io.netty.channel.ChannelInitializer;

import io.netty.channel.ChannelOption;

import io.netty.channel.EventLoopGroup;

importio.netty.channel.nio.NioEventLoopGroup;

importio.netty.channel.socket.SocketChannel;

importio.netty.channel.socket.nio.NioSocketChannel;

importio.netty.handler.codec.DelimiterBasedFrameDecoder;

importio.netty.handler.codec.string.StringDecoder;

 

public class EchoClient {

        

         publicvoid connect(int port,String host) throws Exception{

                   //配置客户端NIO线程组

                   EventLoopGroupgroup=new NioEventLoopGroup();

                   try{

                            Bootstrapb=new Bootstrap();

                            b.group(group).channel(NioSocketChannel.class)

                            .option(ChannelOption.TCP_NODELAY,true)

                            .handler(newChannelInitializer<SocketChannel>() {

                                     @Override

                                     publicvoid initChannel(SocketChannel ch) throws Exception{

                                               ByteBufdelimiter=Unpooled.copiedBuffer("$_".getBytes());

                                               ch.pipeline().addLast(newDelimiterBasedFrameDecoder(1024,delimiter));

                                               ch.pipeline().addLast(newStringDecoder());

                                               ch.pipeline().addLast(newEchoClientHandler());

                                     }

                            });

                            //发起异步连接操作

                            ChannelFuturef=b.connect(host,port).sync();

                            //等待客户端链路关闭

                            f.channel().closeFuture().sync();

                   }catch (Exception e) {

                            //TODO: handle exception

                   }finally{

                            //优雅退出,释放NIO线程组

                            group.shutdownGracefully();

                   }

         }

        

         publicstatic void main(String[] args) throws Exception{

                   intport=8080;

                   if(args!=null&&args.length>0){

                            try{

                                     port=Integer.valueOf(args[0]);

                                    

                            }catch (NumberFormatException e) {

                                     //TODO: handle exception

                                    

                            }

                            newTimeClient().connect(port,"127.0.0.1");

                   }

         }

 

}

1.2.2 EchoClientHandler实现

import io.netty.buffer.Unpooled;

importio.netty.channel.ChannelHandlerAdapter;

importio.netty.channel.ChannelHandlerContext;

 

public class EchoClientHandler extendsChannelHandlerAdapter{

        private int counter;

        static final String ECHO_REQ="Welcome to Netty.$_";

        

        public EchoClientHandler(){

                 

        }

        

        @Override

        public void channelActive(ChannelHandlerContext ctx){

                 for(int i=0;i<10;i++){

                           ctx.writeAndFlush(Unpooled.copiedBuffer(ECHO_REQ.getBytes()));

                 }

        }

        

        public void channelRead(ChannelHandlerContext ctx,Object msg) throwsException{

                 ctx.flush();

        }

        

        @Override

        public voidexceptionCaught(ChannelHandlerContext ctx,Throwable cause){

                 cause.printStackTrace();

                 ctx.close();

        }

}

二.使用FiexLengthFrameDecoder定长解码器进行自动解码

2.1 FixLengthFrameDecoder服务的开发

2.1.1 EchoServer实现

package fixedlength;

import io.netty.bootstrap.ServerBootstrap;

import io.netty.buffer.ByteBuf;

import io.netty.buffer.Unpooled;

import io.netty.channel.ChannelFuture;

import io.netty.channel.ChannelInitializer;

import io.netty.channel.ChannelOption;

import io.netty.channel.EventLoopGroup;

importio.netty.channel.nio.NioEventLoopGroup;

importio.netty.channel.socket.SocketChannel;

importio.netty.channel.socket.nio.NioServerSocketChannel;

importio.netty.handler.codec.DelimiterBasedFrameDecoder;

import io.netty.handler.codec.FixedLengthFrameDecoder;

importio.netty.handler.codec.LineBasedFrameDecoder;

importio.netty.handler.codec.string.StringDecoder;

import io.netty.handler.logging.LogLevel;

importio.netty.handler.logging.LoggingHandler;

/*

 * 利用FixedLengthFrameDecoder固定解码长度

 */

public class EchoServer {

        

         publicvoid bind(int port) throws Exception{

                   //配置服务端的NIO线程组

                   EventLoopGroupbossGroup =new NioEventLoopGroup();

                   EventLoopGroupworkerGroup =new NioEventLoopGroup();

         try{

                   //用于启动NIO服务器的辅助启动类,降低服务端的开发复杂度

                   ServerBootstrapb=new ServerBootstrap();

                   b.group(bossGroup,workerGroup).

                   channel(NioServerSocketChannel.class)

                   .option(ChannelOption.SO_BACKLOG,100)

                   .handler(newLoggingHandler(LogLevel.INFO))

                   .childHandler(newChannelInitializer<SocketChannel>() {

                            @Override

                            publicvoid initChannel(SocketChannel ch) throws Exception{

                                     ByteBufdelimiter=Unpooled.copiedBuffer("$_".getBytes());

                                     ch.pipeline().addLast(

                                                        newFixedLengthFrameDecoder(20)); // 固定解码长度为20

                                     ch.pipeline().addLast(newStringDecoder());

                                     ch.pipeline().addLast(newEchoServerHandler());

                            }

                            });

                           

                  

                   //绑定端口,同步等待成功

                   ChannelFuturef=b.bind(port).sync();

                   //等待服务端监听端口关闭

                   f.channel().closeFuture().sync();

        

                  

         }catch (Exception e) {

                   //TODO: handle exception

         }finally{

                   //优雅退出,释放线程池资源

                   bossGroup.shutdownGracefully();

                   workerGroup.shutdownGracefully();

         }

        

         }

 

        

         publicstatic void main(String[] args) throws Exception{

                   intport=8080;

                   if(args!=null&&args.length>0){

                            try{

                                     port=Integer.valueOf(args[0]);

                            }catch (NumberFormatException e) {

                                     //TODO: handle exception

                            }

                   }

                   newEchoServer().bind(port);

         }

 

}

2.1.2 EchoServerHandler实现

import io.netty.channel.ChannelHandlerAdapter;

import io.netty.channel.ChannelHandlerContext;

/*

 * 打印读取的消息

 */

public classEchoServerHandler extends ChannelHandlerAdapter{

         

   @Override

   public voidchannelRead(ChannelHandlerContext ctx,Object msg)throwsException{

      System.out.println("Receive client:["+msg+"]");

     

   }

   @Override

   public voidexceptionCaught(ChannelHandlerContext ctx,Throwable cause){

      cause.printStackTrace();

      ctx.close();  // 发生异常,关闭链路

   }

}

  利用FixedLengthFrameDecoder解码器,无论一次接受多少数据报,它都会按照构造函数中固定长度进行解码

这篇关于Netty中分隔符和定长解码器的应用的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1087165

相关文章

Python中随机休眠技术原理与应用详解

《Python中随机休眠技术原理与应用详解》在编程中,让程序暂停执行特定时间是常见需求,当需要引入不确定性时,随机休眠就成为关键技巧,下面我们就来看看Python中随机休眠技术的具体实现与应用吧... 目录引言一、实现原理与基础方法1.1 核心函数解析1.2 基础实现模板1.3 整数版实现二、典型应用场景2

Java的IO模型、Netty原理解析

《Java的IO模型、Netty原理解析》Java的I/O是以流的方式进行数据输入输出的,Java的类库涉及很多领域的IO内容:标准的输入输出,文件的操作、网络上的数据传输流、字符串流、对象流等,这篇... 目录1.什么是IO2.同步与异步、阻塞与非阻塞3.三种IO模型BIO(blocking I/O)NI

Python Dash框架在数据可视化仪表板中的应用与实践记录

《PythonDash框架在数据可视化仪表板中的应用与实践记录》Python的PlotlyDash库提供了一种简便且强大的方式来构建和展示互动式数据仪表板,本篇文章将深入探讨如何使用Dash设计一... 目录python Dash框架在数据可视化仪表板中的应用与实践1. 什么是Plotly Dash?1.1

Android Kotlin 高阶函数详解及其在协程中的应用小结

《AndroidKotlin高阶函数详解及其在协程中的应用小结》高阶函数是Kotlin中的一个重要特性,它能够将函数作为一等公民(First-ClassCitizen),使得代码更加简洁、灵活和可... 目录1. 引言2. 什么是高阶函数?3. 高阶函数的基础用法3.1 传递函数作为参数3.2 Lambda

Java中&和&&以及|和||的区别、应用场景和代码示例

《Java中&和&&以及|和||的区别、应用场景和代码示例》:本文主要介绍Java中的逻辑运算符&、&&、|和||的区别,包括它们在布尔和整数类型上的应用,文中通过代码介绍的非常详细,需要的朋友可... 目录前言1. & 和 &&代码示例2. | 和 ||代码示例3. 为什么要使用 & 和 | 而不是总是使

Python循环缓冲区的应用详解

《Python循环缓冲区的应用详解》循环缓冲区是一个线性缓冲区,逻辑上被视为一个循环的结构,本文主要为大家介绍了Python中循环缓冲区的相关应用,有兴趣的小伙伴可以了解一下... 目录什么是循环缓冲区循环缓冲区的结构python中的循环缓冲区实现运行循环缓冲区循环缓冲区的优势应用案例Python中的实现库

SpringBoot整合MybatisPlus的基本应用指南

《SpringBoot整合MybatisPlus的基本应用指南》MyBatis-Plus,简称MP,是一个MyBatis的增强工具,在MyBatis的基础上只做增强不做改变,下面小编就来和大家介绍一下... 目录一、MyBATisPlus简介二、SpringBoot整合MybatisPlus1、创建数据库和

python中time模块的常用方法及应用详解

《python中time模块的常用方法及应用详解》在Python开发中,时间处理是绕不开的刚需场景,从性能计时到定时任务,从日志记录到数据同步,时间模块始终是开发者最得力的工具之一,本文将通过真实案例... 目录一、时间基石:time.time()典型场景:程序性能分析进阶技巧:结合上下文管理器实现自动计时

Java逻辑运算符之&&、|| 与&、 |的区别及应用

《Java逻辑运算符之&&、||与&、|的区别及应用》:本文主要介绍Java逻辑运算符之&&、||与&、|的区别及应用的相关资料,分别是&&、||与&、|,并探讨了它们在不同应用场景中... 目录前言一、基本概念与运算符介绍二、短路与与非短路与:&& 与 & 的区别1. &&:短路与(AND)2. &:非短

Spring AI集成DeepSeek三步搞定Java智能应用的详细过程

《SpringAI集成DeepSeek三步搞定Java智能应用的详细过程》本文介绍了如何使用SpringAI集成DeepSeek,一个国内顶尖的多模态大模型,SpringAI提供了一套统一的接口,简... 目录DeepSeek 介绍Spring AI 是什么?Spring AI 的主要功能包括1、环境准备2