iOS端IM开发从入门到填坑手机IM「iOS端IM开发从入门到填坑」

   日期:2025-04-05    作者:8y2ex 移动:http://www.kub2b.com/mobile/quote/2902.html
 
让App聊起来

IM开发从入门到填坑Demo

IM的第三方服务商国内有很多,底层协议基本上都是基于TCP的,类似有网易云信、环信、融云、极光IM、LeanCloud、云通讯IM(腾讯)、云旺IM(阿里)、容联云、小能、美洽等等,技术也相对比较成熟,提供后台管理和定制化的UI,拿来主义,半小时集成。

缺点也很明显:定制化程度太高,需要二次开发,很多东西我们不可控,关键是太贵了。如果IM对于APP只是一个辅助功能,如客服系统、消息推送等,也基本够用。

几乎所有互联网IM产品都用服务器中转方式进行消息传输。自己去实现也会面临许多选择:

1、传输协议的选择:TCP还是UDP?
2、选择哪种聊天协议进行开发:MQTT、XMPP、基于 Socket 原生或 WebSocket 的私有协议?
3、传输数据的格式:用JSON、还是XML、还是谷歌推出的ProtocolBuffer?
4、我们还有一些细节问题需要考虑,例如TCP的长连接如何保持,心跳机制,Qos机制,重连机制等等。另外,还有一些安全问题需要考虑。

移动端IM的传输协议选型:TCP还是UDP?
TCP:基于连接的可靠协议的全双工的可靠信道,有流量控制、差错控制等,占用系统资源较多,传输效率相对低
UDP:基于无连接的不可靠协议,没有足够的控制手段,传输效率高,有丢包问题

TCP和UDP的最完整的区别

基于UDP协议开发成本较高,容易各种丢包或乱序,一般小公司或技术不成熟或即时性要求不高的公司,多用TCP开发。
QQ-IM的私有协议:登录等安全性操作使用TCP协议,好友之间发消息主要使用UDP协议,内网传输文件采用了P2P技术,另外腾讯还用了自己的私有协议,来保证传输的可靠性。

首先我们以实现方式来切入,基本上有以下四种实现方式:

基于Socket原生:代表框架 CocoaAsyncSocket。
基于WebSocket:代表框架 SocketRocket。
基于MQTT:代表框架 MQTTKit。
基于XMPP:代表框架 XMPPFramework。

我们用基于OS底层的原生Socket来实现一个简单的IM。
socket扩展阅读

服务端需要做的工作简单的总结下:

服务端可以电脑或手机等终端,也可以用多种语言c/c++/java/js等去实现后台,当然OC也可以实现。这里我们借用node.js实现了一个服务端,来验证socket效果。需要在Mac上安装node解释器,node下载,直接下载安装即可,也可以终端命令安装node。
开启服务器:

IM客户端需要做如下4件事

代码实现
我们采用CocoaAsyncSocket框架,封装一个名为WYKSocketManager的单例,来对socket相关方法进行调用:
为了demo演示方便,代码中使用的时间都较短,实际开发中根据需要设置

我们发了一条消息,服务端成功的接收到了消息后,把该消息再发送回客户端,绕了一圈客户端又收到了这条消息。至此我们用OS底层socket实现了简单的IM。这里仅仅是实现了Socket的连接并传输字符串,我们要做的远不止于此。

(1)心跳机制

心跳机制是相对时间内主动向服务器发送心跳包消息,用来检测TCP连接的双方是否可用。TCP的KeepAlive机制只能保证连接的存在,但是并不能保证客户端以及服务端的可用性。
扩展阅读:为什么说基于TCP的移动端IM仍然需要心跳保活?
真正需要心跳机制的原因其实主要是在于国内运营商的网络地址转换设备超时,对于家用路由器来说, 使用的是网络地址端口转换(NAPT), 它不仅改IP, 还修改TCP和UDP协议的端口号, 这样就能让内网中的设备共用同一个外网IP,造成连接存在,但并不一定可用。

而国内的运营商一般NAT超时的时间为5分钟,频繁心跳会带来耗电和耗流量的弊端,所以通常IM心跳设置的时间间隔为3-5分钟,甚至10分钟都行。微信有一种更高端的实现方式,有兴趣的小伙伴可以看看:微信的智能心跳实现方式

(2)PingPong机制

(3)重连机制

理论上,自己主动断开的Socket连接(如退出账号,APP退出到后台等),不需要重连。其他的连接断开,我们都需要进行断线重连。 一般解决方案是尝试重连几次,如果仍旧无法重连成功,那么不再进行重连。

(4)消息可达(即QoS机制)

在移动网络下,丢包、网络重连等情况非常之多,为了保证消息的可达,一般需要做消息回执和重发机制。
一般有三种类型:
QOS(0),最多发送一次:如果消息没有发送过去,那么就直接丢失。
QOS(1),至少发送一次:保证消息一定发送过去,但是发几次不确定。
QOS(2),精确只发送一次:它内部会有一个很复杂的发送机制,确保消息送到,而且只发送一次。

