[iOS]从零开始开发一个即时通讯APP
前言
这是我的毕业设计。
刚开始确定这个课题的时候是因为以前有稍微研究过一些XMPP协议,在这个基础上做起来应该不难。然后开始选技术的时候还有半年,我想为什么不从更底层做起呢!那就不用XMPP,当时接触过相关的即时通讯技术还有WebSocket,那为什么直接从更底层的Socket开始封装呢
服务端就用Go语言吧,用来做IM服务器和HTTP服务器都很好。
技术选型
既然是基于Socket,iOS端我并不准备中C语言的Socket开发封装起,而是使用一个第三方库CocoaAsyncSocket。XMPP的iOS framework也是从这个库开始封装。而Go语言的IM服务端则直接使用原生开发即可,无论是UDP还是TCP都已经封装的很好。
HTTP服务器使用的框架是Gin,已经相当成熟,可以用于大型服务端的开发了。
关于传输的数据格式,XMPP使用的是XML,但是体积太大,冗余过多不必要的数据,考虑了很久好像也没必要自己封装二进制的数据格式,我用的是Google的protocol buffer。HTTP服务器还是使用JSON。
我还需要存储客户端的IP地址,由于需要快速读写,我使用的是Redis。
AccessToken验证方式使用的是JSON Web Token(JWT)
实现思路
我的想法是使用UDP Socket来传输数据,至于为什么使用UDP呢,一开始的想法是UDP比TCP快,虽然可能会丢包但是可以试着优化。关于使用UDP来做IM这个想法也被一些大神喷过,但是这都是我自己的想法,就这样做着先。
使用UDP会丢包,所以我想需要一个回执机制,接收端收到了消息后就给发送端发送一个回执,这个回执包括这条消息的ID,如果发送方过一段时间还没有接受到回执的时候则重新发送。而且这个回执还不能丢,所以我使用TCP来发送回执。
UDP是无连接性的,还是要使用TCP来连接服务端,表明登录状态。所以TCP的作用是连接和发送回执。
具体思路是当客户端登录和重新连接的时候,客户端使用UDP Socket绑定端口,然后使用TCP Socket来发送UDP 地址给服务端,服务端把用户的ID和UDP地址存进Redis,等发送方发送的消息包含接收端的用户ID,服务端再从Redis取出接收方的UDP地址进行转发。
发送图片我是这样实现的,我会把图片上传到七牛云,发图片的URL来发送,接收端只需要使用URL来加载图片即可
简单封装一个通讯协议
就叫简单的即时通讯协议,Simple Instant Messaging Protocol,简称SIMP
我想是基于连接的,所以一个用户对应一个 SIMPConnection,每一个SIMPConnection是一个单例,使用代理进行回调
- (BOOL)connectionToRemoteHost:(NSString *)host port:(NSInteger)port forUser:(NSString *)userID;
连接需要用户ID和服务器的地址和端口
在连接的时候就创建TCP和UDP Socket 进行连接,TCP Socket要发送连接的数据,包括UDP Socket的地址
- (BOOL)connectionToRemoteHost:(NSString *)host port:(NSInteger)port forUser:(NSString *)userID {
self.host = host;
self.port = port;
self.userID = userID;
self.tcpSocket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0)];
self.udpSocket = [[GCDAsyncUdpSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_main_queue()];
return [self connect];
}
- (BOOL)connect {
NSError *error;
BOOL tcpSuccess = [self.tcpSocket connectToHost:self.host onPort:self.port error:&error];
CheckError(@"TCPSocketConnectToHost", &error);
BOOL udpSuccess = [self.udpSocket connectToHost:self.host onPort:self.port + 1 error:&error];
CheckError(@"UDPSocketConnectToHost", &error);
[self.udpSocket beginReceiving:&error];
CheckError(@"beginReceiving", &error);
[self sendConnectData];
return tcpSuccess && udpSuccess;
}
还有封装一个 SIMPMessage
里面包含protobuf的数据
我的protobuf数据是这样的,版本,消息的ID,时间,文字内容,图片URL,发送方的ID和接收方的ID,消息类型,图片的比例
syntax = "proto3";
message Message {
float version = 1;
uint64 messageId = 2;
uint64 time = 3;
string content = 4;
string imageURL = 5;
string fromUser = 6;
string toUser = 7;
MessageType type = 8;
float imageScale = 9;
enum MessageType {
TEXT = 0;
IMAGE = 1;
AUDIO = 2;
CONNECT = 3;
RECEIPT = 4;
}
}
还有消息队列,群聊等一些我已经有想法但是还没实现的功能
架构
关于整个APP的流程如下

