Netty 二进制通信协议设计

Netty 二进制 通信 协议 设计  二进制通信协议

Netty 二进制通信协议设计_第1张图片

2015年在台湾省九份铁路,这是一条日本人修建的用来采矿用的铁路,现在重新修建后作为客运铁路,一路上周围全是原始森林,一路上零零散散的小镇,很温馨。

Netty 二进制通信协议设计_第2张图片

Netty 二进制通信协议设计_第3张图片

Netty 二进制通信协议设计_第4张图片

Netty 二进制通信协议设计_第5张图片

Netty 二进制通信协议设计_第6张图片

Netty 二进制通信协议设计_第7张图片

Netty 二进制通信协议设计_第8张图片

                                                                                             微信公众号

                                                           王皓的GitHub:https://github.com/TenaciousDWang       

 

        今天开始写Netty实战部分仿微信写IM即时通讯系统,后面一系列是我对这段时间学习闪电侠教程的心得和总结,同时也记录和复习一下,部分图片用Excel画的,凑合看吧。

 

       这一篇主要来讲IM的通信协议设计及编码解码的程序设计。上篇文章讲了ByteBuf,也就是Netty的数据传输的容器,本质是一个二进制数据包。例如数据信息在客户端通过我们自定义的通讯协议编码为二进制数据包,然后在网络通过TCP/IP协议传送,传输过程与我们的应用层无关,服务端端只需要用对应的通讯协议解码成有效的信息即可。

 

Netty 二进制通信协议设计_第9张图片

       

       对于Java面向对象编程来说,这个信息就是一个Java对象,根据我们自定义的通讯协议编码为二进制数据包,通过公网传输,到达目的地端解码还原为Java对象进行后面的逻辑处理。

 

 

 

        接下来,我们来设计一个通信协议,首先我们定义一个魔数,这里参照Java的字节码文件,开头为cafe babe是Gosling定义的一个魔数,用来标志这个文件是一个Java类文件,同样我们仿照一下来定义我们数据包的标志,这里我们也使用四个字节来定义0x12345678。

 

        接下来一个字节为版本号,通常情况下是预留字段,用于协议升级的时候用到,多数情况下用不到,预留即可。

 

        序列化算法,表示将Java对象与二进制数据互转的方式,比如Java自带的序列化,json等,我们后面只用一个json即可,平时一直再用阿里的fastjson,所以这里的序列化方法与反序列化方法就直接使用toJSONBytes()与parseObject()。

 

        由于我们要做一个IM聊天功能,那么这个功能就会包含很多指令,例如登陆,登出,发送信息,接收信息等,每一个指令对应我们的一种逻辑,这里用一个字节来表示,可以表示256种指令。

 

        后面我们用4个字节来表示数据长度,最后是数据信息N个字节。基本上这一套协议对于服务端与客户端之间通信完全够用,属于万金油级别。

 

通信协议的实现

 

       首先抽象出一个Packet类,里面定义版本与指令,所有指令数据包对象都要实现这个Packet类。

 

Netty 二进制通信协议设计_第10张图片

 

      我们以登陆为例创建一个登陆指令数据包对象LoginRequestPacket,这里不再罗列userId,userName,password这三个属性的get与set方法。

 

Netty 二进制通信协议设计_第11张图片

       登陆的话我们简单定义用户ID,用户名,密码,实现getCommand方法,由于是登陆指令所以我们返回一个登陆指令常量。LOGIN_REQUEST作为常量,我们来创建一个接口盛放指令常量。

 

 

序列化过程实现

 

        数据包对象实现好后,接下来,我们来定义序列化接口。

 

Netty 二进制通信协议设计_第12张图片

    

        定义一个获取序列化标识的方法,序列化方式的标识我们参照指令常量也定义一个接口来盛放。再定义一个序列化方法和一个反序列化方法。

 

Netty 二进制通信协议设计_第13张图片

 

        然后来实现这个序列化接口,使用阿里的fastjson来序列化。实现上述三个方法,第一个方法返回序列化算法标识,第二个方法使用JSON.toJSONBytes(object)将对象转化为二进制数据包,

 

Netty 二进制通信协议设计_第14张图片

 

编码过程实现

 

Netty 二进制通信协议设计_第15张图片

 

        像把大象放进冰箱一样简单,第一步创建一块ByteBuf容器,第二步将需要传输的Java对象序列化为二进制数据,第三部将数据根据我们之前设计的通信协议填充到到ByteBuf容器中,返回一个ByteBuf数据包。

 

解码过程实现

 

        在PacketCodeC中创建构造器函数,用来初始化两个容器,用来盛放不同数据包类型与不同序列化工具。

 

Netty 二进制通信协议设计_第16张图片

 

        定义两个方法用于从容其中取出,序列化方式和指令数据包类型。

 

Netty 二进制通信协议设计_第17张图片

 

        接下来是解码过程。

 

Netty 二进制通信协议设计_第18张图片

 

        解码过程,首先验证魔数,获取序列化标识用于指定用什么方式序列化,再获取指令标识,用来获取需要转化为什么类型的Java对象,最后获取数据长度,根据长度创建一个byte数据用来存储从ByteBuf中获取的数据。当获得Java对象类型与二进制字节数据后,进行反序列化,返回一个Java对象用于后续逻辑处理。与编码一样,只不过反向过了一遍。

 

你可能感兴趣的:(Java,Netty,Netty,IM实战)