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));//设置定长解码器 长度设置为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 粘包问题处理的更多相关文章

  1. Netty 粘包/半包原理与拆包实战

    Java NIO 粘包 拆包 (实战) - 史上最全解读 - 疯狂创客圈 - 博客园 https://www.cnblogs.com/crazymakercircle/p/9941658.html 本 ...

  2. Netty 粘包 拆包 | 史上最全解读

    Netty 粘包/半包原理与拆包实战(史上最全) 疯狂创客圈 Java 聊天程序[ 亿级流量]实战系列之13 [博客园 总入口 ] 本文的源码工程:Netty 粘包/半包原理与拆包实战 源码 本实例是 ...

  3. Netty 粘包 & 拆包 & 编码 & 解码 & 序列化 介绍

    目录: 粘包 & 拆包及解决方案 ByteToMessageDecoder 基于长度编解码器 基于分割符的编解码器 google 的 Protobuf 序列化介绍 其他的 前言 Netty 作 ...

  4. netty 粘包的解决策略

    粘包问题的解决策略      由于底层的 TCP 无法理解上层业务数据,所以在底层是无法保证数据包不被拆分和重组的 , 这个问题只能通过上层的应用协议栈设计来解决,根据业界主流的协议的解决方案, 可以 ...

  5. Netty 粘包/拆包应用案例及解决方案分析

    熟悉TCP变成的可以知道,无论是客户端还是服务端,但我们读取或者发送消息的时候,都需要考虑TCP底层粘包/拆包机制,下面我们先看一下TCP 粘包/拆包和基础知识,然后模拟一个没有考虑TCP粘包/拆包导 ...

  6. Netty - 粘包和半包(上)

    在网络传输中,粘包和半包应该是最常出现的问题,作为 Java 中最常使用的 NIO 网络框架 Netty,它又是如何解决的呢?今天就让我们来看看. 定义 TCP 传输中,客户端发送数据,实际是把数据写 ...

  7. Netty - 粘包和半包(下)

    上一篇介绍了粘包和半包及其通用的解决方案,今天重点来看一下 Netty 是如何实现封装成帧(Framing)方案的. 解码核心流程 之前介绍过三种解码器FixedLengthFrameDecoder. ...

  8. Netty粘包问题(六)

    netty使用tcp/ip协议传输数据,而tcp/ip协议是类似水流一样的数据传输方法.多次访问的时候可能出现粘包的问题,解决这种问题的方式有如下几种. 一.定长数据流 二.特殊结束符 三.

  9. 2.Netty的粘包、拆包(一)

    Netty粘包.拆包 1.什么是拆包.粘包 (1)拆包.粘包介绍 TCP是个"流"协议,所谓流,就是没有界限的一串数据.大家可以想想河里的流水,是连成一片的,其间并没有分界线.TC ...

随机推荐

  1. SqlServer存储过程学习笔记(增删改查)

    * IDENT_CURRENT 返回为任何会话和任何作用域中的特定表最后生成的标识值. CREATE PROCEDURE [dbo].[PR_NewsAffiche_AddNewsEntity] ( ...

  2. recurse_array_change_key_case()递规返回字符串键名全为小写或大写的数组

    //递归返回字符串键名全为小写或大写的数组function recurse_array_change_key_case(&$input, $case = CASE_LOWER){    if( ...

  3. Java打印温度转换表

    按5度的增量打印出一个从摄氏温度到华氏温度的转换表.转换公式为h=c*9/5+32,其中h为华氏温度,c为摄氏温度. 主要是“按5度的增量”这个要求,一般摄氏温度的起始分别为0度和40度,所以循环可以 ...

  4. AngularJs记录学习04

    <html> <head> <title>Angular JS Views</title> <script src="js/Angula ...

  5. python内建函数-数字相关

    本篇对于数字有关的内置函数进行总结. 数字包括 int() , long() , float() , complex() ,这些函数都能够用来进行数值类型的转换.同时这些函数也接受字符串参数,返回字符 ...

  6. 6.python字符串-内置方法列举

    所谓内置方法,就是凡是字符串都能用的方法,这个方法在创建字符串的类中,下面是总结: 首先,我们要学习一个获取帮助的内置函数 help(对象) ,对象可以是一个我们创建出来的,也可以是创建对象的那个类, ...

  7. Qualcomm device使用ION memory manager取代PMEM

    今天写好device,成功编译出CM,接下来肯定是调戏啦(你什么都没看到)~ BUG肯定也是一堆堆的!一开机,果然一堆error~可是尼玛,大蛋一放假就不见人了!!! 我自己折腾几个小时容易么我,我谷 ...

  8. System V共享内存区

    要点 shell查看命令:ipcs -m 主要函数 #include <sys/shm.h> //oflag=IPC_CREAT|IPC_EXCL|0644组合 //创建一个内存共享区 i ...

  9. DTW

    DTW主要是应用在孤立词识别的算法,用来识别一些特定的指令比较好用,这个算法是基于DP(动态规划)的算法基础上发展而来的.这里介绍语音识别就先介绍下语音识别的框架,首先我们要有一个比对的模版声音,然后 ...

  10. VS2012 常用web.config配置解析之自定义配置节点

    在web.config文件中拥有一个用户自定义配置节点configSections,这个节点可以方便用户在web.config中随意的添加配置节点,让程序更加灵活(主要用于第三方插件的配置使用) 自定 ...