移动端IM系统的协议选型:UDP还是TCP?

转载自 Jack Jiang 感谢原作者

回顾了一下之前项目用到的自定义通讯协议,正好又看到这篇文章,就转载一下。如果想深入,就不应该单看此文章,文章里面提供的跳转链接里面的知识更丰富。

前言

tcp-udp

对于有过网络编程经验的开发者来说,使用何种数据传输层协议来实现数据的通信,是个非常基础的问题,它涉及到你的第一行代码该如何编写。

从PC时代的IM开始,IM开发者就在为数据传输协议的选型争论不休(比如:《为什么QQ用的是UDP协议而不是TCP协议?》 这样的问题,隔一段时间就能在社区里看到)。到了移动互联网时代,鉴于移动网络的不可靠性等特点,再加上手机的省电策略、流量压缩等,为这个问题的回答增了更多的不确定因素。

对于有选择困难证的人来说,基于以上因素,加上UDP和TCP协议的本质差异,这样的选择确实很纠结。本文将从作者的实践总结,给出自已的观点,如有异议还请理性回复,不为找喷,仅供参考。

说明:本文引用了DDPush的技术资料,感谢原作者。

学习交流

参考资料

UDP vs TCP

TCP还是UDP?长连接如何实现?如何实现心跳机制?心跳的间隔如何确定?这些问题都是讨论移动端IM、消息推送等类似话题时,几乎一定被问到的问题。这里尝试正本清源一下。

互联网、移动互联网网络环境

在分析到底应该使用UDP还是TCP之前,有必要先讨论一下互联网与移动互联网的网络环境特点。

互联网的网络基础建设,经过十几年长期的发展,已经较为稳定和成熟,PC终端、操作系统的能力也达到了较高的水平。

而移动互联网,由于涉及到无线电话网络基站、2G、3G和4G技术的不断发展,其稳定性、带宽、资源分配等各方面虽日趋完善,但当前终究还有不少问题的存在。另外,由于移动互联网其“移动”的本质,加上智能终端设备(智能手机、平板电脑)的发展较晚,目前还在不断演变的情况,与互联网相比,移动互联网还是低速、不稳定、终端能力稍弱的情况。而且由于其“移动”本质,短时间内很难达到互联网的质量。

所以,在互联网的环境里面,网络应用程序由于网络设施、操作系统的成熟,开发使用起来比较容易,资源也较为充足。而移动互联网还是要“斤斤计较”。

智能终端电池续航能力,系统休眠

智能终端设备的电池续航能力始终是技术瓶颈。在连续使用的情况下,绝大部分智能设备电池无法支持两个小时以上。所以在没有外部电源的情况,智能终端设备必须频繁、长时间休眠,这将极大地影响两种网络环境下的网络应用场景。

IPv4资源、端口资源

这个话题往往被很多人忽略,但它有着至关重要的影响。虽然大部分人都很清楚IP地址的紧缺导致的动态IP分配的必然,却忽略了由于IP地址不足引起的端口资源不足。

由于需要动态分配IP地址(这里不仅仅指互联网入口的IP,还包括局域网内部的IP),路由器的工作原理都是经过端口映射,把内部网络(包括PC、手机、平板、Wifi、2G、3G、4G)IP与端口映射成外部IP(通常是公网IP)和对应的端口,并维持这个映射关系,才能正常地修改、转发报文信息,保证内部各个ip、端口与外部的各个ip、端口的通信。

然而,单个IP地址的端口资源是有限的,理论上限是65535个端口。对于普通宽带路由器来说,这个已经很充足了。但是!对于大型的网络服务、网络主干接入点等来说,如果IP资源不足,每个IP几万个端口的资源很快会耗尽,从而影响正常通讯。

端口映射老化时间

正因为如此,所有的路由器都会为每个端口映射关系设置老化时间,如果老化时间倒数到0,则端口映射关系失效,该端口被释放给其他连接使用。如果端口全部耗尽,则无法再新建内部与外部的网络连接。

端口映射老化时间,比很多人想象中的要短很多。一般的家用宽带路由器,老化时间一般是两三分钟;在有线宽带运营商接入部分,老化时间可能少于两分钟。在无线电话网络运营商接入部分(例如GPRS连接),老化时间甚至不超过一分钟!

