《移动IM开发指南》系列文章将会介绍一个IM APP的方方面面,包括技术选型、登陆优化等。此外,本文作者会结合他在网易云信多年iOS IM SDK开发的经验,深度分析实际开发中的各种常见问题。

推荐阅读

移动IM开发指南2:心跳指令详解

移动IM开发指南3:如何优化登录模块

通讯方式选择

IM通讯方式无非两种选择:设备直连(P2P)和通过服务器中转。

(1)P2P

P2P多见于局域网内聊天工具,典型的应用有:飞鸽传书等。这类软件在启动后一般做两件事情:

l 进行UDP广播:发送自己信息和接受同局域网内其他端信息

l 开启TCP监听:等待其他端进行连接

详细的流程可以参考飞鸽传书源码。但是这种方式在有种种限制和不便:一方面它只适合在线的点对点消息传输,对离线,群组等业务支持不够。另一方面由于 NAT 的存在,使得不同局域网内机器互联难度大大上升,在某些网络类型(对称NAT)下无法建立连接。

(2)服务器中转

几乎所有互联网IM产品都采用服务器中转这种方式进行消息传输,相对于P2P的方式,它有如下的优点:

l 能够支持更多P2P无法支持或支持不好的业务,如离线消息,群组,聊天室服务

l 方便业务逻辑的拓展和新旧版本的兼容

当然它也有自己的问题:服务器架构复杂,并发要求高。

网络连接方式

IM主流网络连接方式有两种:

l 基于TCP的长连接

l 基于HTTP短连接PULL的方式

后者常见于WEB IM系统(当然现在很多WEB IM都是基于WebSocket实现),它的优点是实现简单,方便开发上手,问题是流量大,服务器负载较大,消息及时性无法很好地保证,对大规模的用户量支持不够,比较适合小型的IM系统,如小网站的客户系统。

基于TCP长连接则能够更好地支持大批量用户,问题是客户端和服务器的实现比较复杂。当然也还有一些变种,如下行使用MQTT进行服务器通知/消息的下发,上行使用HTTP短连接进行指令和消息的上传。这种方式能够保证下行消息/指令的及时性,但是在弱网络下上行慢的问题还是比较严重。早期的来往就是基于这种方式。

协议选择

IM协议选择原则一般是:易于拓展,方便覆盖各种业务逻辑,同时又比较节约流量。后一点的需求在移动端IM上尤其重要。

常见的协议有:XMPP;SIP;MQTT;私有协议。

l XMPP协议的优点在于:协议开源,可拓展性强,在各个端(包括服务器)有各种语言的实现,开发者接入方便。

但是缺点也是不少:XML表现力弱,有太多冗余信息,流量大,实际使用时有大量天坑。

l SIP协议多用于VOIP相关的模块,是一种文本协议,由于我并没有实际用过,所以不做评论,但从它是文本协议这一点几乎可以断定它的流量不会小。

l MQTT的优点是协议简单,流量少,但是它并不是一个专门为IM设计的协议,多使用于推送。

l 市面上几乎所有主流IM APP都是使用私有协议,一个被良好设计的私有协议一般有如下优点:高效,节约流量(一般使用二进制协议),安全性高,难以破解。缺点则是在开发初期没有现有样列可以参考,对于设计者的要求比较高。

一个好的协议需要满足如下条件:高效,简洁,可读性好,节约流量,易于拓展,同时又能够匹配当前团队的技术堆栈。基于如上原则,我们可以推出: 如果团队小,团队技术在IM上积累不够可以考虑使用XMPP或者MQTT+HTTP短连接的实现。反之可以考虑自己设计和实现私有协议。

私有协议的设计

序列化选择

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

协议格式设计

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

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

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

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

上面就是IM系统大致的选型过程,包含了通讯方式,连接方式,协议选择,协议设计。但是实际开发过程中还有大量的问题需要处理。《移动IM开发指南》系列文章第二篇将会为大家解答实际开发中的常见问题。

