统一介绍下一个IM APP的方方面面,包括技术选型(包括通讯方式,网络连接方式,协议选择)和常见问题。

P2P还是服务器中转?

IM通讯方式无非两种选择:设备直连(P2P)和通过服务器中转。

1P2P方式

P2P多见于局域网内聊天工具,典型的应用有:飞鸽传书、天网Maze(你懂的)等。这类软件在启动后一般做两件事情:

进行UDP广播:发送自己信息和接受同局域网内其他端信息;

开启TCP监听:等待其他端进行连接。

详细的流程可以参考飞鸽传书源码。但是这种方式在有种种限制和不便:一方面它只适合在线的点对点消息传输,对离线,群组等业务支持不够。另一方面由于 NAT 的存在,使得不同局域网内机器互联难度大大上升,在某些网络类型(对称NAT)下无法建立连接。

2服务器中转方式

几乎所有互联网IM产品都采用服务器中转这种方式进行消息传输,相对于P2P的方式,它有如下的优点:

能够支持更多P2P无法支持或支持不好的业务,如离线消息,群组,聊天室服务;

方便业务逻辑的拓展和新旧版本的兼容。

当然它也有自己的问题:服务器架构复杂,并发要求高。

该选择什么样的网络通讯技术?

IM主流网络通讯技术有两种:

基于TCP的长连接;

基于HTTP短连接PULL的方式。

后者常见于WEB IM系统(当然现在很多WEB IM都是基于WebSocket实现),它的优点是实现简单,方便开发上手,问题是流量大,服务器负载较大,消息及时性无法很好地保证,对大规模的用户量支持不够,比较适合小型的IM系统,如小网站的客户系统。

基于TCP长连接则能够更好地支持大批量用户,问题是客户端和服务器的实现比较复杂。当然也还有一些变种,如下行使用MQTT进行服务器通知/消息的下发,上行使用HTTP短连接进行指令和消息的上传。这种方式能够保证下行消息/指令的及时性,但是在弱网络下上行慢的问题还是比较严重。早期的来往就是基于这种方式。

协议如何制定?

IM协议选择原则一般是:易于拓展,方便覆盖各种业务逻辑,同时又比较节约流量。后一点的需求在移动端IM上尤其重要。常见的协议有:XMPP、SIP、MQTT、私有协议。

1XMPP

优点:协议开源,可拓展性强,在各个端(包括服务器)有各种语言的实现,开发者接入方便;

缺点:缺点也是不少,XML表现力弱、有太多冗余信息、流量大,实际使用时有大量天坑。

2SIP

SIP协议多用于VOIP相关的模块,是一种文本协议,由于我并没有实际用过,所以不做评论,但从它是文本协议这一点几乎可以断定它的流量不会小。

3MQTT

优点:协议简单,流量少;

缺点:它并不是一个专门为IM设计的协议,多使用于推送。

4私有协议

市面上几乎所有主流IM APP都是是使用私有协议,一个被良好设计的私有协议优点非常明显。

优点:高效,节约流量(一般使用二进制协议),安全性高,难以破解;

缺点:在开发初期没有现有样列可以参考,对于设计者的要求比较高。

该如何设计私有通信协议?

1序列化与反序列化

移动互联网相对于有线网络最大特点是:带宽低,延迟高,丢包率高和稳定性差,流量费用高。所以在私有协议的序列化上一般使用二进制协议,而不是文本协议。

常见的二进制序列化库有protobuf和MessagePack,当然你也可以自己实现自己的二进制协议序列化和反序列的过程,比如蘑菇街的TeamTalk。但是前面二者无论是可拓展性还是可读性都完爆TeamTalk(TeamTalk连Variant都不支持,一个int传输时固定占用4个字节),所以大部分情况下还是不推荐自己去实现二进制协议的序列化和反序列化过程。

2协议格式设计

基于TCP的应用层协议一般都分为包头和包体(如HTTP),IM协议也不例外。包头一般用于表示每个请求/反馈的公共部分,如包长,请求类型,返回码等。 而包头则填充不同请求/反馈对应的信息。

一个最简单的包头可以定义为:

struct PackHeader

{

int32_t    length_;    //包长度

int32_t    serial_;    //包序列号

int32_t    command_;  //包请求类型

int32_t    code_;      //返回码

};

以心跳包为例,假设当前的serial为1,心跳包的command为10,那么使用MessagePack做序列化时:length=4,serial=1,command=10,code=0,每个字段各占一个字节,包体为空,仅需要4个字节。

