netty 粘包问题处理
netty 粘包问题处理
key words: netty 粘包 解包 半包 TCP
一般TCP粘包/拆包解决办法
- 定长消息,例如每个报文长度固定,不够补空格
- 使用回车换行符分割,在包尾加上分割符,例如Ftp协议
- 消息分割,头为长度(消息总长度或消息体长度),通常头用一个int32表示
- 复杂的应用层协议
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));//设置定长解码器 长度设置为30
public 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,我会把你的文章引用放到顶上去
netty 粘包问题处理的更多相关文章
- Netty 粘包/半包原理与拆包实战
Java NIO 粘包 拆包 (实战) - 史上最全解读 - 疯狂创客圈 - 博客园 https://www.cnblogs.com/crazymakercircle/p/9941658.html 本 ...
- Netty 粘包 拆包 | 史上最全解读
Netty 粘包/半包原理与拆包实战(史上最全) 疯狂创客圈 Java 聊天程序[ 亿级流量]实战系列之13 [博客园 总入口 ] 本文的源码工程:Netty 粘包/半包原理与拆包实战 源码 本实例是 ...
- Netty 粘包 & 拆包 & 编码 & 解码 & 序列化 介绍
目录: 粘包 & 拆包及解决方案 ByteToMessageDecoder 基于长度编解码器 基于分割符的编解码器 google 的 Protobuf 序列化介绍 其他的 前言 Netty 作 ...
- netty 粘包的解决策略
粘包问题的解决策略 由于底层的 TCP 无法理解上层业务数据,所以在底层是无法保证数据包不被拆分和重组的 , 这个问题只能通过上层的应用协议栈设计来解决,根据业界主流的协议的解决方案, 可以 ...
- Netty 粘包/拆包应用案例及解决方案分析
熟悉TCP变成的可以知道,无论是客户端还是服务端,但我们读取或者发送消息的时候,都需要考虑TCP底层粘包/拆包机制,下面我们先看一下TCP 粘包/拆包和基础知识,然后模拟一个没有考虑TCP粘包/拆包导 ...
- Netty - 粘包和半包(上)
在网络传输中,粘包和半包应该是最常出现的问题,作为 Java 中最常使用的 NIO 网络框架 Netty,它又是如何解决的呢?今天就让我们来看看. 定义 TCP 传输中,客户端发送数据,实际是把数据写 ...
- Netty - 粘包和半包(下)
上一篇介绍了粘包和半包及其通用的解决方案,今天重点来看一下 Netty 是如何实现封装成帧(Framing)方案的. 解码核心流程 之前介绍过三种解码器FixedLengthFrameDecoder. ...
- Netty粘包问题(六)
netty使用tcp/ip协议传输数据,而tcp/ip协议是类似水流一样的数据传输方法.多次访问的时候可能出现粘包的问题,解决这种问题的方式有如下几种. 一.定长数据流 二.特殊结束符 三.
- 2.Netty的粘包、拆包(一)
Netty粘包.拆包 1.什么是拆包.粘包 (1)拆包.粘包介绍 TCP是个"流"协议,所谓流,就是没有界限的一串数据.大家可以想想河里的流水,是连成一片的,其间并没有分界线.TC ...
随机推荐
- mysql 5.7压缩包安装笔记
转载请注明出处http://www.cnblogs.com/havedream/p/5075263.html 重装系统之后准备安装mysql,看到官网上有mysql 5.7.10可以下载就点了,然后就 ...
- Android系统四层架构分享
Android系统四层架构 个人网站:http://www.51pansou.com Android视频下载:Android视频 Android源码下载:Android源码 如果把Android系统看 ...
- LevelDB源码剖析
LevelDB的公共部件并不复杂,但为了更好的理解其各个核心模块的实现,此处挑几个关键的部件先行备忘. Arena(内存领地) Arena类用于内存管理,其存在的价值在于: 提高程序性能,减少Heap ...
- varnish状态引擎1
vcl: state engine:各引擎之间存一定程度上的相关性:前一个engine如果可以有多种下游engine,则上游engine需要用return指明 要转移的下游engine vcl_rec ...
- Yii 增删改查 测试记录
亲们, 我是yii小白 不要笑话我奥.今天白天写一个管理模块涉及到 yii ar 下的 curd 操作,做 update 操作时纠结了好久,今天晚上花点时间学习, 下面写下我的测试记录 代码如下: ...
- Java 第二天
1.不带访问修饰符号的类成员变量默认是friendly(可以同一个包中访问) 2.protected的类成员可以在同一个包及其子类中访问 3.方法中可以定义内部类(如下面的代码),该类只能访问方法中的 ...
- hadoop-cdh with snappy
hadoop: 2.5.0-cdh5.3.6 snappy: 1.1.3 hadoop 2.*不需要hadoop-snappy.只要机器上安装好snappy, 直接编译就可以 编译命令: mvn cl ...
- 007-python基础-pyc是什么
3.1 解释型语言和编译型语言 计算机是不能够识别高级语言的,所以当我们运行一个高级语言程序的时候,就需要一个"翻译机"来从事把高级语言转变成计算机能读懂的机器语言的过程.这个过程 ...
- 理解ruby on rails中的ActiveRecord::Relation
ActiveRecord::Relation是rails3中添加的.rails2中的finders, named_scope, with_scope 等用法,在rails3统一为一种Relation用 ...
- 安装boost1.57.0__注意之前mgiza似乎因为boost没有安装也没有完全编译成功
首先下载(废话) 解压, ./bootstrap.sh 之后在运行b2 ./b2 -j8 --prefix=$PWD --libdir=$PWD/lib64 --layout=system link= ...