iOS即时通讯应用开发技术要点

一个简单的IM通讯流程

客户端调用 socket(…) 创建socket;
客户端调用 connect(…) 向服务器发起连接请求以建立连接;
客户端与服务器建立连接之后,就可以通过send(…)/receive(…)向客户端发送或从客户端接收数据;
客户端调用 close 关闭 socket;

通讯协议的选择

TCP和UDP的区别

TCP-Transmission Control Protocol

面向连接,先建立可靠连接,连接过程三次握手,断开连接四次握手,安全连接

UDP-User Data Protocol

非连接协议,对系统资源占用少,程序结构简单,不安全,丢包
TCP实现即时通讯的协议较为简单,UDP要解决丢包问题

聊天协议的选择

Socket聊天协议

基于Scoket原生Socket
适用TCP/IP或者UDP/IP的一组编程接口,跨网络的进程间通信
客户端调用 socket(…) 创建socket;
客户端调用 connect(…) 向服务器发起连接请求以建立连接;
客户端与服务器建立连接之后,就可以通过send(…)/receive(…)向客户端发送或从客户端接收数据;
客户端调用 close 关闭 socket;
创建Socket:ClinetSocket = socket(AF_INET, SOCK_STREAM, 0);

基于框架CocoaAsyncSocket

分别实现了TCP和UDP两种传输协议下的通信,对应着GCDAsyncSocket和GCDAsyncUdpSocket;
建立连接: [gcdSocket connectToHost:Khost onPort:Kport error:nil];
连接成功调用:-(void)socket:(GCDAsyncSocket )sock didConnectToHost: (NSString )host port:(uint16_t)port
发送消息: NSData *data = [msg dataUsingEncoding:NSUTF8StringEncoding];
//第二个参数,请求超时时间
[gcdSocket writeData:data withTimeout:-1 tag:110];
断开连接: [gcdSocket disconnect];
断开连接的时候调用:- (void)socketDidDisconnect:(GCDAsyncSocket )sock withError:(nullable NSError )err;

WebSocket聊天协议

基于WebScoket:代表框架 SocketRocket
初始化连接: webSocket = [[SRWebSocket alloc]initWithURL:[NSURL URLWithString:[NSString stringWithFormat:@”ws://%@:%d”, Khost, Kport]]];
webSocket.delegate = self;
//设置代理线程queue
NSOperationQueue *queue = [[NSOperationQueue alloc]init];
queue.maxConcurrentOperationCount = 1;
[webSocket setDelegateOperationQueue:queue];
//连接[webSocket open];
初始化心跳:dispatch_main_async_safe(^{
[self destoryHeartBeat];
__weak typeof(self) weakSelf = self;
//心跳设置为3分钟,NAT超时一般为5分钟
heartBeat = [NSTimer scheduledTimerWithTimeInterval:3*60 repeats:YES block:^(NSTimer * _Nonnull timer) {
NSLog(@”heart”);
//和服务端约定好发送什么作为心跳标识,尽可能的减小心跳包大小
[weakSelf sendMsg:@”heart”];
}];
[[NSRunLoop currentRunLoop]addTimer:heartBeat forMode:NSRunLoopCommonModes];
})
取消心跳:dispatch_main_async_safe(^{
if (heartBeat) {
[heartBeat invalidate];
heartBeat = nil;
}
})
重连机制: [self disConnect];
//超过一分钟就不再重连 所以只会重连5次 2^5 = 64
if (reConnectTime > 64) {
return;
}

        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(reConnectTime * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            webSocket = nil;
        [self initSocket];
    });
        //重连时间2的指数级增长
        if (reConnectTime == 0) {
                reConnectTime = 2;
        }else{
                reConnectTime *= 2;
        }

XMPP聊天协议

基于XMPP:代表框架 XMPPFramework。
可拓展性强,协议开源
获取到的通信数据是XML格式的,需要用到XML解析
XMPP对于IM来说实在是不堪重用。仅仅只能作为一个玩具demo,给大家练练手。网上有太多XMPP的内容了,相当一部分用openfire来做服务端,这一套东西实在是太老了。还记得多年前,楼主初识IM就是用的这一套东西…

MQTT聊天协议

基于MQTT:代表框架 MQTTKit
并不是一个专为IM设计的协议,多用了推送,适用于推送+订阅模式,应用层协议
主要的类MQTTClient:这个类一共分为4个部分:初始化、连接、发布、订阅
当我们连接成功了,我们需要去订阅自己clientID的消息,这样才能收到发给自己的消息。
其次是这个框架为我们实现了一个QOS机制

数据传输格式的选择

JSON或者XML,or Google的ProtocolBuffer
ProtocolBuffer:使用 ProtocolBuffer 减少 Payload(负载),滴滴打车40%;携程之前分享过,说是采用新的Protocol Buffer数据格式+Gzip压缩后的Payload大小降低了15%-45%。数据序列化耗时下降了80%-90%。采用高效安全的私有协议,支持长连接的复用,稳定省电省流量。【高效】提高网络请求成功率,消息体越大,失败几率随之增加。【省流量】流量消耗极少,省流量。一条消息数据用Protobuf序列化后的大小是 JSON 的1/10、XML格式的1/20、是二进制序列化的1/10。同 XML 相比, Protobuf 性能优势明显。它以高效的二进制方式存储,比 XML 小 3 到 10 倍,快 20 到 100 倍。【省电】省电【高效心跳包】同时心跳包协议对IM的电量和流量影响很大,对心跳包协议上进行了极简设计:仅 1 Byte 。【易于使用】开发人员通过按照一定的语法定义结构化的消息格式,然后送给命令行工具,工具将自动生成相关的类,可以支持java、c++、python、Objective-C等语言环境。
缺点:
可能会造成 APP 的包体积增大,通过 Google 提供的脚本生成的 Model,会非常“庞大”,Model 一多,包体积也就会跟着变大。

细节问题的考量

心跳机制:用来检测TCP连接的双方是否可用;客户端发起心跳Ping(一般都是客户端),假如设置在10秒后如果没有收到回调,那么说明服务器或者客户端某一方出现问题,这时候我们需要主动断开连接;服务端也是一样,会维护一个socket的心跳间隔,当约定时间内,没有收到客户端发来的心跳,我们会知道该连接已经失效,然后主动断开连接;移动端IM需要心跳保活:国内运营商NAT超时;
PingPong机制:当服务端发出一个Ping,客户端没有在约定的时间内返回响应的ack,则认为客户端已经不在线,这时我们Server端会主动断开Scoket连接,并且改由APNS推送的方式发送消息。同样的是,当客户端去发送一个消息,因为我们迟迟无法收到服务端的响应ack包,则表明客户端或者服务端已不在线,我们也会显示消息发送失败,并且断开Scoket连接。
Qos机制:QoS(Quality of Service,服务质量)指一个网络能够利用各种基础技术,为指定的网络通信提供更好的服务能力, 是网络的一种安全机制, 是用来解决网络延迟和阻塞等问题的一种技术。
QOS(0),最多发送一次:如果消息没有发送过去,那么就直接丢失。
QOS(1),至少发送一次:保证消息一定发送过去,但是发几次不确定。
QOS(2),精确只发送一次:它内部会有一个很复杂的发送机制,确保消息送到,而且只发送一次。
重连机制:一般解决方案是尝试重连几次,如果仍旧无法重连成功,那么不再进行重连。封装一个重连时间指数级增长的一个重连方式,如支付宝的支付成功后的回调机制。
安全机制:防止 DNS 污染、帐号安全、第三方服务器鉴权、单点登录等等

你可能感兴趣的:(即时通讯)