当然这是最简单的一个例子,面对真正的业务逻辑时,包体里面会需要塞入更多地信息,这个需要开发根据自己的业务逻辑总结公共部分,如为了兼容加入的协议版本号,为了负载均衡加入的模块id等。

其他不可忽视的问题

上面的内容就是一个IM系统大致的选型过程:服务方式,网络通讯协议,数据通信协议选择、协议设计。但是实际开发过程中还有大量的问题需要处理。

1协议加密

为了保证协议不容易被破解,市面上几乎所有主流IM都会对协议进行加密传输。常见的流程和HTTPS加密相似:建立连接后,客户端和服务器进行进行协商,最终客户端获得一个当前Sessino的秘钥,后续的数据传输都通过这个秘钥进行加解密。一般出于效率的考虑都会采用流式加密,如RC4。而前期协商过程则推荐使用RSA等非对称加密以增加破解难度。

2快速连接(即掉线重连机制)

对iOS APP而言,因为没有真后台的存在,APP每次启动基本都需要一次重连登录(短时间内切换除外),所以如何快速重连、重登就非常重要。

常见优化思路如下:

本地缓存服务器IP并定期刷新。

合并部分请求。如加密和登录操作可以合并为同一个操作,这样就可以减少一次不必要的网络请求来回的时间;

简化登录后的同步请求,部分同步请求可以推迟到UI操作时进行,如群成员信息刷新。

3连接保持(即心跳机制)

一般APP实现连接保持的方式无非是采用应用层的心跳,通过心跳包的超时和其他条件(网络切换)来执行重连操作。那么问题来了:为什么要使用应用层心跳和如何设计应用层心跳。众所周知TCP协议是有KEEPALIVE这个设置选项,设置为KEEPALIVE后,客户端每隔N秒(默认是7200s)会向服务器发送一个发送心跳包。

但实际操作中我们更多的是使用应用层心跳。原因如下:

KEEPALIVE对服务器负载压力比较大(服务器大大是这么说的...);

socks代理对KEEPALIVE并不支持;

部分复杂情况下KEEPALIVE会失效,如路由器挂掉,网线(移动端没有网线...)直接被拔除。

移动端在实际操作时为了节约流量和电量一般会在心跳包上做一些小优化:

精简心跳包,保证一个心跳包大小在10字节之内;

心跳包只在空闲时发送;

根据APP前后台状态调整心跳包间隔 (主要是安卓)。

4消息可达(即QoS机制)

在移动网络下,丢包,网络重连等情况非常之多,为了保证消息的可达,一般需要做消息回执和重发机制。参考易信,每条消息会最多会有3次重发,超时时间为15秒,同时在发送之前会检测当前连接状态,如果当前连接并没有正确建立,缓存消息且定时检查(每隔2秒检查一次,检查15次)。所以一条消息在最差的情况下会有2分钟左右的重试时间,以保证消息的可达。即时通讯开发

因为重发的存在,接受端偶尔会收到重复消息,这种情况下就需要接收端进行去重。通用的做法是每条消息都戴上自己唯一的message id(一般是uuid)。

5文件上传优化

IM消息(包括SNS模块)内包含大量的文件上传的需求,如何优化文件的上传就成了一个比较大的主题。

常见有下面这些优化思路:

将上传流程提前:音频提供边录边传。朋友圈的图片进行预上传,选择图片后用户一般会进行文本输入,在这段时间内后台就可以默默将选好的图片进行上传;

提供闪电上传的方式:服务器根据MD5进行文件去重;

优化和上传服务器的连接(参考快速连接),提供连接重用的功能;

文件分块上传:因为移动网络丢包严重,将文件分块上传可以使得一个分组包含合理数量的TCP包,使得重试概率下降,重试代价变小,更容易上传到服务器;

在分包的前提下支持上传的pipeline,避免不必要的网络等待时间;

支持断点续传。

