理论联系实际:一套典型即时通讯协议设计的详细说明

时间:2020-10-20

语音聊天软件

 前言

 本文中的即时消息通信协议是指应用层通信“语言”,而不是传输层协议(如TCP和UDP)。即时通信协议的制定是即时通信开发的起点,是整个设计、开发、运行和维护的核心。通信协议的设计直接影响到用户体验(数据流、功耗、通信速度)、兼容性(新旧版本的无缝集成)、可扩展性(如何升级后期版本)等,这是一项基础且极其重要的工作。

 本文将从理论和实践相结合的角度详细阐述典型即时通信协议设计的各个方面。

 本文的原作者是桐城58人沈健。com:58桐城市技术委员会主席、高级建筑师、优秀讲师。曾任百度hi团队成员,负责58城市im系统的架构设计。

 即时通信协议的分层设计

 所谓“协议”是双方都遵守的规则,如离婚协议和停战协议。

 该协议有三个要素:语法、语义和时间:

 (1)语法:数据和控制信息的结构或格式

 (2)语义:即需要发送什么样的控制信息,应该完成什么样的动作,应该做出什么样的响应

 (3)时序:对事件实现顺序的详细描述

 典型的即时消息通信协议设计分为三层:应用层、安全层和传输层。

 理论与实践相结合:一套典型的即时通讯协议设计细节_ b.jpeg。

 即时消息应用层协议设计

 应用层协议有三种常见类型:文本协议、二进制协议和流式XML协议。

 1文本协议

 文本协议是指“接近人类书面语言表达”的通信传输协议,典型的协议是http协议。http协议大致如下所示:

 1234 get/HTTP/1.1用户代理:curlHost: musicml.netAccept: */*

 文本协议的特点是:

 A.可读性好,易于调试

 B.可伸缩性也很好(通过键扩展:值)

 C.解析效率是平均的(逐行读取,除以冒号,解析键和值)

 D.较差的二进制支持,如语音/视频

 在即时通讯中,移动服务网络使用文本协议。

 2二进制协议

 二进制协议是指二进制协议,通常是ip协议。以下是ip协议的说明:

 理论与实践相结合:一套典型的即时通讯协议设计细节_ a.jpeg。

 二进制协议通常有固定长度的包头和可扩展的可变长度包,每个字段都有固定的含义。例如,IP协议的前四位代表协议版本号(详见TCP/IP详细说明第3章)。

 二进制协议具有以下特征:

 A.可读性差,难以调试

 B.可扩展性不好。如果要扩展该字段,旧协议是不兼容的,因此在一般设计中会有一个版本字段

 C.高解析效率(几乎没有解析成本)

 D.较差的二进制支持,如语音/视频

 在即时通讯中,QQ使用时间二进制协议。

 3流式XML协议

 Xmpp是即时消息的准标准协议,它使用流式XML,如gtalk和Intranet。im基于xmpp。让我们看一下xmpp协议的一个例子:

 罗密欧,你为什么在这里?

 从xml标签可以大致判断出这是罗密欧给朱丽叶的聊天信息。Xmpp协议可以实现跨域互通。例如,gtalk与内部网用户聊天。只要服务器端实现s2s服务(服务器到服务器),目前基本上没有互操作性要求im,所以这个服务基本上没有被任何人实现。

 XMPP协议有几个特点:

 A.这是一个准标准协议,可以跨域互操作

 B.XML的优点,良好的可读性和可扩展性

 C.高解析成本(dom解析)

 D.超低有效数据传输速率(大量标签)

 就个人而言,强烈建议不要使用xmpp,尤其是无线终端im。如果您想使用它,您必须自己压缩它以减少网络流量(使用xmpp的学生知道发送登录包需要多少交互以及浪费了多少流量)。

 4个实例

 让我们看一个im协议的实际例子。通常的做法是:固定长度的二进制包头,可扩展的可变长度包体。包可以使用可扩展的协议,如文本和XML。包头负责传输和解析效率,与业务无关。该包保证了可扩展性,并且与业务相关。

 这是一个实际的16字节im二进制固定长度标头:

 123456789//sizeof(cs _ essay-header)= 16 struct cs _ essay-header { uint 32 _ t version;uint32 _ t magic _ numuint32_t cmd。uint32_t透镜;uint8_t数据[];} __属性_ _((打包));

 -a .前4个字节是版本;;

 接下来的四个字节是“幻数(magic_num)”,用于确保数据错位或数据包丢失。通常的做法是在报头中放一些约定的特殊字符,在数据包的末尾放一些约定的特殊字符。发给你的协议是一个普通的信息。

 -c)命令,用于区分保活消息、服务消息、密钥交换消息等。;

 -d. len(数据包长度),告知服务器接收数据包的时间。

 这是一个实际的可扩展im变长包:

 123456789消息CUserLoginReq{可选字符串username = 1;可选字符串passwd = 2;}消息CUserLoginResp{可选uint 64 uid = 1;}

 谷歌的Protobuf协议被使用(每个玩过的人都知道)。可以看到,登录请求包传入用户名和密码,登录响应包返回用户的uid。当然,除了Protobuf之外,xml、json和mcpack是可选的可扩展包协议。)等。(见“强烈推荐Protobuf作为您的即时通讯应用程序数据传输格式”:http://www.52im。net/thread-277-1-1.html获取有关使用Protobuf的文章,有关即时消息协议的更多文章,请参见:http://www。)mod =收集和操作=查看和ctid=18)

 推荐Protobuf时使用清晰的个人横幅有几个原因:

 A.现有的解析库有很多种,可以生成10多种语言代码,如C++、Java、php等。(详情请点击:http://www.52im。net/thread-277-1-1.html)

 B.自带压缩功能

 C.它已被广泛应用于工业

 D.谷歌制造

 即时消息安全层协议的设计

 im协议,消息的保密性非常重要,没有人希望看到他们的聊天内容,因此安全层是必不可少的。

 1使用SSL

 证书管理略微复杂且成本高昂。

 2自我加密和解密

 加密和解密的核心在于密钥的生成和管理。有许多关键的管理方法,主要包括三种:

 (1)固定键

 服务器和客户端就密钥和加密算法达成一致。在发送之前,客户端im使用约定的算法和约定的密钥进行加密,然后进行传输。服务器收到消息后,使用约定的算法和密钥进行解密。这样,密钥和算法对程序员来说是透明的。

 (2)一个人,一把钥匙

 简单地说,每个人的钥匙都是固定的,但彼此不同。事实上,固定键算法包含用户的一个特殊属性,如用户uid、手机号码、qq号码等。

 (3)动态密钥(一个会话和一个密钥)

 动态密钥、一个会话和一个密钥具有更高的安全性,并且在每个会话之前协商密钥。密钥协商过程应经历两次随机生成非对称密钥和一次随机生成对称加密密钥。这里不详述细节。感兴趣的学生可以看到SSL密钥协商的过程。

 Im传输层协议设计

 可选协议有TCP和UDP。现在,即时消息传输层基本上使用TCP。使用epoll和其他技术,多连接不是一个瓶颈,在一台机器上有几十万个链接也不成问题。似乎同一个城市的单机连接现在是10w?(也许单机性能测试可以达到一百万,而在线测试一般可以达到几十万)

 关于QQ使用UDP协议的问题(请参见“为什么QQ使用UDP协议而不是TCP协议?帖子中的讨论)。就我个人而言,我不知道QQ使用UPD作为传输层协议的初衷,但我猜想这是因为10多年前10K客户端问题没有得到很好的解决,而且一台服务器无法支持1W的TCP连接。腾讯同时拥有很大的在线容量,所以不能不使用UDP,但是UDP是不可靠的,所以只能在UDP上实现TCP超时/重传/确认机制。

 结论

 关于QQ使用的UDP协议,在讨论的过程中,一些同学提出了一个很好的问题:“UDP在无线环境下更好,可以独立的状态,而TCP不稳定,导致进出电梯断线,用户体验不好”。

 实际上,“用户状态可以被设计成与连接状态无关”。如果你感兴趣的话,我可以写一篇文章稍后和你谈。传输层使用TCP,如何实现在线状态与底层连接无关。