Netty 通讯协议结构设计的总结

key words: 通信,协议,结构设计,netty,解码器,LengthFieldBasedFrameDecoder

原创

包含与机器/设备的通讯协议结构的设计,安全性,数据有效性的设计思路记录

通讯协议结构选择

按照解决TCP粘包的解决方案的协议设计思路,大部分情况也就是:

  1. 定长消息,每个报文固定长度,不够补0或其他
  2. 用特殊字符/字节做分割符,遇到分隔符拆包
  3. 不定长报文,包头带长度,以长度字节为准进行消息分割

每种处理方式都有不同的适用场景(例如 方法2适合文本传输过程中的拆包,却不适合byte[]数据的拆包),方法1,2,3在netty里面得到了很好的支持,具体可以见详见netty 在TCP粘包问题处理这篇文章

对于物联通讯来说,传输是最佳数据类型,所以方法3是比较合适的,这就要求通讯协议在设计时,需要把报文长度放在最前面,下面看看netty自带的基于包头不定长的解码器,能省去自己解决粘包的时间,把关注点放到业务数据的处理上

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

LengthFieldBasedFrameDecoder参数说明

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

有了这个解码器,就很轻松完成拆包工作,拆出来的业务数据,再交由下一个decoder handler处理

那么封包呢?封包也不用自己加长度,直接在ChannelPipeline的最后加上LengthFieldPrepender 编码器

LengthFieldPrepender 编码器

参数说明:

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

配合使用LengthFieldPrepender,很容易就完成了,这样在flush前,netty自动会为报文加上一个length。

需要注意的是,在业务处理器里面要响应write时,请用pipeline.write,如果直接用ctx.write,最后报文就不会加长度,因为不会进入到LengthFieldPrepender编码器中去

示例代码:

@Component("MyChannelInit")
public class MyChannelInitializer extends ChannelInitializer<SocketChannel> { @Override
protected void initChannel(SocketChannel channel) throws Exception {
ChannelPipeline pipeline = channel.pipeline();
//pipeline.addLast(new LoggingHandler(LogLevel.INFO));
pipeline.addLast("frameDecode",new LengthFieldBasedFrameDecoder(1024,0,2,-2,2));
pipeline.addLast("decoder", new MyDataDecoder());//in 1
pipeline.addLast("handler", new MyInboundHandler());//in 2 pipeline.addLast(new IdleStateHandler(40, 0, 0));//out3
//pipeline.addLast("encoder", new DataEncoder());//out2
pipeline.addLast("frameEncode",new LengthFieldPrepender(2,true));//out1
}
}

收到设备发过来的数据,new LengthFieldBasedFrameDecoder(1024,0,2,-2,2):

解码最大长度1024,起始偏移0,长度参数占字节数2,总长包含长度字节数,修正长度-2,传输到下一个Decoder时数据,跳过字节数2(也就是不带长度)

发送到设备的数据,new LengthFieldPrepender(2,true),自动加上两个字节的长度

通讯数据的保密性

如果不想让人拦截有效数据和入侵破坏,通讯数据最好还是带上加密,最好还是动态的,不要说什么MD5 RSA DES之类的,终端硬件那边处理器性能没那么强悍,服务端这边也影响性能

所以,哪怕就是个简单的加解密,也足够让90%的人知难而退(大部分人没事突突你干嘛(-__-)b)

我们当时设计了token机制,token有时效性,每隔一段时间就需要从服务端获取新的token值,而数据解密的参数就跟token有关,这样就算拿着数据去分析规律,由于token值时不时变换,导致解密方法和解密参数都不一样,这样也许能起到部分作用

因为token,一段时间就会失效,所以我们就有一条专门获取token的指令,为了保证协议的一致性(凡是数据传递都需要token),所以订了一个特殊的token和特殊的加解密,这样可以保证获取token获取能够通过程序的辨识

所以数据结构的头 为: LENGTH + TOKEN

通讯数据的有效性验证

对于高要求的的数据传输,是否有必要进行校验,CRC16 CRC32校验应该就够了

数据结构的头 :LENGTH + TOKEN + CRC + DATA

后面的就是具体传输的数据的处理

