TCP粘包/拆包--利用FixedLengthFrameDecoder解决TCP粘包问题
来源:互联网 发布:app模型制作软件 编辑:程序博客网 时间:2024/06/11 03:10
前面我们介绍了利用LineBasedFrameDecoder和DelemiterBasedFrameDecoder解决TCP的粘包/拆包的问题,
现在我们继续介绍Netty的最后一种解码器--FixedLengthFrameDecoder。
利用FixedLengthFrameDecoder解码器,无论一次接收到多少数据报,它都会按照构造函数中设置的固定长度进行解码,如果是半包消息,FixedLengthFrameDecoder会缓存半包消息并等待下个包到达后进行拼包,直到读取到一个完整的包。
1. EchoServer.java
import io.netty.bootstrap.ServerBootstrap;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.FixedLengthFrameDecoder;import io.netty.handler.codec.string.StringDecoder;public class EchoServer { private final static int port = 8080; public static void main(String[] args) { start(); } private static void start() { final EchoServerHandler serverHandler = new EchoServerHandler(); // 创建EventLoopGroup EventLoopGroup bossGroup = new NioEventLoopGroup(); EventLoopGroup workerGroup = new NioEventLoopGroup(); // 创建EventLoopGroup ServerBootstrap b = new ServerBootstrap(); b.group(bossGroup, workerGroup) .channel(NioServerSocketChannel.class) .option(ChannelOption.SO_BACKLOG, 100) .childHandler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel socketChannel) throws Exception { socketChannel.pipeline().addLast( new FixedLengthFrameDecoder(20)); socketChannel.pipeline().addLast(new StringDecoder()); socketChannel.pipeline().addLast(serverHandler); } }); try { // 异步地绑定服务器;调用sync方法阻塞等待直到绑定完成 ChannelFuture f = b.bind(port).sync(); // 获取Channel的CloseFuture,并且阻塞当前线程直到它完成 f.channel().closeFuture().sync(); } catch (InterruptedException e) { e.printStackTrace(); } finally { // 优雅的关闭EventLoopGroup,释放所有的资源 bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully(); } }}2. EchoServerHandler.java
import io.netty.buffer.ByteBuf;import io.netty.buffer.Unpooled;import io.netty.channel.ChannelHandler.Sharable;import io.netty.channel.ChannelHandlerContext;import io.netty.channel.ChannelInboundHandlerAdapter;@Sharablepublic class EchoServerHandler extends ChannelInboundHandlerAdapter{ private int counter = 0; @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { String body = (String )msg; System.out.println( "This is " + ++counter +" times receive client [" + body +"]" ); ByteBuf resp = Unpooled.copiedBuffer(body.getBytes()); ctx.writeAndFlush(resp); } /** * 异常处理 * @param ctx * @param cause * @throws Exception */ @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { //打印异常栈跟踪 cause.printStackTrace(); // 关闭该Channel ctx.close(); }}3. EchoClient.java
import io.netty.bootstrap.Bootstrap;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.FixedLengthFrameDecoder;import io.netty.handler.codec.string.StringDecoder;import java.net.InetSocketAddress;public class EchoClient { private final static String HOST = "localhost"; private final static int PORT = 8080; public static void start() { EventLoopGroup group = new NioEventLoopGroup(); Bootstrap bootstrap = new Bootstrap(); bootstrap.group(group) .channel(NioSocketChannel.class) .option(ChannelOption.TCP_NODELAY, true) .handler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel socketChannel) throws Exception { socketChannel.pipeline().addLast(new FixedLengthFrameDecoder(20)); socketChannel.pipeline().addLast(new StringDecoder()); socketChannel.pipeline().addLast(new EchoClientHandler()); } }); try { ChannelFuture f = bootstrap.connect(HOST,PORT).sync(); f.channel().closeFuture().sync(); } catch (InterruptedException e) { e.printStackTrace(); }finally { group.shutdownGracefully(); } } public static void main(String[] args) { start(); }}4. EchoClientHandler.java
import io.netty.buffer.Unpooled;import io.netty.channel.ChannelHandler.Sharable;import io.netty.channel.ChannelHandlerContext;import io.netty.channel.ChannelInboundHandlerAdapter;@Sharablepublic class EchoClientHandler extends ChannelInboundHandlerAdapter { private int counter; static final String ECHO_REQ = "Hi, Welcome to Netty World!"; @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { String body = (String) msg; System.out.println( "This is "+ ++counter + " times receive server:[" + body +"]" ); } @Override public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { ctx.flush(); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { cause.printStackTrace(); ctx.close(); } @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { for (int i = 0; i < 10; i++) { ctx.writeAndFlush(Unpooled.copiedBuffer(ECHO_REQ.getBytes())); } }}分别运行EchoServer和EchoClient,控制台的运行结果如下
服务端运行结果:
This is 1 times receive client [Hi, Welcome to Netty]This is 2 times receive client [ World!Hi, Welcome t]This is 3 times receive client [o Netty World!Hi, We]This is 4 times receive client [lcome to Netty World]This is 5 times receive client [!Hi, Welcome to Nett]This is 6 times receive client [y World!Hi, Welcome ]This is 7 times receive client [to Netty World!Hi, W]This is 8 times receive client [elcome to Netty Worl]This is 9 times receive client [d!Hi, Welcome to Net]This is 10 times receive client [ty World!Hi, Welcome]This is 11 times receive client [ to Netty World!Hi, ]This is 12 times receive client [Welcome to Netty Wor]This is 13 times receive client [ld!Hi, Welcome to Ne]客户端运行结果:
This is 1 times receive server:[Hi, Welcome to Netty]This is 2 times receive server:[ World!Hi, Welcome t]This is 3 times receive server:[o Netty World!Hi, We]This is 4 times receive server:[lcome to Netty World]This is 5 times receive server:[!Hi, Welcome to Nett]This is 6 times receive server:[y World!Hi, Welcome ]This is 7 times receive server:[to Netty World!Hi, W]This is 8 times receive server:[elcome to Netty Worl]This is 9 times receive server:[d!Hi, Welcome to Net]This is 10 times receive server:[ty World!Hi, Welcome]This is 11 times receive server:[ to Netty World!Hi, ]This is 12 times receive server:[Welcome to Netty Wor]This is 13 times receive server:[ld!Hi, Welcome to Ne]
节选自《Netty权威指南第二版》, 代码部分有部分改动。
阅读全文
0 0
- TCP粘包/拆包--利用FixedLengthFrameDecoder解决TCP粘包问题
- TCP粘包/拆包--利用LineBasedFrameDecoder解决TCP粘包问题
- TCP粘包/拆包--利用DelimiterBasedFrameDecoder解决TCP粘包问题
- 利用LineBasedFrameDecoder解决TCP粘包问题
- Netty初探-解决TCP粘包/拆包问题
- TCP粘包与拆包问题
- TCP粘包问题
- TCP粘包问题
- TCP粘包问题
- TCP粘包问题
- tcp 粘包问题
- tcp 粘包问题
- TCP粘包问题
- TCP 粘包问题
- tcp 粘包问题
- TCP粘包问题
- tcp粘包问题
- TCP粘包问题
- KF算法学习(二):例程验证
- Struts2学习(九)【OGNL表达式与Struts框架结合参数接收】
- 【爬虫学习6】爬虫自动获取并使用代理ip
- PullToRefresh使用详解(二)---重写BaseAdapter实现复杂XML下拉刷新
- Object.keys()
- TCP粘包/拆包--利用FixedLengthFrameDecoder解决TCP粘包问题
- dubbo的应用场景 RPC远程服务调用
- Struts2学习(十)【Struts2基本流程(源码)】
- SSL2783 2017年10月23日提高组T1 摆书(math)
- Wifi模块解析和启动流程
- 使用Photoshop吸取色值
- windows下安装tomcat
- 计算归并排序和快速排序算法排序100-1000个数组的时间(重点在时间精确到微妙us)
- Retrofit2使用中文文档