前言

这是我的毕业设计。
刚开始确定这个课题的时候是因为以前有稍微研究过一些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的更多相关文章

  1. 开发一款即时通讯App,从这几步开始

    欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 本文由腾讯云视频发表于云+社区专栏 关注公众号"腾讯云视频",一键获取 技术干货 | 优惠活动 | 视频方案 " ...

  2. MQTT是IBM开发的一个即时通讯协议,构建于TCP/IP协议上,是物联网IoT的订阅协议,借助消息推送功能,可以更好地实现远程控制

    最近一直做物联网方面的开发,以下内容关于使用MQTT过程中遇到问题的记录以及需要掌握的机制原理,主要讲解理论. 背景 MQTT是IBM开发的一个即时通讯协议.MQTT构建于TCP/IP协议上,面向M2 ...

  3. 即时通讯App怎样才能火?背后的技术原理,可以从这5个角度切入

    欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 本文由腾讯云视频发表于云+社区专栏 关注公众号"腾讯云视频",一键获取 技术干货 | 优惠活动 | 视频方案 社交场景 ...

  4. 个人开源作品,即时通讯App支持文本、语音、图片聊天

    开源一个即时通讯类App,支持纯文本.语音.地理位置.图片聊天,同时还加入了好友圈功能,支持分享动态和发送图片,支持搜索附近的人,使用的百度地图定位功能:由Bmob后端云提供服务器支持,欢迎喜欢的伙伴 ...

  5. 从零开始, 开发一个 Web Office 套件 (2): 富文本编辑器

    书接前文: 从零开始, 开发一个 Web Office 套件 (1): 富文本编辑器 这是一个系列博客, 最终目的是要做一个基于HTML Canvas 的, 类似于微软 Office 的 Web Of ...

  6. 移动跨平台开发框架Ionic开发一个新闻阅读APP

    移动跨平台开发框架Ionic开发一个新闻阅读APP 前言 这是一个系列文章,从环境搭建开始讲解,包括网络数据请求,将持续更新到项目完结.实战开发中遇到的各种问题的解决方案,也都将毫无保留的分享给大家. ...

  7. 从零开始, 开发一个 Web Office 套件 (3): 鼠标事件

    这是一个系列博客, 最终目的是要做一个基于HTML Canvas 的, 类似于微软 Office 的 Web Office 套件, 包括: 文档, 表格, 幻灯片... 等等. 对应的Github r ...

  8. 从零开始, 开发一个 Web Office 套件(4):新的问题—— z-index

    <从零开始, 开发一个 Web Office 套件>系列博客目录 这是一个系列博客, 最终目的是要做一个基于HTML Canvas 的, 类似于微软 Office 的 Web Office ...

  9. 《从零开始, 开发一个 Web Office 套件》系列博客目录

    这是一个系列博客, 最终目的是要做一个基于HTML Canvas 的, 类似于微软 Office 的 Web Office 套件, 包括: 文档, 表格, 幻灯片... 等等. 对应的Github r ...

随机推荐

  1. USACO section 1.1 C++题解

    USACO section1.1:DONE 2017.03.03 TEXT Submitting Solutions DONE 2017.03.04 PROB Your Ride Is Here [A ...

  2. 转:Maven项目编译后classes文件中没有dao的xml文件以及没有resources中的配置文件的问题解决

    问题1:在做spring+mybatis时,自动扫描都配置正确了,却在运行时出现了如下错误.后来查看target/classes/.../dao/文件夹下,发现只有mapper的class文件,而没有 ...

  3. React入门---开始前的准备(下)-3

    React开始前的准备(下): ·配置webpack热加载(热加载就是修改js文件,点击保存之后,浏览器会自动刷新,提高开发效率) 1. 全局安装: npm install webpack -g np ...

  4. List的多维度排序案例演示~

    文章也已同步到我的csdn:http://blog.csdn.net/u012881584/article/details/72377510 关于List的多维度排序. 日常工作中有很多关于list的 ...

  5. 最常用的缓存技术---redis入门

      Redis简介 Redis是基于内存,也可以基于磁盘持久化nosql数据库,使用c语言开发. 数据存储结构:key-value 安装环境准备 Redis使用c语言开发,需要使用gcc编译程序进行编 ...

  6. SpringMVC——DispatcherServlet的IoC容器(Web应用的IoC容器的子容器)创建过程

    在上一篇<Spring--Web应用中的IoC容器创建(WebApplicationContext根应用上下文的创建过程)>中说到了Web应用中的IoC容器创建过程.这一篇主要讲Sprin ...

  7. 「CODVES 1922 」骑士共存问题(二分图的最大独立集|网络流)&dinic

    首先是题目链接  http://codevs.cn/problem/1922/ 结果发现题目没图(心情复杂 然后去网上扒了一张图 大概就是这样了. 如果把每个点和它可以攻击的点连一条边,那问题就变成了 ...

  8. Apache solr(二)

    上一篇试着进行了solr的安装和配置,以及如何solr的检索,今天试着简单的将solr连接MySQL数据库(才尝试了单表.一对多和多对多的还有待研究) 1.MySQL的目录结构 2.新建一个democ ...

  9. Lists, Maps and Sets in Java

    ArrayList vs LinkedList vs Vector From the hierarchy diagram, they all implement List interface. The ...

  10. YYLabel 自动布局 富文本文字点击事件

    YYLabel显示多行除了需要设置numberOfLines = 0以外,还需要设置preferredMaxLayoutWidth最大的宽度值才可以生效多行效果 YYLabel中的NSMutableA ...