跟闪电侠学Netty:Netty即时聊天实战与底层原理
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

8.2 通信协议的设计

通信协议的设计如下图所示。

1.第一个字段是魔数,通常情况下为固定的几字节(这里规定为4字节)。为什么需要这个字段,而且还是一个固定的数?假设我们在服务器上开了一个端口,比如80端口,如果没有这个魔数,任何数据包传递到服务器,服务器都会根据自定义协议来进行处理,包括不符合自定义协议规范的数据包。例如,直接通过http://服务器IP来访问服务器(默认为80端口),服务端收到的是一个标准的HTTP协议数据包,但是它仍然会按照事先约定好的协议来处理HTTP协议,显然,这是会解析出错的。而有了这个魔数之后,服务端首先取出前面4字节进行比对,能够在第一时间识别出这个数据包并非是遵循自定义协议的,也就是无效数据包,出于安全考虑,可以直接关闭连接以节省资源。在Java字节码的二进制文件中,开头的4字节为0xcafebabe,用来标识这是一个字节码文件,亦有异曲同工之妙。

2.接下来的1字节为版本号,通常情况下是预留字段,在协议升级的时候用到,有点类似TCP协议中的一个字段标识是IPV4协议还是IPV6协议。在大多数情况下,这个字段是用不到的,但是为了协议能够支持升级,还是先留着。

3.第三部分的序列化算法表示如何把Java对象转换为二进制数据及二进制数据如何转换回Java对象,比如Java自带的序列化、JSON、Hessian等序列化方式。

4.第四部分的字段表示指令,关于指令相关的介绍,我们在前面已经讨论过。服务端或者客户端每收到一种指令,都会有相应的处理逻辑。这里我们用1字节来表示,最高支持256种指令,对于这个即时聊天系统来说已经完全足够了。

5.第五部分的字段表示数据长度,占4字节。

6.最后一部分为数据内容,每一种指令对应的数据都是不一样的,比如登录的时候需要用户名和密码,收消息的时候需要用户标识和具体消息内容等。

在通常情况下,这样一套标准的协议能够适配大多数情况下的客户端与服务端的通信场景,接下来我们就看一下如何使用Netty来实现这套协议。