给我一个及时的问候——XMPP
XMPP总的来说就是:基于XML数据结构,点对点的,及时通讯协议
是 Linux操作系统+Apache软件+mySql数据库 + php 编程语言 组成
开始时要导入 XMPPFrameWork框架:【附带框架如下】
具体的框架下载地址:http://pan.baidu.com/s/1hqoB4pQ
如果要搭建XMPP开发环境 可以从下面获取一些必要的安装软件:
我把需要安装的软件都已经整理好了,下次给大家分享一下如何搭建的问题:
安装好环境接下来就进入最有意思的环节写代码:
首先将值之前下载的框架引入我们的文件中:
引入完框架接下来县创建一个XMPPManager的类用来放置通道管理器:XMPPStream
,用户类:XMPPRoster和XMPP的CoreData储存的类:并创建登陆和注册方法获取用户名和密码:
具体代码如下:
// 1、通道管理器类 在服务器之间创建通道
@property(nonatomic,strong)XMPPStream * XMPPStream; // 好友关系(好友花名册,添加好友信息)2、 用户类
@property(nonatomic,strong)XMPPRoster * XMPPRoSter; // 这两个属性是聊天记录用到的
// XMPP的CoreData存储的类 @property(nonatomic,strong)XMPPMessageArchiving * achivimg; @property(nonatomic,strong)NSManagedObjectContext * context; // 创建单例 放进不会重复初始化的东西 +(instancetype)defaultManager; // 登陆 -(void)loginWithUserName:(NSString *)userName andPassWorld:(NSString *)password; // 注册 -(void)registerWithUserName:(NSString *)userName andPassword:(NSString *)password;
在XMPPManager的.m文件中还需要使用一个XMPPJID的类来记录用户的一些信息,主要的工作是对通道管理器类进行初始化,设置自己的服务器名,设置端口号遵循
XMPPStreamDelegate,XMPPRosterDelegate这两个代理。初始化方法如下:
-(id)init{ self = [super init];
if (self) {
// 初始化自己的通道管理器类 self.XMPPStream =[[XMPPStream alloc]init]; // 服务器的名字,(在openfire后台管理里面看) self.XMPPStream.hostName = @"127.0.0.1"; // 设置端口号, 默认是5222
self.XMPPStream.hostPort = ;
// 设置代理在主线程里面
[self.XMPPStream addDelegate:self delegateQueue:(dispatch_get_main_queue())];
XMPPRosterCoreDataStorage * coreDataStorage =[XMPPRosterCoreDataStorage sharedInstance]; // 初始化用户管理
self.XMPPRoSter = [[XMPPRoster alloc]initWithRosterStorage:coreDataStorage dispatchQueue:(dispatch_get_main_queue())];
// 在主线程中添加代理方法
[self.XMPPRoSter addDelegate:self delegateQueue:(dispatch_get_main_queue())];
// 将用户类放进通道管理器类里面
[self.XMPPRoSter activate:self.XMPPStream];
XMPPMessageArchivingCoreDataStorage * coreData = [XMPPMessageArchivingCoreDataStorage sharedInstance];
self.achivimg =[[XMPPMessageArchiving alloc]initWithMessageArchivingStorage:coreData dispatchQueue:(dispatch_get_main_queue())];
// 将消息类放进管理器通道类里面
[self.achivimg activate:self.XMPPStream]; self.context = coreData.mainThreadManagedObjectContext; }
return self;
}
接着实现代理方法:
通道管理器类作为一个信息传输的通道,需要每次进行连接,在连接的同时我们可以通过JID获取用户的信息实现具体的连接类用来获取用户数:
-(void)connectionWithUserName:(NSString *)userName andPassWord:(NSString *)passwod { // 在发生登录注册的时候,需要让我的通道类连接断掉,防止出现连接混乱的情况 if ([self.XMPPStream isConnected]) { // 仅允许一个终端在线登录(不允许重复登录)
[self.XMPPStream disconnect];
} self.password = passwod; // 3、XMPPJId 保存的是一些用户的信息
// 这个类当这个通道和服务器连接,保存的是一些用户的信息
// 可以知道是给别人发消息,还是别人发来的消息 XMPPJID * jid =[XMPPJID jidWithUser:userName domain:@"127.0.0.1" resource:@"iOS"]; // 可以知道是发送消息还是接收消息 // 在jid保存到XMPPStream里面
self.XMPPStream.myJID = jid; // 让通道管理器类建立连接 [self.XMPPStream connectWithTimeout:1.0f error:nil]; }
除此之外要使用代理中的方法,判断连接的状态,这也是使用管理器连接成功的关键:
代理方法如下:
// 当连接成功
-(void)xmppStreamDidConnect:(XMPPStream *)sender
{
switch (self.myConnectMode) {
case connectIsLogin:
[self.XMPPStream authenticateWithPassword:self.password error:nil]; break;
case connectIsRefister:
[self.XMPPStream registerWithPassword:self.password error:nil];
break; default:
break;
} }
// 连接失败 -(void)xmppStreamDidDisconnect:(XMPPStream *)sender withError:(NSError *)error
{ }
// 将要失去连接 -(void)xmppStreamWillConnect:(XMPPStream *)sender
{ }
这样基本上我们就把我们的XMPPManager类给写好了接下来就是登录和注册页面:
可以简单的使用storyboard将登录和注册页面拖拽出来:
使用storyboard时应该有三点需要注意的尤其对于新手来讲:首先如果存在代理,遵循代理(比如tableView),接着要记得绑定相应的页面,最后记得设置storyboard Id
在登录和注册页面中都要遵循 <XMPPStreamDelegate>代理:并将其放进主线程中
在注册页面中主要实现的方法有:
登录成功执行的方法主要是为了想服务器发送上线的消息
// 登录成功执行的方法
-(void)xmppStreamDidAuthenticate:(XMPPStream *)sender
{
// 连接成功后发送消息,发送有效消息,上线消息
XMPPPresence * presence =[XMPPPresence presenceWithType:@"available"]; // 上线的消息通过XMPPStream 发送 [[XMPPManager defaultManager].XMPPStream sendElement:presence];
NSLog(@"登录成功"); AppDelegate * app = [UIApplication sharedApplication].delegate; RootViewController * roster =[[UIStoryboard storyboardWithName:@"Main" bundle:nil]instantiateViewControllerWithIdentifier:@"rootVC"]; app.window.rootViewController = roster; }
当点击登录按钮时需要将用户的用户名和密码发送
- (IBAction)LoginAction:(id)sender {
// 调用XMPPManager里面的登录注册的方法 // 调用XMPP里面的登录注册的方法获取用户名密码
[[XMPPManager defaultManager]loginWithUserName:self.nameTextFild.text andPassWorld:self.passwordTextFild.text]; }
在注册的界面中主要要实现的方法是:
注册成功的方法:
-(void)xmppStreamDidRegister:(XMPPStream *)sender
{ UIAlertView * alertView =[[UIAlertView alloc]initWithTitle:@"提示" message:@"恭喜您注册成功" delegate:self cancelButtonTitle:@"取消" otherButtonTitles:@"确定", nil];
[alertView show]; LoginViewController * longinVC =[[UIStoryboard storyboardWithName:@"Main" bundle:nil]instantiateViewControllerWithIdentifier:@"loginVC"]; [self showViewController:longinVC sender:nil]; }
之后登录注册页面就这样简单的完成了,做好了登录和注册就想发送消息就想把冬天的那句暖暖的问候发送给你,但是我需要知道你的信息才行,接下来我们可以建立用户的好友列表界面:
在好友列表界面中要遵循<XMPPRosterDelegate>用户类的代理方法,主要实现的方法包括:
// 获取好友列表 -(void)xmppRoster:(XMPPRoster *)sender didReceiveRosterItem:(DDXMLElement *)item
{
// 通过获取好友列表这个方法有助于获得各个好友的信息,通过item获取
if ([[[item attributeForName:@"subscription"]stringValue]isEqualToString:@"both"]) {
// 获取item里面节点的数据
NSString * jidStr =[[item attributeForName:@"jid"]stringValue];
// 通过在item里面获取到的数据初始化一个XMPPJID
XMPPJID * jid =[XMPPJID jidWithString:jidStr];
// 把这个jid放到数据源数组里面
[self.dataArray addObject:jid]; // 使界面中的信息能够自动下翻
[self.tableView insertRowsAtIndexPaths:@[[NSIndexPath indexPathForRow:self.dataArray.count - inSection:]] withRowAnimation:UITableViewRowAnimationAutomatic]; }
}
还有两个好友列表的代理方法根据需要来实现:
/ 开始获取好友列表 -(void)xmppRosterDidBeginPopulating:(XMPPRoster *)sender
{
NSLog(@"开始获取");
} // 结束获取好友列表 -(void)xmppRosterDidEndPopulating:(XMPPRoster *)sender
{
NSLog(@"结束获取");
}
有了你的信息我就想加你为好友接下来在XMPPManager里面设置加好友的方法:
// 收到好友的请求的代理方法 -(void)xmppRoster:(XMPPRoster *)sender didReceivePresenceSubscriptionRequest:(XMPPPresence *)presence
{
// 获取来自于好友的请求
self.fromJID = presence.from; // 弹框 UIAlertView * view =[[UIAlertView alloc]initWithTitle:@"收到好友请求" message:@"加我为好友吧~~" delegate:self cancelButtonTitle:@"残忍拒绝" otherButtonTitles:@"乐意加入", nil]; [view show]; }
根据自己的选择实现UIAlertView的代理方法来进行好友的添加:
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
switch (buttonIndex) {
case : // 拒绝来自fromJID的加入
[self.XMPPRoSter rejectPresenceSubscriptionRequestFrom:self.fromJID];
break; // 接受来自fromJID的数据
case :
[self.XMPPRoSter acceptPresenceSubscriptionRequestFrom:self.fromJID andAddToRoster:YES];
break; default:
break;
}
}
有了好友,接下来就是做信息处理了我们在建立一个MessageViewController用来处理信息:
首先在MessageViewController设置一个JID的属性确定和我聊天的是谁
接着在.m文件中需要实现的代理方法有:
首先我们要在CoreData中获取数据:
// 获取发送的信息数据
-(NSArray *)findData
{ NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"XMPPMessageArchiving_Message_CoreDataObject" inManagedObjectContext:[XMPPManager defaultManager].context];
[fetchRequest setEntity:entity];
// Specify criteria for filtering which objects to fetch //bareJidStr 参数代表的是和我聊天的人
//streamBareJidStr 参数代表的是我自己
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"bareJidStr = %@ AND streamBareJidStr = %@", self.toJid.bare, [XMPPManager defaultManager].XMPPStream.myJID.bare];
[fetchRequest setPredicate:predicate];
// Specify how the fetched objects should be sorted
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"timestamp"ascending:YES];
[fetchRequest setSortDescriptors:[NSArray arrayWithObjects:sortDescriptor, nil]]; NSError *error = nil;
NSArray *fetchedObjects = [[XMPPManager defaultManager].context executeFetchRequest:fetchRequest error:&error];
if (fetchedObjects == nil) {
// 查询的数据不存在则返回一个数组 return [NSArray array];
}else{
// 返回查询的数据
return fetchedObjects;
} }
接着就设置接收消息的方法:
// 接收消息时
-(void)xmppStream:(XMPPStream *)sender didReceiveMessage:(XMPPMessage *)message
{
[self.dataArray removeAllObjects];
[self.dataArray setArray:[self findData]]; [self.tableView reloadData]; // 代码自动滚动
[self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForItem:self.dataArray.count - inSection:] atScrollPosition:UITableViewScrollPositionBottom animated:YES]; }
发送消息是的代理方法:
// 发送时遵循的代理 -(void)xmppStream:(XMPPStream *)sender didSendMessage:(XMPPMessage *)message
{
[self.dataArray removeAllObjects]; [self.dataArray setArray:[self findData]]; [self.tableView reloadData];
// 代码自动滚动
[self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForItem:self.dataArray.count - inSection:] atScrollPosition:UITableViewScrollPositionBottom animated:YES];
}
这样我们的消息类也处理完成了,运行程序可以看到:
首先是保证我们的服务器都已经开启:
接着注册
然后点击注册:
接着登陆
此时点击登陆后我们跳转到的是好友列表界面因为没有添加好友所以目前是空的
我们打开Spark登陆我们之前在服务器中注册的一个账号
:
添加windsSunShine为好友:
此时我们的模拟器会收到邀请信息:
选择加入就成功添加好友,然后点击聊天就可以把你的问候传递给你的朋友啦~~~
具体的代码可以上我的GitHub上下载欢迎点星:
欢迎转载,请注明转载和原文出处:http://www.cnblogs.com/windsSunShine/p/4986234.html
给我一个及时的问候——XMPP的更多相关文章
- XMPP iOS客户端实现三:登录、注册
1.创建一个单例模式来管理xmpp的连接和操作 +(XMPPManager *)share { static XMPPManager *_share=nil; static dispatch_once ...
- SIP vs XMPP
sip和xmpp都是应用层的协议,主要用来在互联网上发送语音和即时通讯IM,rfc3521定义了sip,rfc3920定义了xmpp.xmpp来自即时通讯系统,sip类似语音和视频通信. xmpp协议 ...
- TCP/IP,Http,Socket,XMPP的区别
大学学习网络基础的时候老师讲过,网络由下往上分为物理层.数据链路层.网络层.传输层.会话层.表示层和应用层.通过初步的了解,我知道IP协议对应于网络层,TCP协议对应于传输层,而HTTP协议对应于应用 ...
- 基于XMPP协议的手机多方多端即时通讯方案
一.开发背景 1.国际背景 随着Internet技术的高速发展,即时通信已经成为一种广泛使用的通信方式.1996年Mirabilis公司推出了世界上第一个即时通信系统ICQ,不到10年间,即时通信(I ...
- 基于XMPP的即时通信系统的建立(二)— XMPP详解
XMPP详解 XMPP(eXtensible Messaging and Presence Protocol,可扩展消息处理和现场协议)是一种在两个地点间传递小型结构化数据的协议.在此基础上,XMPP ...
- 转:XMPP协议、MQTT协议、HTTP协议、CoAP协议的基本比较
一.先看下相关国外的专业数据对四大协议的比较: Protocol CoAP XMP ...
- iOS开发——网络编程OC篇&(一)XMPP简单介绍与准备
XMPP简单介绍与准备 一.即时通讯简单介绍 1.简单说明 即时通讯技术(IM)支持用户在线实时交谈.如果要发送一条信息,用户需要打开一个小窗口,以便让用户及其朋友在其中输入信息并让交谈双方都看到交谈 ...
- XMPP协议的基本理解
即时通讯技术简介 即时通讯技术(IM)支持用户在线实时交谈.如果要发送一条信息,用户需要打开一个小窗口,以便让用户及其朋友在其中输入信息并让交谈双方都看到交谈的内容.大多数常用的即时通讯发送程序都会提 ...
- 即时通讯协议之XMPP
目前IM即时通信有四种协议 1.即时信息和空间协议(IMPP) 2.空间和即时信息协议(PRIM) 3.针对即时通讯和空间平衡扩充的进程开始协议SIP 4.XMPP协议: 该协议的前身是Jabber, ...
随机推荐
- 为Ubuntu笔记本电脑设置WiFi热点共享上网
该文由土木坛子转译而来,说是转译,其实看截图就可以方便的设置,没有任何命令,全是图形界面,方便容易.我们都知道怎样在 windows 7 系统上如何设计 Wifi 热点,当你只有一条网线,多台计算机的 ...
- hybrid开发设计
hybrid方案背景 大部分业务都是在不停改变的,我们希望native不发布新版本就可以让线上用户使用新功能.我们要实现这样的方式,采用h5来实现就可以满足这一要求,准确说是native里提供一个装载 ...
- 天猫浏览型应用的CDN静态化架构演变
原文链接:http://www.csdn.net/article/2014-01-22/2818227-CDN-Architecture 在天猫双11活动中,商品详情.店铺等浏览型系统,通常会承受超出 ...
- Android事件传递机制
http://blog.csdn.net/awangyunke/article/details/22047987 1)public boolean dispatchTouchEvent(MotionE ...
- mysql中int、bigint、smallint 和 tinyint的区别详细介绍
1 bytes = 8 bit ,一个字节最多可以代表的数据长度是2的8次方 11111111 在计算机中也就是 -128到127 1.BIT[M] 位字段类型,M表示每个值的位数,范围从1到64,如 ...
- 【转载】Serial NOR Flash and U-Boot
转载自:http://blackfin.uclinux.org/doku.php?id=bootloaders:u-boot:serial-flash U-Boot supports serial N ...
- js实现页面a向页面b传参的方法
方法一:使用HTML5本地化存储(localStorage) 组件(本地最大能存储5M数据)localStorage是本地永久存储数据,是cookie的优化 方法二:使用cookie将数据存放在客户的 ...
- SQL Server 2016里TempDb的提升
几个星期前,SQL Server 2016的最新CTP版本已经发布了:CTP 2.4(目前已经是CTP 3.0).这个预览版相比以前的CTP包含了很多不同的提升.在这篇文章里我会谈下对于SQL Ser ...
- Linux永久修改系统时间和时区方法
修改时区: 1> 找到相应的时区文件 /usr/share/zoneinfo/Asia/Shanghai 用这个文件替换当前的/etc/localtime文件. 或者找你认为是标准时间的服务器, ...
- Mysql log_slave_updates 参数
官网说明: Normally, a slave does not log to its own binary log any updates that are received from a mast ...