IM 协议的分析和选取 (XMPP&WebSocket)

Stella981
• 阅读 779

IM 业务涉及许多技术点,比如点对点通信,组播,实时语音和视频等等,不同的业务也是需要用不同的协议去实现。近期我们的项目面临许多IM业务 比如 群聊,群语音,群组播等等;有关IM的技术虽然我们有研究一段时间,但是受时间限制就只能先用了第三方でserver。 语音技术不太熟悉,这里就基本的IM通信对我学习到的个别几个协议进行对比和说明(不熟悉的协议我就略过了)。

IM协议和介绍:

1.XMPP

最早听说的IM协议是xmpp,去年我也萌生想要做一个聊天室 这样的想法,几经波折后学长推荐我使用xmpp这个协议。XMPP的前身是Jabber,一个开源形式组织产生的网络即时通信协议。XMPP目前被IETF国际标准组织完成了标准化工作。标准化的核心结果分为两部分:

(1)核心的xml流传输协议

(2)基于xml流传输的即时通讯扩展应用

看到xml了,这种树形结构表示数据十分清晰,特别是展示类和类,实体之间的关系也十分方便(早期SSH框架中大量使用这个结构)。其实传统的im协议完全可以在通信的时候发送二进制流,传输到server(或者其他点)的时候做解析,但这样一来解析过程复杂 需要自己实现解析协议等。xmpp定义的xml中有很多通用标签和属性,使用者可以遵循这个协议で基础上解析消息等等。当然xmpp也是可以传输数据流的(消息传输本质也是数据流,可能是表现形式是用了xml的数据结构),比如我们需要做文件上传的时候,虽然xmpp有一种方式是直接放到xml里传输(和传递文本一样对待,文本换成流罢了),但是这不实用,之多传递小文件;而xmpp还有种传输方式貌似叫 socket5,可以传输中小型文件。 这里我找了一个socket5方式的传输过程:

1.A向B发送请求查询B是否支持字节流。

2.B返回应答

3.A向服务器发送请求,查询可用的代理

4.服务器应答,返回目前disco列表中所有可用的服务项

5.A验证服务器中每一项是否是字节流代理

6.服务器应答每一项的查询结果

7.A发送请求,查询代理服务器的网络地址

8.服务器返回代理服务器的网络地址(包括IP和端口)

9.A通知B代理服务器的地址

10.B与代理进行验证和连接初始化

一旦A通知完B后,B就要主动与代理服务器建立socks5连接。

这种方式也仅仅适合传输中小文件,比如几十秒之内的语音文件(其实我真心不喜欢用im协议去直接传输文件,因为你除了通信还要发文件对server影响有些不好)。所以对于中大型文件,还是要用http传输比较合理。在带宽足够的时候可以选择用im传输较小的文件。

2.websocket

websocket是在http协议基础之上进行的改进,这里说道http协议,这个协议是无状态的,所以才有了session来充当生命周期(当然一次请求响应也是http协议得一个生命周期)。而websocket和xmpp这种协议则是有状态的,这种状态靠 心跳 来维持,所谓心跳就是客户端服务器在不停的校验对方是否还是持久的,有没有断线。http其实也可以做到这点,HTTP有1.1和1.0之说,也就是所谓的keep-alive,把多个HTTP请求合并为一个,但是Websocket其实是一个新协议,跟HTTP协议基本没有关系。

IM 协议的分析和选取 (XMPP&WebSocket)

引用这么一张图,他俩之间有交集。

其实websocket在建立连接的时候也是借助了http的,首先你需要用http和客户端建立一次握手,之后的事情就是websocket来处理了,C/S开始持续的检查心跳,一方有断线另一方检测不到心跳,这一次生命周期结束。传输细节可以看看它的协议头。

那么这就有个问题了,我http也能做到你说的这个要求啊,ajax轮询大家应该听说过吧,至少ajax大家有用过,在不影响客户端使用的时候发送异步请求,得到server的响应。这样一来也能做到实时监听客户端和服务器的连接呢。当然长轮询按理说也可以(得不到消息就不响应)。

但是ajax轮询和所谓的长轮询都存在这么几个问题:1.请求一次服务器需要一定的的速度。2.需要高并发,你站着IO资源不放,别人来了就要死了。而且频繁打开关闭http链接也比较消耗资源

所以websocket解决了这方面的问题,只需一次http后面的事儿交给websocket。也就好比我们有个速度很快的接线员(nginx,nodejs),速度较慢的客服(Java,php),我们把消息给接线员,接线员统一给客服服务,同样我们可以和接线员建立长连接,客服可以把消息通过接线员给我们。

websocket可传递的数据形式就多了,他没有官方统一定制的格式,二进制,json字符串都可以。需要我们自己封装。

3.做作比较

最后来说说这两个协议

xmpp协议优势在于 它的数据格式和业务协议可扩展性相对较好(xml嘛),而且xmpp有一些成品开源server  比如tigase,openfire等等,客户端也有很多解决方案。但是缺点就是如果你想做并发高,送达率快,的应用,他可能有些乏力,因为xmpp的数据格式也决定了他的处理速度比人慢一点,解析xml的效率可想而知,而且数据冗余也会较多,毕竟不是每个应用都要用到它提供的所有协议,需要我们人为的进行调整。

websocket是近些年来的比较新鲜的协议,支持浏览器。优点是传输量级比较轻,可以自定义json格式,传递轻量级文件等等,特别是提到websocket就和nodejs能扯上,node作为近两年比较火热で一个平台,在速度上有着绝对的优势,这二者搭档可以说IM的性能应该会有很大的保障。但是缺点也就在于他太年轻(同node),许多解决方案不成熟,虽然我找到了一些client的解决方案,但是对于一些不熟悉IM的团队,可能会抛弃他转向xmpp,况且xmpp虽然性能一般但是尚且能支持几千甚至上万的在线量。

其实我还是比较看好websocket的(同样看好nodejs),新技术的发展空间很大,环信等厂商的IM可以看得出是XMPP协议,但是说不定一年后websocket成熟了,自然会开放公用API。如果使用方便效率又高,何乐而不为呢?

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
5个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Karen110 Karen110
3年前
​一篇文章总结一下Python库中关于时间的常见操作
前言本次来总结一下关于Python时间的相关操作,有一个有趣的问题。如果你的业务用不到时间相关的操作,你的业务基本上会一直用不到。但是如果你的业务一旦用到了时间操作,你就会发现,淦,到处都是时间操作。。。所以思来想去,还是总结一下吧,本次会采用类型注解方式。time包importtime时间戳从1970年1月1日00:00:00标准时区诞生到现在
Stella981 Stella981
3年前
Python之time模块的时间戳、时间字符串格式化与转换
Python处理时间和时间戳的内置模块就有time,和datetime两个,本文先说time模块。关于时间戳的几个概念时间戳,根据1970年1月1日00:00:00开始按秒计算的偏移量。时间元组(struct_time),包含9个元素。 time.struct_time(tm_y
Easter79 Easter79
3年前
Twitter的分布式自增ID算法snowflake (Java版)
概述分布式系统中,有一些需要使用全局唯一ID的场景,这种时候为了防止ID冲突可以使用36位的UUID,但是UUID有一些缺点,首先他相对比较长,另外UUID一般是无序的。有些时候我们希望能使用一种简单一些的ID,并且希望ID能够按照时间有序生成。而twitter的snowflake解决了这种需求,最初Twitter把存储系统从MySQL迁移
Stella981 Stella981
3年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
11个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这