移动IM开发指南1:如何进行技术选型的更多相关文章

  1. EMIS快速开发平台 - 微服务版技术选型

    http://demo.zuoyour.com/system/login EMIS快速开发平台 - 微服务版技术选型 开发框架:Spring Boot 2.1.3.RELEASE 微服务:Spring ...

  2. 吴裕雄--天生自然PythonDjangoWeb企业开发:框架基础和技术选型

    简单的Web Server import socket eol1 = b'\n\n' eol2 = b'\n\r\n' body = '''Hello,world!<h1>tszrwyx& ...

  3. 转:Google技术开发指南:给大学生自学的建议

    原文来自于:http://blog.jobbole.com/80621/ 技术开发指南 想要成为成功的软件工程师,必须拥有坚实的计算机科学的基础.本指南针对大学生,给出一条自学途径,让学生以科班和非科 ...

  4. 【web开发 | 移动APP开发】 Web 移动开发指南(2017.01.05更新)

    版本记录 - 版本1.0 创建文章(2016.12.30) - 版本1.1 更正了hybird相关知识:增加了参考文章(2017.01.05): + Web APP更正为响应式移动站点与页面,简称响应 ...

  5. FreeMarker模板开发指南知识点梳理

    freemarker是什么? 有什么用? 怎么用? (问得好,这些都是我想知道的问题) freemarker是什么? FreeMarker 是一款 模板引擎: 即一种基于模板和要改变的数据, 并用来生 ...

  6. JVM 平台上的各种语言的开发指南

    JVM 平台上的各种语言的开发指南 为什么我们需要如此多的JVM语言? 在2013年你可以有50中JVM语言的选择来用于你的下一个项目.尽管你可以说出一大打的名字,你会准备为你的下一个项目选择一种新的 ...

  7. 移动应用安全开发指南(Android)--完结篇(http://www.bubuko.com/infodetail-577312.html)

    1.认证和授权 概述 认证是用来证明用户身份合法性的过程,授权是用来证明用户可以合法地做哪些事的过程,这两个过程一般是在服务器端执行的,但也有的APP出于性能提升或用户体验等原因,将其做在客户端完成, ...

  8. Knockout应用开发指南(完整版) 目录索引

    http://learn.knockoutjs.com/  所有示例和代码都在在上面直接运行预览 注意:因为它用了google的cdn加速,所要要用代_理+_翻_墙才能正常加载 使用Knockout有 ...

  9. 智捷公开课马上开始了-欢迎大家一起讨论学习-第一系列读《Swift开发指南(修订版) 》看Swift视频教程

    引用: 智捷课堂携手51CTO学院.图灵教育联合举办iOS线上培训就业班系列体验公开课. 分享移动开发.移动设计方向最新,最热,最抢眼技术热点以及设计经验.我们每周将最少举办一次公开课,同时会提前安排 ...

随机推荐

  1. 使用Toast进行用户提醒(转)

    Toast是Android提供的一个轻量级的用户提醒控件,使用也很简单,就相当一个极简的dialog!!!下面将向您介绍一些Toast的详细用法: 1.普遍使用的方法: Context context ...

  2. 王立平--GC

    Gabage Collection:垃圾回收 是.net中对内存管理的一种功能. 垃圾回收器跟踪并回收托管内存中分配的对象,定期运行垃圾回收以回收分配给没有有效引用的对象的内存. 当使用可用内存不能满 ...

  3. Opencv中SVM样本训练、归类流程及实现

    支持向量机(SVM)中最核心的是什么?个人理解就是前4个字--"支持向量",一旦在两类或多累样本集中定位到某些特定的点作为支持向量,就可以依据这些支持向量计算出来分类超平面,再依据 ...

  4. hdoj 5087 Revenge of LIS II 【第二长单调递增子】

    称号:hdoj 5087 Revenge of LIS II 题意:非常easy,给你一个序列,让你求第二长单调递增子序列. 分析:事实上非常easy.不知道比赛的时候为什么那么多了判掉了. 我们用O ...

  5. CefSharp For WPF自定义右键菜单栏

    原文:CefSharp For WPF自定义右键菜单栏 初始化 <!--浏览器--> <cefSharpWPF:ChromiumWebBrowser Name="webBr ...

  6. WPF 获得DataGridRow和 DataGridCell的方法

    原文:WPF 获得DataGridRow和 DataGridCell的方法 原文地址 简介 在WPF中,DataGrid控件并没有提供访问其DataGridRow或者DataGridCell的方法. ...

  7. ASP Get请求

    <!DOCTYPE html><html><head><meta http-equiv="Content-Type" content=&q ...

  8. C/C++ static用法

    这篇文章没有太多的实际内容,简单记录下static的用法.顺便试一下用markdown来写文章. 1. 在函数中使用 我们都知道在一个函数中的变量是存储在栈区中,函数的每一次调用都伴随着变量的重新定义 ...

  9. C#获取带汉字的字符串长度

    正常情况下,我们是直接去string的length的,但是汉字是有两个字节的,所以直接用length是错的.如下图: 所以应该用以下代码来获取长度: private void button1_Clic ...

  10. JVM的几个介绍

    关于jvm内存的几点 jvm在运行时分为方法区(Method Area) .虚拟机栈(VM Stack).本地方法栈(Native Method Stack).堆 (Heap).程序计数器 (Prog ...