im即时通讯开发:移动端需要面对的问题相关推荐

  1. 即时通讯开发移动端弱网络优化方法总结

    本篇的目的,就是希望以通俗易懂的语言,帮助移动端IM开发者更好地针对性优化移动网络的各种特性,使得开发出的功能给用户带来更好的使用体验. 本文乃全网同类文章中,唯一内容最全."粪" ...

  2. 即时通讯开发Android端消息推送总结

    为什么要研究Android推送技术? 主要还是毕业设计要做一个即时通信app, 我是不喜欢做什么社交app的, 也就象牙塔里的人想得出来, 说实话有这功夫还不如钻研一个小技术点, 把一个点研究透彻, ...

  3. 即时通讯开发如何构建一套移动端消息推送系统

    消息推送作为移动端 APP 运营中的一项关键技术,已经被越来越广泛的运用. 本文追溯了推送技术的发展历史,剖析了其核心原理,并对推送服务的关键技术进行深入剖析,围绕消息推送时产生的服务不稳定性,消息丢 ...

  4. Android 即时通讯开发小结(二)

    <Android 即时通讯开发小结>基于IM Andriod 开发的各种常见问题,结合网易云信即时通讯技术的实践,对 IM 开发做一个全面的总结. 相关推荐阅读:. Android即时通讯 ...

  5. Android 即时通讯开发小结(一)

    本文将基于 IM Andriod 开发的各种常见问题,结合网易云信即时通讯技术的实践,对 IM 开发做一个全面的总结. 客户端架构 作为一个 IM 软件,最重要的一个特性就是保证消息的达到率和实时性. ...

  6. im即时通讯开发:高可用、易伸缩、高并发的IM群聊、单聊架构方案设计

    要实现一整套能用于大用户量.高并发场景下的IM群聊,技术难度远超IM系统中的其它功能,原因在于:IM群聊消息的实时写扩散特性带来了一系列技术难题. 举个例子:如一个2000人群里,一条普通消息的发出问 ...

  7. 基于Netty实现分布式IM即时通讯开发

    计算机编程的学习,能不能把知识学到手,讲究的是动手实践.在我编写的文章中,基本都是以实践代码验证结果为核心来讲述文章内容. 可能有人不知道 Netty 是什么,这里简单介绍下: Netty 是一个 J ...

  8. im即时通讯开发:聊天消息的同步和存储

    IM全称是『Instant Messaging』,中文名是即时通讯.在这个高度信息化的移动互联网时代,生活中IM类产品已经成为必备品,比较有名的如钉钉.微信.QQ等以IM为核心功能的产品.当然目前微信 ...

  9. im即时通讯开发之后台应用保活、消息推送的噩梦

    Android P的最后一个开发者预览版(即DP5)已如期发布于2018年7月26日,根据上面这张发布路线图,相信Android P的正式版将很快到来.对于Andriod开发者来说,不管Andriod ...

最新文章

  1. 2019年工信部重点实验室名单公布 涵盖卫星导航及人工智能等多个领域
  2. 网络丢包问题排查总结
  3. Shell脚本_备份/etc数据
  4. java超时自动关闭_[Java教程]web页面超时自动退出方法_星空网
  5. maya崩溃自动保存路径_maya 使用swig将插件编译成pyd,无缝使用内置数据实现加速计算模块...
  6. [转载] Java Formatter toString()方法与示例
  7. JAVA代码实现hive连接mysql_Java采用JDBC的方式连接Hive(SparkSQL)
  8. JavaEE 保存文件获取绝对路径getResource()和servletContext.getRealPath(/)
  9. HTML5期末大作业:我的家乡网站设计——可以根据百度百科更换家乡适用多数我的家乡
  10. You need to prove you’re evil cheap nike air max
  11. Android监听系统输入法键盘弹出显示与隐藏事件
  12. 华为——策略路由(校园网配置)
  13. 网页怎么与服务器进行连接,如何实现网页与服务器的连接
  14. vue-qr 自动生成二维码+logo图片
  15. hdmi怎么支持2k分辨率_HDMI版本小科普及毕亚兹HDMI高清线体验
  16. s3c2440A操作24C08
  17. JXTA HelloWorld on JXSE 2.5 【二】
  18. 爱迪尔 门锁接口文档_门锁接口说明
  19. 启信宝牵手国家队,征信服务进化再加速
  20. Linux下安装JDK教程,老爷爷看了都说会了!

热门文章

  1. 通联支付公司软件测试待遇,通联支付怎么样
  2. java 行为参数化_Java中的行为参数化
  3. BS 476-7 常做的产品有哪些?纤维板适用这个标准吗?
  4. octave画心形曲线
  5. hp2548无线服务器地址,扫清连接障碍 惠普解决移动打印机难题
  6. SLAM综述(2)-视觉SLAM
  7. 亿信华辰以“数治”谋“智变”,让天下没有难用的数据!
  8. 融云 imkit 解析
  9. Qt画图之五子棋象棋围棋坐标轴等棋盘棋子程序案例解析
  10. 都会演出连城诀—诺基亚N78决战入手入手了!