商业化IM 客户端接口设计分析

  对于刚接触IM(即时通讯)开发,通过阅读成熟的商业代码能够对即时通讯软件大体上有个认识,比如消息发送,消息接受,消息监听,群聊,单聊,聊天室。我这边直接拿[Gobelieve IM]源码来做剖析。IMService在代码层级里起着承上启下的作用,负责发送消息,接受消息(聊天消息,系统消息,控制命令消息(比如邀请VOIP,退群,加群)),消息在客户端转发,消息类型判断和分发,消息observer的增加和删除,IMService本身会根据业务需求实现handlers对接到数据传输层(socket)。Observers是衔接IMService和UI层。如果只侧重于UI层开发,重点是Observers,比如PeerMessageObserver是一对一聊天监听,GroupMessageObserver:群聊天监听,RoomMessageObserver:聊天室监听。

下面直接上接口代码来说,
@class IMessage;

  IMessage 模型类的前置声明

@protocol IMPeerMessageHandler <NSObject>
-(BOOL)handleMessage:(IMMessage*)msg uid:(int64_t)uid;
-(BOOL)handleMessageACK:(int)msgLocalID uid:(int64_t)uid;
-(BOOL)handleMessageFailure:(int)msgLocalID uid:(int64_t)uid;
@end

一对一聊天的hanlder定义,IM有一个ACK的设计,用来显示消息是否已经通过服务器下发到对方客户端。具体的函数,handleMessage()接收到消息的处理函数。handleMessageACK()接收到消息已读的处理函数。 handleMessageFailure()接收到消息发送失败的处理函数。

@protocol IMGroupMessageHandler <NSObject>

-(BOOL)handleMessage:(IMMessage*)msg;
-(BOOL)handleMessageACK:(int)msgLocalID gid:(int64_t)gid;
-(BOOL)handleMessageFailure:(int)msgLocalID gid:(int64_t)gid;

-(BOOL)handleGroupNotification:(NSString*)notification;
@end

群聊天的hanlder定义,接口上比单聊多一个群状态改变的处理,还有就是单聊下发的是个人ID,群聊下发的是群聊ID,同样的函数,handleMessage()接收到消息的处理函数。handleMessageACK()接收到消息已读的处理函数。 handleMessageFailure()接收到消息发送失败的处理函数。handleGroupNotification(),处理群状态改变的函数,比如群名称改变,群成员改变,群解散等等事件。

@protocol IMCustomerMessageHandler <NSObject>
-(BOOL)handleCustomerSupportMessage:(CustomerMessage*)msg;
-(BOOL)handleMessage:(CustomerMessage*)msg;
-(BOOL)handleMessageACK:(CustomerMessage*)msg;
-(BOOL)handleMessageFailure:(CustomerMessage*)msg;
@end

  客服聊天的handler定义。

@protocol LoginPointObserver <NSObject>
//用户在其他地方登陆
-(void)onLoginPoint:(LoginPoint*)lp;
@end

  多端登录事件监听。

@protocol PeerMessageObserver <NSObject>
@optional
-(void)onPeerMessage:(IMMessage*)msg;

//服务器ack
-(void)onPeerMessageACK:(int)msgLocalID uid:(int64_t)uid;

//消息发送失败
-(void)onPeerMessageFailure:(int)msgLocalID uid:(int64_t)uid;

//对方正在输入
-(void)onPeerInputing:(int64_t)uid;

@end

  一对一聊天的Observer的定义,提供了对输入状态监听的接口,用来实现,实时获取对方是否在编辑消息。

@protocol GroupMessageObserver <NSObject>
@optional
-(void)onGroupMessage:(IMMessage*)msg;
-(void)onGroupMessageACK:(int)msgLocalID gid:(int64_t)gid;
-(void)onGroupMessageFailure:(int)msgLocalID gid:(int64_t)gid;

-(void)onGroupNotification:(NSString*)notification;
@end

  群聊天的Observer的定义。

@protocol RoomMessageObserver <NSObject>
@optional
-(void)onRoomMessage:(RoomMessage*)rm;
-(void)onRoomMessageACK:(RoomMessage*)rm;
-(void)onRoomMessageFailure:(RoomMessage*)rm;

@end

  聊天室消息Observer的定义。

@protocol RTMessageObserver <NSObject>

@optional
-(void)onRTMessage:(RTMessage*)rt;

@end

@protocol SystemMessageObserver <NSObject>
@optional
-(void)onSystemMessage:(NSString*)sm;

@end

  系统消息的Observer的定义。

@protocol CustomerMessageObserver <NSObject>
@optional
-(void)onCustomerMessage:(CustomerMessage*)msg;
-(void)onCustomerSupportMessage:(CustomerMessage*)msg;

