为译者
CocoaAsyncSocket
终,这篇主要介绍了:disconnect
注:由于该框架源码篇幅过大,且有大部分相对抽象的数据操作逻辑,尽管楼主竭力想要简单的去陈述相关内容,但是阅读起来仍会有一定的难度。不是如果想诚心学习IM
相关知识,在这里就可以离场了......
插座与的APN
iOS- CocoaAsyncSocket源码解析(Connect上) iOS- CocoaAsyncSocket源码解析( 阅读上) iOS- CocoaAsyncSocket源码解析(阅读下) iOS- CocoaAsyncSocket源码解析(写)
注:文中涉及代码比较多,建议大家结合源码一起阅读比较容易能加深理解。这里有楼主标注好注释的源码,有需要的可以作为参照:CocoaAsyncSocket源码注释
这里面还是常规操作,对我们关闭任务的处理:同步关闭
disconnect
核心代码
preBuffer
也进行reset
如果大家想玩转插座还有两个重要点还是需要掌握的
简单的来说,心跳就是用来检测TCP连接的双方是否可用。那又会有人要问了,TCP本身不是就自带一个KeepAlive
机制吗?
这里我们需要说明的是TCP的KeepAlive
机制只能保证连接的存在,但是并不能保证客户端以及服务端的可用性。比如会有以下一种情况:
某台服务器因为某些原因导致负载超高,CPU 100%,无法响应任何业务请求,但是使用TCP探针则仍旧能够确定连接状态,这就是典型的连接活着但业务提供方已死的状态。
这个时候心跳机制就起到作用了:
参考文章:为什么说基于TCP的移动端IM仍然需要心跳保活?
其实做过IM的小伙伴们都知道,真正我们需要心跳机制的原因其实主要的英文在于国内运营商NAT
超时。
NAT
超时呢?原来这是因为IPV4引起的,我们上网很可能会处在一个NAT设备(无线路由器之类)之后 .NAT设备会在IP封包通过设备时修改源/目的IP地址。对于家用路由器来说,使用的是网络地址端口转换(NAPT),它不仅改IP,还修改TCP和UDP协议的端口号,这样就能让内网中的设备共用同一个外网IP。举个例子,NAPT维护一个
类似下表的NAT表:
NAT设备会根据NAT表对出去和进来的数据做修改,192.168.0.3:8888
比如将发出去的封包改成120.132.92.21:9202
,外部就认为他们是在和120.132.92.21:9202
通信。同时NAT设备会将120.132.92.21:9202
收到的封包的IP和端口改成192.168.0.3:8888
,再发给内网的主机,这样内部和外部就能双向通信了,但如果其中192.168.0.3:8888
== 120.132.92.21:9202
这一映射因为某些原因被NAT设备淘汰了,那么外部设备就无法直接与192.168.0.3:8888
通信了。
我们的设备经常是处在NAT设备的后面,比如在大学里的校园网,查一下自己分配到的IP,其实是内网IP,表明我们在NAT设备后面,如果我们在寝室再接个个由器,那么我们发出的数据包会多经过一次NAT。
国内移动无线网络运营商在链路上一段时间内没有数据通讯后,会淘汰NAT表中的对应项,造成链路中断。
而国内的运营商一般NAT超时的时间为5分钟,所以通常我们心跳设置的时间间隔为3-5分钟。
很多小伙伴可能又会感觉到疑惑了,那么我们在这心跳间隔的3-5分钟如果连接假在线(例如在地铁电梯这种环境下)。那么我们岂不是无法保证消息的即时性么?这显然是我们无法接受的,所以的业内解决方案的英文采用双向的PingPong
机制。
当服务端发出一个Ping
,客户端没有在约定的时间内返回响应的ack
,则认为客户端已经不在线,我们这时Server
端的会主动断开Scoket
连接,改并且由APNS
推送的方式发送消息。
同样的是,当客户端去发送一个消息,因为我们迟迟无法收到服务端的响应的ACK包,则表明客户端或者服务端已不在线,我们也会显示消息发送失败,断开并且Scoket
连接。
记得还我们之前CocoaSyncSockt
的例子所讲的电子杂志消息超时就断开吗?它其实就是一个PingPong
机制的客户端的实现。我们每次可以在发送消息成功后,调用这个超时读取的方法,如果一段时间没收到服务器的响应,那么说明连接不可用,断开则Scoket
连接
理论上,自己我们去主动断开的Scoket
连接(例如退出账号,APP退出到后台等等),不需要重连。其他的连接断开,我们都需要进行断线重连。一般解决方案是尝试重连几次,如果仍旧无法重连成功,那么不再进行重连。
CocoaAsyncSocket源码解析的过程,还是收货颇丰的!