八、分隔符和定长解码器的应用(2)
来源:互联网 发布:ubuntu命令行安装中文 编辑:程序博客网 时间:2024/05/16 23:55
下面主要是使用FixedLengthFrameDecoder应用开发
FixedLengthFrameDecoder是固定长度解码器,它能够按照指定的长度对消息进行自动解码,我们不需要去考虑TCP的粘包和拆包问题。同样上代码实例:
服务端代码:
package FixedLengthFrameDecoder;import NettyFrameDecoder.EchoServerHandler;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;import io.netty.channel.nio.NioEventLoopGroup;import io.netty.channel.socket.SocketChannel;import io.netty.channel.socket.nio.NioServerSocketChannel;import io.netty.handler.codec.DelimiterBasedFrameDecoder;import io.netty.handler.codec.FixedLengthFrameDecoder;import io.netty.handler.codec.string.StringDecoder;import io.netty.handler.logging.LoggingHandler;import sun.rmi.log.LogHandler;/** * Created by L_kanglin on 2017/6/12. */public class EchoServerFixed { public void bind(int port) throws Exception { //配置服务端的线程组 EventLoopGroup bossGroup=new NioEventLoopGroup(); EventLoopGroup workGroup=new NioEventLoopGroup(); try { ServerBootstrap b = new ServerBootstrap(); b.group(bossGroup,workGroup) .channel(NioServerSocketChannel.class) .option(ChannelOption.SO_BACKLOG,100) .handler(new LoggingHandler(LogHandler.class)) .childHandler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel ch) throws Exception { //创建FixedLengthFrameDecoder对象,长度设置为20 ch.pipeline().addLast(new FixedLengthFrameDecoder(20)); //将接收到的消息转化为字符串,将ByteBuf解码成字符串对象 ch.pipeline().addLast((new StringDecoder())); //接收到的msg消息就是解码后的字符串对象 ch.pipeline().addLast(new EchoServerHandlerFixed()); } }); //绑定端口,同步等待成功 ChannelFuture f =b.bind(port).sync(); //等待服务端监听端口关闭 f.channel().closeFuture().sync(); } finally{ bossGroup.shutdownGracefully(); workGroup.shutdownGracefully(); } } public static void main(String[] args) throws Exception { int port=9030; if(args !=null && args.length>0){ port=Integer.valueOf(args[0]); } new EchoServerFixed().bind(port); }}
package FixedLengthFrameDecoder;import io.netty.buffer.ByteBuf;import io.netty.buffer.Unpooled;import io.netty.channel.ChannelHandlerAdapter;import io.netty.channel.ChannelHandlerContext;/** * Created by L_kanglin on 2017/6/12. */public class EchoServerHandlerFixed extends ChannelHandlerAdapter { @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { System.out.println("Receive client : [" +msg+ "]"); String body = (String) msg; ByteBuf echo= Unpooled.copiedBuffer(body.getBytes()); ctx.writeAndFlush(echo); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { cause.printStackTrace(); ctx.close(); }}
客户端代码如下:
package FixedLengthFrameDecoderClient;import NettyFrameDecoderClient.EchoClientHandler;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;import io.netty.channel.nio.NioEventLoopGroup;import io.netty.channel.socket.SocketChannel;import io.netty.channel.socket.nio.NioSocketChannel;import io.netty.handler.codec.DelimiterBasedFrameDecoder;import io.netty.handler.codec.FixedLengthFrameDecoder;import io.netty.handler.codec.string.StringDecoder;/** * Created by L_kanglin on 2017/6/12. */public class EchoClientFixed { public void connnect(int port,String host) throws InterruptedException { EventLoopGroup group = new NioEventLoopGroup(); try { Bootstrap b =new Bootstrap(); b.group(group).channel(NioSocketChannel.class) .option(ChannelOption.TCP_NODELAY,true) .handler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel ch) throws Exception { ch.pipeline().addLast(new FixedLengthFrameDecoder(20)); ch.pipeline().addLast(new StringDecoder()); ch.pipeline().addLast(new EchoClientHandlerFixed()); } }); //发起异步连接操作 ChannelFuture f =b.connect(host,port).sync(); //等待客户端链路关闭 f.channel().closeFuture().sync(); } finally{ //优雅退出,释放NIO线程组 group.shutdownGracefully(); } } public static void main(String[] args) throws InterruptedException { int port = 9030; if(args !=null && args.length>0){ port=Integer.valueOf(args[0]); } new EchoClientFixed().connnect(port,"127.0.0.1"); }}
package FixedLengthFrameDecoderClient;import io.netty.buffer.Unpooled;import io.netty.channel.ChannelHandlerAdapter;import io.netty.channel.ChannelHandlerContext;/** * Created by L_kanglin on 2017/6/12. */public class EchoClientHandlerFixed extends ChannelHandlerAdapter { private int counter; static final String ECHO_REQ="LiKanglin Welcome to Netty at WuHan"; public EchoClientHandlerFixed() { } //在TCP链路建立成功之后循环发送请求消息给服务端 @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { //发送指定内容 ctx.writeAndFlush(Unpooled.copiedBuffer(ECHO_REQ.getBytes())); } //打印接收到的服务端应答消息同时进行计数 @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { System.out.println(" receive server:{ " + msg + "}"); } @Override public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { ctx.flush(); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { cause.printStackTrace(); ctx.close(); }}
服务端运行如下:
Receive client : [LiKanglin Welcome to]
客户端运行如下:
receive server:{ LiKanglin Welcome to}
通过FixedLengthFrameDecoder解码器,每次会按照设置的固定长度进行解码,如果是半包消息,FixedLengthFrameDecoder会缓存半包消息并等待下个包到达后进行拼包,直到读取到一个完整的包。
总结:
通过熟练运用这两种解码器,即可完成很多消息的自动解码,并且不用考虑TCP的粘包和拆包导致的读半包问题,极大的提升了开发效率。
补充:重要的是记住什么情况下会发生TCP的粘包和拆包问题,主要是应用层、运输层、网络层,详情请看前面的部分。
阅读全文
0 0
- 八、分隔符和定长解码器的应用(2)
- Netty分隔符解码器和定长解码器的应用方案
- Netty的分隔符和定长解码器应用
- 七、分隔符和定长解码器的应用(1)
- Netty中分隔符和定长解码器的应用
- 分隔符和定长解码器在netty中的应用
- Netty权威指南 第2版学习笔记5——分隔符和定长解码器的应用
- 《netty权威指南》5分隔符和定长解码器的应用
- Netty (四) 分隔符和定长解码器的使用
- [netty]--分隔符解码器DelimiterBasedFrameDecoder和定长解码器FixedLengthFrameDecoder
- netty分割符和定长解码器的应用
- Netty权威指南之分隔符和定长解码器
- netty之分隔符和定长解码器解决之道
- Netty学习之旅(三)(分隔符和定长解码器)
- Netty的分隔符解码器的使用
- TStringList的分隔符应用
- 分割符和定长解码
- 分隔符的应用【日期处理问题】
- Android视频开发资料
- 超简单将Centos的yum源更换为国内的阿里云源
- Redis 常见 的几种使用场景
- oracle查询约束
- 矩阵,向量求导
- 八、分隔符和定长解码器的应用(2)
- mysql 优化
- 乱码问题
- BroadcastReceiver总结
- centos7 mysql数据库安装和配置
- 我的Java第二课下
- QSettings操作配置文件
- JFinal连接数据库失败
- 微信开发–带参数的二维码