关于iOS端,使用了MVVM设计模式结合RAC,在Controller里面只需要组合一下视图和布局,绑定数据即可,把处理数据和大部分逻辑都放在了ViewModel里面,结构还算清晰。
关于数据管理,我使用了一个Redux思想的全局数据调度中心,实现了单向数据流,数据的持久化等。数据持久化用到了FMDB。但是大部分代码是一个大神写的,很屌。
效果和下一步
目前实现传输文字和图片,好友添加还是在后台添加(前端还没做),动态模块等。
登录
通讯录
详细资料
个人资料
聊天界面
Demo
先上传到了github,目前功能还不完善,还会持续开发
https://github.com/AscenZ/Hey
[iOS]从零开始开发一个即时通讯APP的更多相关文章
- 开发一款即时通讯App,从这几步开始
欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 本文由腾讯云视频发表于云+社区专栏 关注公众号"腾讯云视频",一键获取 技术干货 | 优惠活动 | 视频方案 " ...
- MQTT是IBM开发的一个即时通讯协议,构建于TCP/IP协议上,是物联网IoT的订阅协议,借助消息推送功能,可以更好地实现远程控制
最近一直做物联网方面的开发,以下内容关于使用MQTT过程中遇到问题的记录以及需要掌握的机制原理,主要讲解理论. 背景 MQTT是IBM开发的一个即时通讯协议.MQTT构建于TCP/IP协议上,面向M2 ...
- 即时通讯App怎样才能火?背后的技术原理,可以从这5个角度切入
欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 本文由腾讯云视频发表于云+社区专栏 关注公众号"腾讯云视频",一键获取 技术干货 | 优惠活动 | 视频方案 社交场景 ...
- 个人开源作品,即时通讯App支持文本、语音、图片聊天
开源一个即时通讯类App,支持纯文本.语音.地理位置.图片聊天,同时还加入了好友圈功能,支持分享动态和发送图片,支持搜索附近的人,使用的百度地图定位功能:由Bmob后端云提供服务器支持,欢迎喜欢的伙伴 ...
- 从零开始, 开发一个 Web Office 套件 (2): 富文本编辑器
书接前文: 从零开始, 开发一个 Web Office 套件 (1): 富文本编辑器 这是一个系列博客, 最终目的是要做一个基于HTML Canvas 的, 类似于微软 Office 的 Web Of ...
- 移动跨平台开发框架Ionic开发一个新闻阅读APP
移动跨平台开发框架Ionic开发一个新闻阅读APP 前言 这是一个系列文章,从环境搭建开始讲解,包括网络数据请求,将持续更新到项目完结.实战开发中遇到的各种问题的解决方案,也都将毫无保留的分享给大家. ...
- 从零开始, 开发一个 Web Office 套件 (3): 鼠标事件
这是一个系列博客, 最终目的是要做一个基于HTML Canvas 的, 类似于微软 Office 的 Web Office 套件, 包括: 文档, 表格, 幻灯片... 等等. 对应的Github r ...
- 从零开始, 开发一个 Web Office 套件(4):新的问题—— z-index
<从零开始, 开发一个 Web Office 套件>系列博客目录 这是一个系列博客, 最终目的是要做一个基于HTML Canvas 的, 类似于微软 Office 的 Web Office ...
- 《从零开始, 开发一个 Web Office 套件》系列博客目录
这是一个系列博客, 最终目的是要做一个基于HTML Canvas 的, 类似于微软 Office 的 Web Office 套件, 包括: 文档, 表格, 幻灯片... 等等. 对应的Github r ...
随机推荐
- Dalsa Sherlock 直连千兆网相机(通用驱动)
支持 Sherlock 7.1.7.2,用于千兆网相机与 Sherlock 的连接. 可适用于很多厂商的相机,如:巴斯勒(Basler),JAI,堡盟相机(Baumer),灰点相机(Point Gre ...
- nodejs环境的搭建(linux环境centos6.5)
更新yum # yum update 新建用户 # adduser user设置密码 # passwd user 允许用户通过ssl远程访问 # vi /etc/ssh/sshd_config 在文末 ...
- [ABP实战开源项目]---ABP实时服务-通知系统.发布模式
简介 在ABP中,提供了通知服务.它是一个基于实时通知的基础设施.分为订阅模式和发布模式. 本次会在项目中使用发布模式来演示一个用户注册后,收到的欢迎信息. 发布模式 首先我们在领域层建立" ...
- Python初识文本基本操作
初识文本的基本操作 怎么在文件里面写内容和都内容 文件操作过程 1,找到文件 文件路径 2,打开文件 file_obj=file(文件路径,模式) 3,文件操作,读写文件 file_obj.read( ...
- css 3d 基础知识
css3d 总结 3d transform (3D变形)(rotate skew scale translate) 基础知识 perspective (视距,景深) perspective-origi ...
- Visual Studio 2017 针对移动开发的新特性介绍
欢迎大家持续关注葡萄城控件技术团队博客,更多更好的原创文章尽在这里~~ Visual Studio是世界上最好的IDE之一,如果是 .NET世界,那就没有之一了(^_^),而最近推出的Visual S ...
- 在Adapter中如何关闭当前Activity
很多时候我们需要在点击adapter条目的时候关闭当前界面,把所点击条目的信息带到前一个界面,同时关闭当前界面. 这个 时候就需要在adapter对某一个点击事件做处理. 代码如下: holder.l ...
- 关于JS的页面跳转
"window.location.href"."location.href"是本页面跳转 "parent.location.href"是上一 ...
- javaWeb学习总结(10)- Filter(过滤器)常见应用(3)
一.统一全站字符编码 通过配置参数charset指明使用何种字符编码,以处理Html Form请求参数的中文问题 package me.gacl.web.filter; import java.io. ...
- Lambda类库篇 —— Streams API, Collector和并行
本文是深入理解Java 8 Lambda系列的第二篇,主要介绍Java 8针对新增语言特性而新增的类库(例如Streams API.Collectors和并行). 本文是对 Brian Goetz 的 ...