写一个即时通信的app,服务器端需要用到哪些技术?

自学安卓有段时间了,现在想写一个即时通信类的app。不知道服务器端应该怎么写,最简单粗暴的socket+MySQL可行么? 我在网上看了些java w…
关注者
2,385
被浏览
328,319

43 个回答

我觉得奇怪,为什么在这个问题下知乎变成和百度搜索一样了。

题主问的是写即时通讯的app,服务器端需要什么技术,大部分人都在下面给出用第三方的lib是几个意思。题主真想用第三方的lib,直接去百度就搜到了,根本没必要来这里问。

我说下我个人的经历。

几年前,当我刚接触移动开发的时候,我就在想一个问题,为什么玩一款App,觉得好玩,想要分享给朋友,却只能通过微信或是QQ去分享?我很不理解为什么我要从这个App跳出去启动另一个App来完成这件事,这样不是很麻烦吗?即使好友也来下载了这款App,然后我要和他交流,也得通过微信或者QQ,麻烦死了。

为什么我不能直接在App里面直接和好友进行交流?

为什么不能直接在App里面和其他App的好友进行交流?

开发App里的即时通讯很难吗?

后来,我进了现在的这家公司,因为CEO和我面谈的时候,在最终要实现的目标上,我觉得他的想法和我惊人的一致。

经过一段时间的学习,虽然说公司的IM和Push这块儿源码不是我写的,但是在不断的拓展功能和修复Bug上,我也渐渐了解了这个事情是怎么回事儿。

协议

由于我们公司使用的是mqtt协议,所以我对这个协议是了解得比较多的。(看到其他的人都在回答使用XMPP这个协议,但是我了解得不多,不做评价)

mqtt协议是什么,怎么用,这种东西我给题主一个官网的链接,自己看去。

public.dhe.ibm.com/soft

我可以分享一个故事给题主。

我去客户那儿做支持的时候,有个做服务器的客户和我聊天,他说他以前就是做IM服务器的(一家还挺有名的公司,后来没落了,就不说了),第一次开发IM服务器的时候,啥都不会弄,然后他们领导打印了XMPP的协议和MQTT的协议,整整两大堆纸,让他把两个协议每天看一遍,等什么时候记住了,什么时候就知道开发了。

然后他真的就每天看每天看,一个星期后,两个协议都记在脑子里了,流程,传输信息头,信息内容,一字不差。再动手开始弄IM服务器,几乎没有问过同事和领导任何问题。

我说这个故事是想说,搞懂协议是做IM服务器的第一步(当然那哥们本身能力很不错,所以他弄懂了协议就知道接下来要怎么弄)。

语言和数据库和实现方式

语言方面,题主提到自己自学Android,如果不是全栈工程师,所以应该会选择Java,

数据库题主选的是MySQL。

实现方式是Socket。

我个人的见解是,题主你的选择没问题。使用任何一种语言,任何一个数据库都可以用Socket实现。但是题主你要想清楚,你想要实现的是一台什么级别的服务器能供多少用户同时在线收发消息?

我再给题主分享一个故事吧。

我室友,去年的这个时候在北京进了一家大公司,原本进去做Java Web开发,后来公司说要弄一个App,包含公司的行政,管理以及类似朋友圈等功能。因为我会Android,所以他为了绩效,向公司虚报他会Android,然后由我晚上在家负责教他怎么做。(当然他学习能力很不错)

做到后面,那个App需要IM功能,这下傻眼了,问我怎么办。我说你直接用第三方lib吧,比如我们公司的。他和领导去周旋,领导没同意,后来决定自己开发。然后从其他组调了一个据说能力很不错的做后台服务器的。那哥们鼓捣了一个星期,搭了一个mqtt协议的服务器,提供一系列收发消息的接口,说是完成了。我室友毫不犹豫地使用了,回到家还对我吹嘘IM服务器不难嘛,你看他一个星期就做好了。

一个月后,App上线了,全公司几千个员工在第一天,几乎全体都在反馈,收发消息的时候漏消息了。

他回到家问我,为什么会这样?

我问了他相关情况后得知,他们后台服务器语言是Java,数据库是Oracle,在实现mqtt协议的时候使用的是QOS为1的标准,服务器是一台8G内存20M带宽的Linux系统。