//服务器ack
-(void)onCustomerMessageACK:(CustomerMessage*)msg;
//消息发送失败
-(void)onCustomerMessageFailure:(CustomerMessage*)msg;
@end

  客服消息的Observer的定义。

@protocol VOIPObserver <NSObject>

-(void)onVOIPControl:(VOIPControl*)ctl;

@end

  支持整合VOIP功能的Observer的定义。

@interface IMService : TCPConnection
@property(nonatomic, copy) NSString *deviceID;
@property(nonatomic, copy) NSString *token;
@property(nonatomic) int64_t uid;
//客服app需要设置,普通app不需要设置
@property(nonatomic) int64_t appID;

@property(nonatomic, weak)id<IMPeerMessageHandler> peerMessageHandler;//一对一聊天Handler
@property(nonatomic, weak)id<IMGroupMessageHandler> groupMessageHandler;//群聊handler
@property(nonatomic, weak)id<IMCustomerMessageHandler> customerMessageHandler;//客服handler

当前的IMService实现了三个(一对一聊天,群聊,客服)handler,可以按自己需要增加新的handler类型。消息统一在IMService做转发。
根据注册的Observer,传递到对该消息类型感兴趣的界面。

+(IMService*)instance;//IMService是单例的形式使用

-(BOOL)isPeerMessageSending:(int64_t)peer id:(int)msgLocalID;
-(BOOL)isGroupMessageSending:(int64_t)groupID id:(int)msgLocalID;
-(BOOL)isCustomerSupportMessageSending:(int)msgLocalID
                            customerID:(int64_t)customerID
                         customerAppID:(int64_t)customerAppID;
-(BOOL)isCustomerMessageSending:(int)msgLocalID storeID:(int64_t)storeID;

-(BOOL)sendPeerMessage:(IMMessage*)msg;
-(BOOL)sendGroupMessage:(IMMessage*)msg;
-(BOOL)sendRoomMessage:(RoomMessage*)msg;
//顾客->客服
-(BOOL)sendCustomerMessage:(CustomerMessage*)im;
//客服->顾客
-(BOOL)sendCustomerSupportMessage:(CustomerMessage*)im;
-(BOOL)sendRTMessage:(RTMessage*)msg;

-(void)enterRoom:(int64_t)roomID;
-(void)leaveRoom:(int64_t)roomID;

//正在输入
-(void)sendInputing:(MessageInputing*)inputing;
//更新未读的消息数目
-(void)sendUnreadCount:(int)unread;

-(void)addPeerMessageObserver:(id<PeerMessageObserver>)ob;
-(void)removePeerMessageObserver:(id<PeerMessageObserver>)ob;

-(void)addGroupMessageObserver:(id<GroupMessageObserver>)ob;
-(void)removeGroupMessageObserver:(id<GroupMessageObserver>)ob;

-(void)addLoginPointObserver:(id<LoginPointObserver>)ob;
-(void)removeLoginPointObserver:(id<LoginPointObserver>)ob;

-(void)addRoomMessageObserver:(id<RoomMessageObserver>)ob;
-(void)removeRoomMessageObserver:(id<RoomMessageObserver>)ob;

-(void)addSystemMessageObserver:(id<SystemMessageObserver>)ob;
-(void)removeSystemMessageObserver:(id<SystemMessageObserver>)ob;

-(void)addCustomerMessageObserver:(id<CustomerMessageObserver>)ob;
-(void)removeCustomerMessageObserver:(id<CustomerMessageObserver>)ob;

-(void)addRTMessageObserver:(id<RTMessageObserver>)ob;
-(void)removeRTMessageObserver:(id<RTMessageObserver>)ob;

-(void)pushVOIPObserver:(id<VOIPObserver>)ob;
-(void)popVOIPObserver:(id<VOIPObserver>)ob;

-(BOOL)sendVOIPControl:(VOIPControl*)ctl;

@end

  坑下挖好,慢慢补充,完整的代码和DEMO可以到[Gobelieve IM]查看。

[1]: http://developer.gobelieve.io/

时间: 2024-10-15 09:27:10

商业化IM 客户端接口设计分析的相关文章

关于客户端接口分页sql语句

今天突然翻到为客户端写分页数据的sql,发现其实逻辑不对.按照id降序 当时这样写的: #翻上一页: select 字段 from 表 where id>lastId order by id desc limit pageSize #翻下一页: select 字段 from 表 where id<lastId order by id desc limit pageSize lastId是临近id,即上一页是最上面的id,下一页是最下面的id pageSize是页面条数 显然,逻辑有问题. 如果

手机客户端接口开发文档模板整理

