博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
netty 解决TCP粘包与拆包问题(二)
阅读量:2204 次
发布时间:2019-05-03

本文共 6260 字,大约阅读时间需要 20 分钟。

TCP以流的方式进行数据传输,上层应用协议为了对消息的区分,采用了以下几种方法。

1.消息固定长度

2.第一篇讲的回车换行符形式

3.以特殊字符作为消息结束符的形式

4.通过消息头中定义长度字段来标识消息的总长度

 

一、采用指定分割符解决粘包与拆包问题

服务端

1 package com.ming.netty.nio.stickpack; 2  3  4  5 import java.net.InetSocketAddress; 6  7 import io.netty.bootstrap.ServerBootstrap; 8 import io.netty.buffer.ByteBuf; 9 import io.netty.buffer.Unpooled;10 import io.netty.channel.ChannelFuture;11 import io.netty.channel.ChannelInitializer;12 import io.netty.channel.ChannelOption;13 import io.netty.channel.EventLoopGroup;14 import io.netty.channel.nio.NioEventLoopGroup;15 import io.netty.channel.socket.SocketChannel;16 import io.netty.channel.socket.nio.NioServerSocketChannel;17 import io.netty.handler.codec.DelimiterBasedFrameDecoder;18 import io.netty.handler.codec.string.StringDecoder;19 import io.netty.handler.logging.LogLevel;20 import io.netty.handler.logging.LoggingHandler;21 22 public class EchoServer {23 24     public void bind(String addr,int port) throws Exception{25         EventLoopGroup bossGroup=new NioEventLoopGroup();26         EventLoopGroup workGroup=new NioEventLoopGroup();27         try {28             ServerBootstrap server=new ServerBootstrap();29             server.group(bossGroup,workGroup)30                   .channel(NioServerSocketChannel.class)31                   .option(ChannelOption.SO_BACKLOG, 100)32                   .handler(new LoggingHandler(LogLevel.INFO))33                   .childHandler(new ChannelInitializer
() {34 35 @Override36 protected void initChannel(SocketChannel sc) throws Exception {37 ByteBuf delimiter=Unpooled.copiedBuffer("$_".getBytes());//指定消息分割符处理数据38 sc.pipeline().addLast(new DelimiterBasedFrameDecoder(1024, delimiter));//如果取消了分割符解码,就会出现TCP粘包之类的问题了39 sc.pipeline().addLast(new StringDecoder());40 sc.pipeline().addLast(new EchoServerHandler());41 42 }43 44 });45 ChannelFuture f=server.bind(new InetSocketAddress(addr, port)).sync();46 System.out.println("启动服务器:"+f.channel().localAddress());47 //等等服务器端监听端口关闭48 f.channel().closeFuture().sync();49 } catch (Exception e) {50 e.printStackTrace();51 }finally{52 bossGroup.shutdownGracefully();53 workGroup.shutdownGracefully();54 }55 }56 57 58 public static void main(String[] args) throws Exception{59 new EchoServer().bind("192.168.1.108", 8500);60 }61 62 }
1 package com.ming.netty.nio.stickpack; 2  3 import io.netty.buffer.ByteBuf; 4 import io.netty.buffer.Unpooled; 5 import io.netty.channel.ChannelHandlerAdapter; 6 import io.netty.channel.ChannelHandlerContext; 7  8 public class EchoServerHandler extends ChannelHandlerAdapter{ 9 10     int count=0;11     12     @Override13     public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {14         15         String body=(String)msg;16         System.out.println("服务器收到"+(++count)+"次客户端消息,消息是:"+body);17         body+="$_";18         ByteBuf rep=Unpooled.copiedBuffer(body.getBytes());19         ctx.writeAndFlush(rep);20     }21 22     @Override23     public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {24         cause.printStackTrace();25         ctx.close();26     }27 28     29 }

 

客服端:

1 package com.ming.netty.nio.stickpack; 2  3 import java.net.InetSocketAddress; 4  5 import io.netty.bootstrap.Bootstrap; 6 import io.netty.buffer.ByteBuf; 7 import io.netty.buffer.Unpooled; 8 import io.netty.channel.ChannelFuture; 9 import io.netty.channel.ChannelInitializer;10 import io.netty.channel.ChannelOption;11 import io.netty.channel.EventLoopGroup;12 import io.netty.channel.nio.NioEventLoopGroup;13 import io.netty.channel.socket.SocketChannel;14 import io.netty.channel.socket.nio.NioSocketChannel;15 import io.netty.handler.codec.DelimiterBasedFrameDecoder;16 import io.netty.handler.codec.string.StringDecoder;17 18 public class EchoClient {19 20     public void connect(String addr,int port) throws Exception{21         EventLoopGroup workGroup=new NioEventLoopGroup();22         try {23             Bootstrap b=new Bootstrap();24             b.group(workGroup)25              .channel(NioSocketChannel.class)26              .option(ChannelOption.TCP_NODELAY, true)27              .handler(new ChannelInitializer
() {28 29 @Override30 protected void initChannel(SocketChannel sc) throws Exception {31 ByteBuf delimiter=Unpooled.copiedBuffer("$_".getBytes());//指定消息分割符32 sc.pipeline().addLast(new DelimiterBasedFrameDecoder(1024, delimiter));33 sc.pipeline().addLast(new StringDecoder());34 sc.pipeline().addLast(new EchoClientHandler());35 }36 37 });38 39 ChannelFuture f=b.connect(new InetSocketAddress(addr, port)).sync();40 System.out.println("连接服务器:"+f.channel().remoteAddress()+",本地地址:"+f.channel().localAddress());41 f.channel().closeFuture().sync();//等待客户端关闭连接42 43 } catch (Exception e) {44 e.printStackTrace();45 }finally{46 workGroup.shutdownGracefully();47 }48 }49 50 public static void main(String[] args) throws Exception{51 new EchoClient().connect("192.168.1.108", 8500);52 }53 }
1 package com.ming.netty.nio.stickpack; 2  3 import io.netty.buffer.Unpooled; 4 import io.netty.channel.ChannelHandlerAdapter; 5 import io.netty.channel.ChannelHandlerContext; 6  7 public class EchoClientHandler extends ChannelHandlerAdapter{ 8  9     int count=0;10     11     static final String REQUEST_TEST_DATA="I love you....$_";12 13     14     15     @Override16     public void channelActive(ChannelHandlerContext ctx) throws Exception {17         //发送消息,模拟发送向服务端发送1000条数据18         for(int i=0,j=1000;i

 

很多事情看代码解决,hello world!

 

下篇打算写定长解码了...最后写一下通过消息头中定义长度字段来标识消息的总长度来解码玩玩....

 

感觉可以点个赞吧,好自恋一把

 

转载于:https://www.cnblogs.com/huzi007/p/5547896.html

你可能感兴趣的文章
集成测试(一)—— 使用PHP页面请求Spring项目的Java接口数据
查看>>
使用Maven构建的简单的单模块SSM项目
查看>>
Intellij IDEA使用(十四)—— 在IDEA中创建包(package)的问题
查看>>
FastDFS集群架构配置搭建(转载)
查看>>
HTM+CSS实现立方体图片旋转展示效果
查看>>
FFmpeg 命令操作音视频
查看>>
问题:Opencv(3.1.0/3.4)找不到 /opencv2/gpu/gpu.hpp 问题
查看>>
目的:使用CUDA环境变量CUDA_VISIBLE_DEVICES来限定CUDA程序所能使用的GPU设备
查看>>
问题:Mysql中字段类型为text的值, java使用selectByExample查询为null
查看>>
程序员--学习之路--技巧
查看>>
解决问题之 MySQL慢查询日志设置
查看>>
contOS6 部署 lnmp、FTP、composer、ThinkPHP5、docker详细步骤
查看>>
TP5.1模板布局中遇到的坑,配置完不生效解决办法
查看>>
PHPstudy中遇到的坑No input file specified,以及传到linux环境下遇到的坑,模板文件不存在
查看>>
TP5.1事务操作和TP5事务回滚操作多表
查看>>
composer install或composer update 或 composer require phpoffice/phpexcel 失败解决办法
查看>>
TP5.1项目从windows的Apache服务迁移到linux的Nginx服务需要注意几点。
查看>>
win10安装软件 打开时报错 找不到 msvcp120.dll
查看>>
PHPunit+Xdebug代码覆盖率以及遇到的问题汇总
查看>>
PHPUnit安装及使用
查看>>