我说你们后台服务器太重,数据库不方便拓展,而且还就这么一台服务器,mqtt协议用QOS为1,简直就是做死。你们测试的时候难道没进行压力测试吗。

他说没有。因为这个App是对公司内部发布的,外面没得下载的。公司就几千人,压力也不大吧。

后面有些话我不方便说太多,反正这个App他自己除了签到打卡这个功能外,其他功能他自己都不用,今年过了年,领导说他做的App没有达到原有的期望,绩效没上去,他最后跳了。

我说这个故事想说的是,题主你用任何一种语言和数据库都可以实现,但是最终效果可能不会像你开始设想的那么美好。

即时聊天这个功能,因为是多数据小信息量的模式,使用轻量级的框架和语言(比如NodeJS,Ruby)还有非关系型数据库(比如MongoDB)是比较好的,如果选用太沉重的,那之后只能用增加服务器这种手段来实现。


说了这么多,我想表达的是,我不可能直接告诉题主要怎么做。我只是把我所知道的我所接触到的都摆在你面前,告诉你哪条路走下去可能是不好的,哪条路是相对比较好的。

以上,基于我个人经验。

刚好本科毕业设计是做一个Android即时聊天应用-EasyIM。感谢题主的这个问题,让我有动力整理下毕业设计的代码。

因为实习占用了大四的大部分时间,导致EasyIM只完成了部分功能便参与答辩。虽然最终侥幸过了毕设答辩,但效果与自己期望的相去甚远。

开始工作后,有比较多的空闲时间,我打算慢慢完善该项目,并将近期所学习的一些新技术应用到该项目中。

该项目分为两部分:

EasyIM目前实现了:

  • 用户基础功能(登录/注册)
  • 好友功能(添加/删除好友)
  • 点对点的消息发送功能(文本消息/图文消息)
  • 离线消息功能(获取离线时收到的消息,消息的接收/已读回执)

实现思路

我们先来聊聊具体实现的思路


基础协议

因为移动设备多变的网络环境,以及即时通讯应用实时在线的需求,简单地使用Scoket建立客户端与服务端,或者客户端与客户端的通信是行不通的。
当前普遍的做法是在服务端与客户端之间建立一个长连接,客户端A将消息发送给服务端,服务端再将消息转发给客户端B。
而如何建立一个长连接实现客户端与服务端的通信,以及保证连接的质量与低耗电,低耗流量是一个难题。这里就要扯上XMPP,MQTT这两个协议。

  • XMPP是PC时代的产物,其底层通讯的数据格式的XML,数据冗余性太高(约70%),比较耗流量,并且在复杂的移动网络环境下会遇到各种各样的问题。不过胜在拥有比较多的开发资料以及Openfire(底层是基于XMPP)这样一个成熟的即时聊天框架。
  • MQTT协议较之XMPP更为轻量级,其连接的建立与传输的开销都非常小,非常精简,非常适合大量节点在弱网络环境的场景,发布/订阅的模式也比较易于扩展。

很明显, 我们需要选择MQTT作为我们这个即时通信应用的基础协议,关于MQTT客户端与服务端的开源实现有:

比较遗憾的是,因为毕业设计是在太赶,我并没有自己实现(实现难度也挺大的),而是使用了第三方的推送服务。


服务端实现

整个服务端实现比较简单,因为整个项目采用重客户端-轻服务端的开发策略,所以服务端的逻辑非常少,总共就4张表,12个接口。使用Restful风格的API。
用户模块,好友模块比较简单,无外就是增删查改。
值得一提的是消息模块,我将整个系统的各种功能事件,抽象成为"消息事件“, 比如,添加好友是一条消息,确认添加好友也是一条消息, 发送文本是一条文本消息,发送图文是图文消息。服务端只负责将该消息转发给指定客户端,而不关注消息是什么类型。而客户端接收到消息并根据消息类型进行其他逻辑操作。其他细节谈起来就没完没了了,附赠2张时序图。


发送文本消息时序图&添加好友时序图



客户端实现

Android端的实现没啥值得说的,实际上我学习Android也就两个月,项目经验非常有限,所以很多代码结构上写的挺混乱。
堆砌式地使用了近期流行的各种Android技术,RxJava,EventBus,MVP,没啥技术难点。
IM还是在Android上非常好的实践项目,UI,网络,架构等都能学到不少东西。题主应该也是刚学Android,有兴趣也可以交流交流。