这是个人整理的手机开发文档模板,方便自己以后编写文档. 大体内容如下,详细在个人csdn中下载: 移动端转发短信上传温湿度信息 移动端负责后台接收温湿度传感器通过短信发来的温湿度和经纬度信息,移动端后台接收后上传web服务器,当然传感器也可通过wifi直接上传web服务器.返回小写true或者false. 请求URL: http://192.168.1.101:8080/RFID/addTransTemperature.action?phoneNumber=123&temperature=12.

使用fiddler轻轻松松制造客户端接口time out的情况

1.打开fiddler,过滤出你想要的请求 2.复制出你想要中断的请求 3.设置中断这个请求,bpu+请求,回车(详情请百度fiddle默认命令) 4.ctrl+x(清楚所有的请求),刷新页面,重新获取请求,获取response信息 5.若长时间得不到time out的效果,右键点击abort(忽略请求),反复几次,就可以得到time out的效果啦!!! 6.当你想这条请求恢复正常的时候,在下方命令框内输入bpu就ok~~~

spring整合redis客户端及缓存接口设计(转)

一.写在前面 缓存作为系统性能优化的一大杀手锏,几乎在每个系统或多或少的用到缓存.有的使用本地内存作为缓存,有的使用本地硬盘作为缓存,有的使用缓存服务器.但是无论使用哪种缓存,接口中的方法都是差不多.笔者最近的项目使用的是memcached作为缓存服务器,由于memcached的一些限制,现在想换redis作为缓存服务器.思路就是把memached的客户端换成redis客户端,接口依然是原来的接口,这样对系统可以无损替换,接口不变,功能不变,只是客户端变了.本文不介绍缓存的用法,不介绍redis

spring整合redis客户端及缓存接口设计

一.写在前面 缓存作为系统性能优化的一大杀手锏,几乎在每个系统或多或少的用到缓存.有的使用本地内存作为缓存,有的使用本地硬盘作为缓存,有的使用缓存服务器.但是无论使用哪种缓存,接口中的方法都是差不多.笔者最近的项目使用的是memcached作为缓存服务器,由于memcached的一些限制,现在想换redis作为缓存服务器.思路就是把memached的客户端换成redis客户端,接口依然是原来的接口,这样对系统可以无损替换,接口不变,功能不变,只是客户端变了.本文不介绍缓存的用法,不介绍redis

用C#开发基于自动化接口的OPC客户端

OPC全称是Object Linking and Embedding(OLE) for Process Control,它的出现为基于Windows的应用程序和现场过程控制应用建立了桥梁.OPC作为一整套接口.属性和方法的协议标准集,与具体的开发语言没有关系. 1.OPC客户端接口方式 开发OPC客户端程序,其访问接口方式有多种,根据官方提供的资料大约有如下几种方式: 使用OPCNetAPI,需要用到OPCNetAPI.dll,OPCNetAPI.Com.dll 使用自动化接口,需要用到OPCD

IBM AIX5.3 linux下C/C++实现HTTPS接口

最近在工作中需要开发一个Https接口,其不同于http.soap等协议,可以直接组织报文并发送,不存在加密,认证和获取密钥等安全操作.且之前开发的项目没有开发过这类接口,所以当时压力很大. 通过网上查阅资料,要实现https接口,必须现在本机上安装openssl和curl(说明:只用opessl也可以实现https,目前我是使用openssl和curl). 在安装openssl和curl过程中吃了不少苦头,因为服务器是IBM AIX5.3,服务器很久没升级打补丁很多软件安装都不能顺利进行,可以

Filter过滤器简单应用( 接口访问控制 )

一.描述 在提供安卓.IOS客户端接口时,可以在登陆接口分配Session给客户端,用于判断其他接口是否是合法访问,以避免将所有的接口都暴露在web中可以由路径直接访问.但是最近的一个项目中的移动接口并没有给客户端分配Session,所以所有的接口都可以通过路径直接访问,这种方式会存在一定的风险性,只能通过接口对参数进行更精确的验证.一般情况下为方便管理会将所有接口单独放到WebRoot下单独一个文件夹目录下如WebRoot/appreq.改目录下的接口可直接被访问,如:http://local

Hbase权威指南 客户端API基础小结笔记(未完)

客户端API:基础 HBase的主要客户端接口是由org.apache.hadoop.hbase.client包中的HTable类提供的,通过这个类,用户可以完成向HBase存储和检索数据,以及删除无效数据之类的操作. 通常在正常负载下和常规操作下,客户端读操作不会受到其他修改数据的客户端影响,因为它们之间的冲突可以忽略不计.但是,当允许客户端需要同时修改同一行数据时就会产生问题.所以,用户应当尽量使用批量处理(batch)更新来减少单独操作同一行数据的次数. (如果是实时系统,则需要加上syn