Netty 对通讯协议结构设计的启发和总结的更多相关文章

  1. netty 自定义通讯协议

    Netty中,通讯的双方建立连接后,会把数据按照ByteBuf的方式进行传输,例如http协议中,就是通过HttpRequestDecoder对ByteBuf数据流进行处理,转换成http的对象.基于 ...

  2. netty 支持多种通讯协议

    通讯协议,指的是把Netty通讯管道中的二进制流转换为对象.把对象转换成二进制流的过程.转换过程追根究底还是ChannelInboundHandler.ChannelOutboundHandler的实 ...

  3. 基于dubbo框架下的RPC通讯协议性能测试

    一.前言 Dubbo RPC服务框架支持丰富的传输协议.序列化方式等通讯相关的配置和扩展.dubbo执行一次RPC请求的过程大致如下:消费者(Consumer)向注册中心(Registry)执行RPC ...

  4. [转]netty对http协议解析原理

    本文主要介绍netty对http协议解析原理,着重讲解keep-alive,gzip,truncked等机制,详细描述了netty如何实现对http解析的高性能. 1 http协议 1.1 描述 标示 ...

  5. MODBUS-RTU通讯协议简介

    MODBUS-RTU通讯协议简介   什么是MODBUS? MODBUS 是MODICON公司最先倡导的一种软的通讯规约,经过大多数公司 的实际应用,逐渐被认可,成为一种标准的通讯规约,只要按照这种规 ...

  6. dubbo源码分析4-基于netty的dubbo协议的server

    dubbo源码分析1-reference bean创建 dubbo源码分析2-reference bean发起服务方法调用 dubbo源码分析3-service bean的创建与发布 dubbo源码分 ...

  7. 【读书笔记】iOS-防止通讯协议被轻易破解的方法

    开发者可以选择类似Protobuf之类的二进制通讯协议或者自己实现通讯协议,对于传输的内容进行一定程度的加密,以增加黑客破解协议的难度. 参考资料: <iOS开发进阶> --唐巧

  8. CNN 美国有线电视新闻网 wapCNN WAP 指无线应用通讯协议 ---- 美国有线电视新闻网 的无线应用

    wapCNN  wap指无线应用通讯协议  CNN美国有线电视新闻网   固, wapCNN 美国有线电视新闻网的无线应用 -------------------------------------- ...

  9. 几种通讯协议的比较RMI > Httpinvoker >= Hessian >> Burlap >> web service

    一.综述本文比较了RMI,Hessian,Burlap,Httpinvoker,web service等5种通讯协议的在不同的数据结构和不同数据量时的传输性能.RMI是java语言本身提供的远程通讯协 ...

随机推荐

  1. 解决Access连接 accdb 不可识别的数据库格式异常

    在Access07之前的数据库后缀名均为*.mdb 而连接字符串写成Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\myFolder\*.mdb ;Pe ...

  2. 反编译工具(.NET Reflector )

    1.下载安装原程序,然后运行 Reflector.exe 2.运行注册机,点击 Generate 获得序列号 3.把序列号填写到 Reflector 软件上4.断开网络,点击 Activate 激活( ...

  3. php header 函数详解

    网页的缓存是由 HTTP消息头中的“Cache-control”来控制的,常见的取值有private.no-cache.max-age.must- revalidate等,默认为private.其作用 ...

  4. C++求1!到n!的和

    题目内容:求1!+2!+3!+4!+……+n!的结果. 输入描述:输入不多于50个正整数的数据n(1<=n<=12). 输出描述:对于每个n,输出计算结果.每个计算结果应单独占一行. 参考 ...

  5. VMware虚拟机升级过程中遇到的一点问题

    在将VWware由9.0升级到10.0的过程中,出现如下图的错误:        failed to create the requested registry key Key:Installer e ...

  6. Oracle sql trace

    一.SQL_TRACE说明 1.1.在全局启用 在参数文件(pfile/spfile)中指定:sql_trace =true 1.2.在当前session级设置 启用当前session的跟踪: alt ...

  7. 16.python中的浅拷贝和深拷贝

    在讲什么是深浅拷贝之前,我们先来看这样一个现象: a = ['scolia', 123, [], ] b = a[:] b[2].append(666) print a print b

  8. 【设计模式】策略模式 (Strategy Pattern)

    策略模式是一种很简单的基础模式,用于封装一系列算法,使客户端的访问独立于算法的实现.我们可以”井中取水”来形象的描述策略模式.“取水”是一个动作,完成这个动作的方式有很多中,可以直接用手提.可以用水车 ...

  9. JavaWeb之Servlet:请求 与 响应

    1 引入 浏览器和服务器的种类都有很多,要在它们之间通讯,必定要遵循一定的准则,而http协议就是这样的一个"准则". Http协议:规定了 浏览器 和 服务器 数据传输的一种格式 ...

  10. static关键字的作用

    static可以用来定义静态成员变量.静态函数.静态代码块. 静态成员变量的语法特点 定义方法:在成员变量前面加上static class Person{ static int i; //静态成员变量 ...