对于Socket,我也是自己慢慢学习,参考大神文章https://www.jianshu.com/p/2dbb360886a8
实现IM方式中,第一种方式,使用第三方IM服务,对于短平快公司,采用第三个sdk实现,如云信,环信,融云,LeanCloud.
第三方服务商IM底层协议基本上都是TCP.使用第三方sdk甚至不需要自己去搭建IM后台.
缺点: 定制化程度太高,很多东西不可控.需要费用.如果IM对于APP只是一个辅助功能,那么用第三方服务页可以.
另一种方式,我们自己去实现
我们自己实现需要选择:
1.首先面临的就是传输协议的选择,TCP还是UDP
2.其次是我们需要去选择使用哪种聊天协议
基于Scoket或WebScoket或其他的私有协议
MQTT
XMPP
3.我们是自己去基于OS底层Socket进行封装还是在第三方框架的基础上进行封装
4.传输数据的格式,我们是用Json, XML 还是谷歌推出ProtocolBuffer
5.我们还有一些细节问题需要考虑, 如TCP的长连接如何保持,心跳机制, Qos机制,重连机制等等.当然,除此之外,我们还有一些安全问题需要考虑.
传输协议的选择
实现IM,首先从传输层协议来说,我们有两种选择:TCP 或 UDP
有关移动端IM/推送系统的协议选型: UDP / TCP 参考:http://www.52im.net/thread-33-1-1.html
有关IM的数据传输协议的选型,是鉴于移动互联网时代,移动网络的不可靠性等特点,加上手机的省电策略,流量压缩等
UDP vs TCP
1. TCP还是UDP? 长连接如何实现, 如何实现心跳机制? 心跳的间隔如何确定? 这些问题都是讨论移动端IM,消息推送等类似话题时,被问到的问题.
2. 互联网/移动互联网网络环境
PC端,操作系统的能力都达到了较高水平.
移动互联网,涉及到无线电话网络基站/2G/3G/4G,其稳定性,带宽,资源分配等各方面虽日趋完善,但是还是有不少问题.还是低速/不稳定/终端能力稍弱等情况.
3. 智能终端电池续航能力,系统休眠
电池续航能力始终是技术瓶颈.
4.IPv4资源,端口资源
IP地址的紧缺导致的动态IP分配的必然,却忽略了由于IP地址不足引起的端口资源不足.
动态分配IP地址(这里不仅仅指互联网入口的IP,还包括局域网内部的IP),路由器的工作原理都是经过端口映射,把内部网络(包括PC/手机/平板/Wifi/2G/3G/4G)IP与端口映射成外部IP(通常是公网IP)和对应的端口,并维持这个映射关系,才能正常修改,转发报文信息,保证内部各个ip/端口与外部的各个ip/端口的通信.
单个IP地址端口理论上是65535个端口.
5.端口映射老化问题
所有路由器都会为每个端口映射关系设置老化时间, 老化时间倒数到0 ,端口映射关系失效,端口被释放给其他连接使用.
端口映射老化时间,比很多人想象中的要短很多.一般的家用宽带路由器,老化时间一般是两三分钟; 在有线宽带运营商接入部分,老化时间可能少于两分钟.在无线电话网络运营商接入部分,老化时间甚至不超过一分钟.
也就是说,任何一个网络通讯(不管TCP/UDP),如果几分钟之内没有网络报文传输, 其占用的IP地址端口将被路由器回收.这个时候该次通信必将终止,不管TCP/UDP,神马都是浮云.
互联网可认为是由无数个路由器连接而成的,一个网络通信往往需要通过n个路由器,每个路由器都会为一次通信建立自己的端口映射.只要其中一个路由器回收其端口,则整个通讯中断.
这也是TCP的KeepAlive参数无法保证长连接的原因.TCP的keepAlive默认是两个小时(而且该参数还是TCP的可选实现,不是必然实现),在路由器端口映射老话时间的影响下,必然无法发挥其作用.
由于路由器端口映射的存在,加上只能终端频繁,长时间的休眠,TCP长连接的实用性在移动互联网情况下极大地打了折扣.
也因为如此,移动端IM/推送系统必须实现所谓的心跳包机制,以保持端口映射关系的老化时间不会减少到0而被回收,从而避免链接中断.
6.服务端承载能力
不管是UDP还是TCP, 都是应用服务器的设备区提供服务的. 而TCP由于提供了安全可靠的流服务, 对计算机,网络资源的消耗是远远大于UDP协议的. 终端在线服务,若是一个较为简单的服务, 未必使用上TCP众多的高级功能,但承受TCP的昂贵成本,未必值得.如果能用UDP来提供服务,单服务器的承载能力,是可以去到TCP服务器的数十倍,甚至上百倍的增长.这也是为什么DNS这种并发数巨大的服务器提供UDP接口的原因.
上百万TCP连接的网络服务,其编程的难度,程序复杂度,调试难度,服务器运维成本,网络成本等远远高于UDP.如果提供的网络服务不是基于流的服务,也允许一定的失败几率如P2P,则UDP往往是更适合的方式.
7. 高级应用网络通讯要求
移动端IM系统/推送系统一方面提供终端在线服务, 另一方面也需要考虑内容信息的完整性和安全性.毕竟信息的丢失或通讯被窃听,都是问题.TCP不管在网络层的可靠性控制,还是在应用层的安全支持(如HTTPS),都为应用提供无法替代的便利.
总结:
移动端IM/推送系统,既面对移动互联网的不确定性,又面对智能终端频繁的系统休眠/网络切换,还要考虑服务端的承载成本,对于在线服务UDP比TCP更适合的方式.但是为了数据完整性/安全性的需要,又不应完全放弃TCP可靠与安全.
所以 两种通讯协议同时使用,各有侧重.UDP用于保持大量终端的在线与控制,应用与业务则通过TCP去实现.这个和FTP服务控制与数据分离,采用不同的连接类似.
早起的QQ主要使用TCP协议,后来转向了采用UDP方式保持在线,TCP来上传和下载数据.如: 登录PC端QQ,
一般的传输协议还是用TCP比较好.
接下来是聊天协议的实现
1.基于Socket原生,代表框架 CocoaAsyncSocket
2.基于WebScoket:代表框架SocketRocket
3.基于MQTT: 代表框架MQTTKit
4.基于XMPP: 代表框架XMPPFramework
或者是基于OS底层Scoket企业实现我们自定义封装.
MQTT/XMPP为聊天协议, 它们是最上层的协议,而webScoket是传输通讯协议,它是基于Socket封装的一个协议.而通常我们所说的腾讯IM的私有协议,就是基于webScoket/Scoket原生进行封装的一个聊天协议
XMPP 优点: 协议开源,可拓展性强,在各个端(包括服务器)有各种语言的实现,开发者接入方便
缺点:确定也是不少,XML表现力弱,有太多冗余信息,流量大,实际使用时有大量坑
MQTT 优点:协议简单,流量少,订阅+推送模式,非常适合Uber/滴滴的小车轨迹的移动
缺点:它并不是一个专门为IM设计的协议,多使用于推送.IM情景要复杂多,如加入对话,创建对话等
私有协议 优点:目前主流IM APP都是使用私有协议,一个被良好设计的私有协议优点非常明显.高效,节约流量,一般使用二进制协议,安全性高,难以破解.
缺点:开发初期没有现有样列参考,对于设计者要求高
iOS要做一个IM产品,一般都是基于Scoket/WebScoket,再加上一些私有协议来保证.
1.直接用OS底层Socket来实现一个简单IM
实现思路:创建Socket,和服务器的Socket对接上,然后开始传输数据就可以.
无论c/c++/java语言,都要讲Socket,Socket就是使用TCP/IP或UDP/IP协议的一组编程接口.
我们在应用层,使用socket,来实现进程之间的通信,跨网络的,如果没有socket,我们要直面TCP/IP协议.