博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
netty 粘包问题处理
阅读量:5233 次
发布时间:2019-06-14

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

netty 粘包问题处理

key words: netty 粘包 解包 半包 TCP

一般TCP粘包/拆包解决办法

  1. 定长消息,例如每个报文长度固定,不够补空格
  2. 使用回车换行符分割,在包尾加上分割符,例如Ftp协议
  3. 消息分割,头为长度(消息总长度或消息体长度),通常头用一个int32表示
  4. 复杂的应用层协议

netty的几种解决方案

特殊分隔符解码器:DelimiterBasedFrameDecoder

客户端发送消息

String message = "netty is a nio server framework &"                +"which enables quick and easy development &"                +"of net applications such as protocol &"                +"servers and clients!";

服务端添加解码器:DelimiterBasedFrameDecoder

ByteBuf delimiter = Unpooled.copiedBuffer("&".getBytes());ch.pipeline().addLast(new DelimiterBasedFrameDecoder(1024,delimiter));//1024表示单条消息的最大长度,解码器在查找分隔符的时候,达到该长度还没找到的话会抛异常ch.pipeline().addLast(new StringDecoder());....ch.pipeline().addLast(new StringEncoder());

打印输出:

接收消息:[netty is a nio server framework ]接收消息:[which enables quick and easy development ]接收消息:[of net applications such as protocol]接收消息:[servers and clients!]

参数解释:

public DelimiterBasedFrameDecoder(int maxFrameLength, ByteBuf delimiter) {    this(maxFrameLength, true, delimiter);}maxFrameLength:解码的帧的最大长度stripDelimiter:解码时是否去掉分隔符failFast:为true,当frame长度超过maxFrameLength时立即报TooLongFrameException异常,为false,读取完整个帧再报异常delimiter:分隔符

定长解码器:FixedLengthFrameDecoder

参数说明:

  • frameLength:帧的固定长度

服务端

ch.pipeline().addLast(new FixedLengthFrameDecoder(30));//设置定长解码器 长度设置为30public void channelRead(ChannelHandlerContext ctx, Object msg)        throws Exception {    System.out.println("接收客户端msg:["+msg+"]");    ByteBuf echo=Unpooled.copiedBuffer(MESSAGE.getBytes());    ctx.writeAndFlush(echo);}

客户端

ch.pipeline().addLast(new FixedLengthFrameDecoder(30));//设置定长解码器

基于包头不固定长度的解码器:LengthFieldBasedFrameDecoder

参数说明

  • maxFrameLength:解码的帧的最大长度
  • lengthFieldOffset:长度属性的起始位(偏移位),包中存放有整个大数据包长度的字节,这段字节的其实位置
  • lengthFieldLength:长度属性的长度,即存放整个大数据包长度的字节所占的长度
  • lengthAdjustmen:长度调节值,在总长被定义为包含包头长度时,修正信息长度。
  • initialBytesToStrip:跳过的字节数,根据需要我们跳过lengthFieldLength个字节,以便接收端直接接受到不含“长度属性”的内容
  • failFast :为true,当frame长度超过maxFrameLength时立即报TooLongFrameException异常,为false,读取完整个帧再报异常

备注:如果长度解析失误,(过大,就直接丢弃这个包;过小,1、netty不抛出异常;2、校验通不过)

源码:int frameLengthInt = (int) frameLength;if (in.readableBytes() < frameLengthInt) {    return null;}

封包时配合使用LengthFieldPrepender,很容易加上包长度

包头添加总包长度字节:LengthFieldPrepender

在发布时,自动在帧的头部加上长度

参数说明:

  • lengthFieldLength:长度属性的字节长度
  • lengthIncludesLengthFieldLength:false,长度字节不算在总长度中,true,算到总长度中

    应用:

    pipeline.addLast("frameEncode", new LengthFieldPrepender(4, false));

官方说明:

编码类,自动将+----------------+  | "HELLO, WORLD" |  +----------------+格式的数据转换成如下格式的数据,    +--------+----------------+ + 0x000C | "HELLO, WORLD" | +--------+----------------+如果lengthIncludesLengthFieldLength设置为true,则编码为(多了两个字节)+--------+----------------+ + 0x000E | "HELLO, WORLD" | +--------+----------------+

备注

当时解决问题和记录时,是查阅了官网和几篇博客,如果里面内容有copy的地方,请留言url,我会把你的文章引用放到顶上去

转载于:https://www.cnblogs.com/sloong/p/5047743.html

你可能感兴趣的文章
如何将Excel导入到DataGridView中
查看>>
高级sed编程
查看>>
Android自定义Dialog效果
查看>>
第一章 安装webpack
查看>>
跳一跳辅助使用教程
查看>>
还不错的html5引擎
查看>>
腾讯云服务器遭到勒索病毒经历
查看>>
tomcat安装
查看>>
Django知识点
查看>>
使用JExcelAPI组件操作Excel文件
查看>>
php模块memcache和memcached区别分析
查看>>
字符串匹配dp+bitset,滚动数组优化——hdu5745(经典)
查看>>
1月28日 表单验证和正则表达式
查看>>
正则表达式
查看>>
基于openfire的ios聊天demo
查看>>
3D游戏中的画质与效率适配
查看>>
Linux 命令
查看>>
字符串中字符调换
查看>>
用C#编写猜数、九九乘法表‘、迷宫
查看>>
HA 部署wordpress
查看>>