也就是说,任何一个网络通讯(不管是TCP或UDP),如果几分钟之内没有网络报文传输,其占用的IP地址端口将被路由器回收。这个时候该次通信必将终止,不管TCP还是UDP,神马都是浮云。

更残酷的事实是,互联网可认为是由无数个路由器连接而成的,一个网络通信往往需要通过n个路由器,每个路由器都会为一次通信建立自己的端口映射。只要其中一个路由器回收其端口,则整个通讯中断。

这也是很多人疑惑为什么TCP的KeepAlive参数无法保证长连接的原因。TCP的KeepAlive默认是两个小时(而且该参数还是TCP的可选实现,不是必然实现),在路由器端口映射老化时间的影响下,必然无法发挥其作用。实际上,该参数在单一的局域网内才可能被使用上,还要依赖具体的操作系统。

由于路由器端口映射的存在,加上智能终端频繁、长时间的休眠,TCP长连接的实用性在移动互联网情况下极大地打了折扣。

也因为如此,移动端IM、推送系统必须实现所谓的心跳包机制,以保持端口映射关系的老化时间不会减少到0而被回收,从而避免连接中断。

服务端承载能力

不管是UDP还是TCP,最终都是应用服务端的设备去提供服务的。而TCP由于提供了安全可靠的流服务,其对计算机、网络资源的消耗是远远大于UDP协议的。对于配置较好的主流服务器,配备大量的内存(数十G至上百G内存),与高速的磁盘、网卡,是能同时支持数百万个TCP连接的。不过这里需要较专业的服务器设置,需要调整不少系统参数,再加上服务程序的配合。另外,TCP连接的建立、维持与释放,都是需要较昂贵的计算、网络资源的。

终端在线服务,若是一个较为简单的服务,未必使用上TCP众多的高级功能,但承受TCP的昂贵成本,未必值得。如果能用UDP来提供服务,单服务器的承载能力,是可以去到TCP服务的数十倍,甚至上百倍的增长。这也是为什么DNS这种并发数巨大的服务器提供UDP接口的原因。

另外,上百万TCP连接的网络服务,其编程的难度、程序复杂度、调试难度、服务器运维成本、网络成本等都远远高于UDP。

而UDP编程,与上百万个终端通讯的难度与成本则低很多。如果提供的网络服务不是基于流的服务,也允许一定的失败机率(例如P2P),则UDP往往是更适合的方式。

高级应用网络通讯要求

不过,移动端IM系统、推送系统一方面提供终端在线服务,另外一方面也需要考虑内容信息的完整性和安全性。毕竟信息的丢失,或者通讯的被窃听,都是难以接受的。而TCP不管在网络层的可靠性控制,还是在应用层的安全支持(例如HTTPS),都为应用提供无法替代的强大功能和便利。

结论

综合以上所述,其实答案也呼之欲出。

现在的移动端IM、推送系统,既面对移动互联网的不确定性,又面对智能终端频繁的系统休眠、网络切换,还要考虑服务端的承载成本,对于在线服务而言UDP是比TCP更适合的方式。但是由于数据完整性、安全性的需要,又不应完全放弃TCP的可靠与安全。

所以,个人认为,更恰当的方式应该是:两种通信协议同时使用,各有侧重。UDP用于保持大量终端的在线与控制,应用与业务则通过TCP去实现。这个和FTP服务控制与数据分离,采取不同的连接,有异曲同工之处。

事实上,这个也是即时通讯巨头QQ所采用的方式。早期的时候,QQ还是主要使用TCP协议,而后来就转向了采用UDP的方式来保持在线,TCP的方式来上传和下载数据。现在,UDP是QQ的默认工作方式,表现良好。相信这个也被沿用到了微信上。

简单的考证:登录PC版QQ,关闭多余的QQ窗口只留下主窗口,并将其最小化。几分钟过后,查看系统网络连接,会发现QQ进程已不保有任何TCP连接,但有UDP网络活动。这时在发送聊天信息,或者打开其他窗口和功能,将发现QQ进程会启用TCP连接。

文章目录
  1. 1. 前言
  2. 2. 学习交流
  3. 3. 参考资料
  4. 4. UDP vs TCP
  5. 5. 互联网、移动互联网网络环境
  6. 6. 智能终端电池续航能力,系统休眠
  7. 7. IPv4资源、端口资源
  8. 8. 端口映射老化时间
  9. 9. 服务端承载能力
  10. 10. 高级应用网络通讯要求
  11. 11. 结论
|