网络编程之每天学习一点点[day10]-----netty之tcp拆包粘包解决方案二“固定字符串长度”
发布日期:2021-06-30 13:45:24
浏览次数:2
分类:技术文章
本文共 5150 字,大约阅读时间需要 17 分钟。
固定字符串的长度的方式主要是依赖于这个类,先看下jdk中的解释
. . . .FixedLengthFrameDecoder
A decoder that splits the received ByteBuf
s by the fixed number of bytes. For example, if you received the following four fragmented packets:
+---+----+------+----+ | A | BC | DEFG | HI | +---+----+------+----+A
FixedLengthFrameDecoder
(3)
will decode them into the following three packets with the fixed length: +-----+-----+-----+ | ABC | DEF | GHI | +-----+-----+-----+
翻译过来就是:
这个类是一个将接收的byteebuf缓冲对象按照固定的字节长度分割的解码器,例如,如果你收到的是以下片段,
+---+----+------+----+ | A | BC | DEFG | HI | +---+----+------+----+
一个按照固定3个字节拆分的解码器将会分割成:
+-----+-----+-----+ | ABC | DEF | GHI | +-----+-----+-----+
我们看下代码:
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 Server { public static void main(String[] args) throws Exception{ //1 创建2个线程,一个是负责接收客户端的连接。一个是负责进行数据传输的 EventLoopGroup pGroup = new NioEventLoopGroup(); EventLoopGroup cGroup = new NioEventLoopGroup(); //2 创建服务器辅助类 ServerBootstrap b = new ServerBootstrap(); b.group(pGroup, cGroup) .channel(NioServerSocketChannel.class) .option(ChannelOption.SO_BACKLOG, 1024) .option(ChannelOption.SO_SNDBUF, 32*1024) .option(ChannelOption.SO_RCVBUF, 32*1024) .childHandler(new ChannelInitializer() { @Override protected void initChannel(SocketChannel sc) throws Exception { //设置定长字符串接收 sc.pipeline().addLast(new FixedLengthFrameDecoder(5)); //设置字符串形式的解码 sc.pipeline().addLast(new StringDecoder()); sc.pipeline().addLast(new ServerHandler()); } }); //4 绑定连接 ChannelFuture cf = b.bind(8765).sync(); //等待服务器监听端口关闭 cf.channel().closeFuture().sync(); pGroup.shutdownGracefully(); cGroup.shutdownGracefully(); } }
ServerHandler
import io.netty.buffer.Unpooled;import io.netty.channel.ChannelHandlerAdapter;import io.netty.channel.ChannelHandlerContext;public class ServerHandler extends ChannelHandlerAdapter { @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { System.out.println(" server channel active... "); } @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { String request = (String)msg; System.out.println("Server :" + msg); String response = request ; ctx.writeAndFlush(Unpooled.copiedBuffer(response.getBytes())); } @Override public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable t) throws Exception { }}
Client
import io.netty.bootstrap.Bootstrap;import io.netty.buffer.Unpooled;import io.netty.channel.ChannelFuture;import io.netty.channel.ChannelInitializer;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;public class Client { public static void main(String[] args) throws Exception { EventLoopGroup group = new NioEventLoopGroup(); Bootstrap b = new Bootstrap(); b.group(group) .channel(NioSocketChannel.class) .handler(new ChannelInitializer() { @Override protected void initChannel(SocketChannel sc) throws Exception { sc.pipeline().addLast(new FixedLengthFrameDecoder(5)); sc.pipeline().addLast(new StringDecoder()); sc.pipeline().addLast(new ClientHandler()); } }); ChannelFuture cf = b.connect("127.0.0.1", 8765).sync(); cf.channel().writeAndFlush(Unpooled.wrappedBuffer("aaaaabbbbb".getBytes())); cf.channel().writeAndFlush(Unpooled.copiedBuffer("ccccccc".getBytes())); //等待客户端端口关闭 cf.channel().closeFuture().sync(); group.shutdownGracefully(); }}
ClientHandler
import io.netty.channel.ChannelHandlerAdapter;import io.netty.channel.ChannelHandlerContext;public class ClientHandler extends ChannelHandlerAdapter{ @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { System.out.println("client channel active... "); } @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { String response = (String)msg; System.out.println("Client: " + response); } @Override public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { }}
打印:
client
client channel active... Client: aaaaaClient: bbbbbClient: ccccc
Server
server channel active... Server :aaaaaServer :bbbbbServer :ccccc
可以看到客户端发送aaaaabbbbb,被完美分割成aaaaa和bbbbb两部分,但ccccccc含有7个字符,服务器端只能收到ccccc
缺失了2个字符,这是因为使用定长字符串方式只会发送符合长度的字符串,多余的不会被发送,解决办法是可以补齐缺少的字s符,比如给多的cc补三个空格。这样server将会收到:
server channel active... Server :aaaaaServer :bbbbbServer :cccccServer :cc
转载地址:https://jeffsheng.blog.csdn.net/article/details/80809390 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!
发表评论
最新留言
留言是一种美德,欢迎回访!
[***.207.175.100]2024年04月12日 11时24分26秒
关于作者
喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
JAVA使用HBase的Rowkey精确批量处理
2019-05-01
Collections排序sort排序list,单个及多条件排序
2019-05-01
Mysql中where 条件中加 if 判断-纯jdbc
2019-05-01
分布式数据中间件TDDL、Amoeba、Cobar、MyCAT架构比较
2019-05-01
Sharding-JDBC的SQL引擎(Druid)处理的支持情况总结
2019-05-01
大数据开发者应该知道的分布式系统 CAP 理论
2019-05-01
HBase在人工智能场景的使用
2019-05-01
Apache Spark 2.4 中解决复杂数据类型的内置函数和高阶函数介绍
2019-05-01
数据结构与算法?看这篇就够了!
2019-05-01
Apache Kafka:优化部署的 10 种最佳实践
2019-05-01
HBase 中加盐之后的表如何读取:Spark 篇
2019-05-01
一篇文章了解 Spark Shuffle 内存使用
2019-05-01
【免费下载】某平台3980元Hadoop大数据/机器学习全套视频,仅此1次
2019-05-01
Apache Hive 联邦查询(Query Federation)
2019-05-01
为什么说流处理即未来?
2019-05-01
Leetcode 剑指 Offer 39. 数组中出现次数超过一半的数字 c#
2019-05-01
Leetcode 35. 搜索插入位置 c#
2019-05-01
LeetCode64:最小路径和
2019-05-01
LeetCode931. 下降路径最小和
2019-05-01