参考易信,每条消息会最多会有3次重发,超时时间为15秒,同时在发送之前会检测当前连接状态,如果当前连接并没有正确建立,缓存消息且定时检查(每隔2秒检查一次,检查15次)。所以一条消息在最差的情况下会有2分钟左右的重试时间,以保证消息的可达。因为重发的存在,接受端偶尔会收到重复消息,这种情况下就需要接收端进行去重。通用的做法是每条消息都戴上自己唯一的message id(一般是uuid)。

扩展阅读:
IM消息送达保证机制实现

(1)基于WebSocket最具代表性的一个第三方框架SocketRocket

实现的思路和基于CocoaAsyncSocket框架类似,需要编写遵守webSocket协议的服务端,感兴趣的也可以参照实现一下。

(2)基于MQTT协议的框架-MQTTKit

MQTT是一个聊天协议,它比webSocket更上层,属于应用层,它的基本模式是简单的发布订阅,也就是说当一条消息发出去的时候,谁订阅了谁就会收到消息。其实它并不适合IM的场景,例如用来实现有些简单IM场景,却需要很大量的、复杂的处理。这个框架是c来写的,把一些方法公开在MQTTKit类中,对外用OC来调用,这个库有4年没有更新了。

(3)基于XMPP协议的框架-MQTTKit

XMPP是较早的聊天协议(2000年发布第一个公开版本),当时主要是用来打通 ICQ、MSN 等 PC 端的聊天软件而设计的,技术比较成熟,它本身有很多优点,如开放、标准、可扩展,并且客户端和服务器端都有很多开源的实现,但是相对于移动端它也有很明显的缺点,譬如数据负载过重、不支持二进制,在交互中有50% 以上的流量是协议本身消耗的,需要做深度的二次开发。

移动互联网相对于有线网络最大特点是:带宽低,延迟高,丢包率高和稳定性差,流量费用高。所以在私有协议的序列化上一般使用二进制协议,而不是文本协议。
常见的二进制序列化库有Protocol Buffers和MessagePack,当然你也可以自己实现自己的二进制协议序列化和反序列的过程,比如蘑菇街的TeamTalk。但是前面二者无论是可拓展性还是可读性都完爆TeamTalk(TeamTalk连Variant都不支持,一个int传输时固定占用4个字节),所以大部分情况下还是不推荐自己去实现二进制协议的序列化和反序列化过程。

一条消息数据用Protobuf序列化后的大小是 JSON 的1/10、XML格式的1/20、是二进制序列化的1/10。同 XML 相比, Protobuf 性能优势明显。它以高效的二进制方式存储,比 XML 小 3 到 10 倍,快 20 到 100 倍。

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

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

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

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

除了心跳机制、PingPong机制、断线重连机制这些被用来保证连接的可用,要提高IM服务时的可靠性,能做的还有很多:比如在大文件传输的时候使用分片上传、断点续传、秒传技术、P2P技术等来保证文件的传输。

我们通常还需要一些安全机制来保证我们IM通信安全。如:加密传输、防止 DNS 污染、帐号安全、第三方服务器鉴权、单点登录等。

精简心跳包,心跳包只在空闲时发送,动态化心跳间隔。文件上传、下载优化等。类似微信,服务器不做聊天记录的存储,只在本机进行缓存,这样可以减少对服务端数据的请求,一方面减轻了服务器的压力,另一方面减少客户端流量的消耗。
我们进行http连接的时候尽量采用上层API,类似NSUrlSession。而网络框架尽量使用AFNetWorking3.0 以上版本。因为这些上层网络请求都用的是HTTP/2 ,我们请求的时候可以复用这些连接。
更多优化相关请参考这篇文章:
《iOS端移动网络调优的8条建议》
IM 即时通讯技术在多应用场景下的技术实现,以及性能调优( iOS 视角)

IM应用中的实时音视频技术,几乎是IM开发中的最后一道高墙。原因在于:实时音视频技术 = 音视频处理技术 + 网络传输技术 的横向技术应用集合体,而公共互联网不是为了实时通信设计的。
实时音视频技术上的实现内容主要包括:音视频的采集、编码、网络传输、解码、播放等环节。这么多项并不简单的技术应用,如果把握不当,将会在在实际开发过程中遇到一个又一个的坑。


特别提示:本信息由相关用户自行提供,真实性未证实,仅供参考。请谨慎采用,风险自负。


举报收藏 0评论 0
0相关评论
相关最新动态
推荐最新动态
点击排行
{
网站首页  |  关于我们  |  联系方式  |  使用协议  |  隐私政策  |  版权隐私  |  网站地图  |  排名推广  |  广告服务  |  积分换礼  |  网站留言  |  RSS订阅  |  违规举报  |  鄂ICP备2020018471号