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的更多相关文章

  1. XMPP iOS客户端实现三:登录、注册

    1.创建一个单例模式来管理xmpp的连接和操作 +(XMPPManager *)share { static XMPPManager *_share=nil; static dispatch_once ...

  2. SIP vs XMPP

    sip和xmpp都是应用层的协议,主要用来在互联网上发送语音和即时通讯IM,rfc3521定义了sip,rfc3920定义了xmpp.xmpp来自即时通讯系统,sip类似语音和视频通信. xmpp协议 ...

  3. TCP/IP,Http,Socket,XMPP的区别

    大学学习网络基础的时候老师讲过,网络由下往上分为物理层.数据链路层.网络层.传输层.会话层.表示层和应用层.通过初步的了解,我知道IP协议对应于网络层,TCP协议对应于传输层,而HTTP协议对应于应用 ...

  4. 基于XMPP协议的手机多方多端即时通讯方案

    一.开发背景 1.国际背景 随着Internet技术的高速发展,即时通信已经成为一种广泛使用的通信方式.1996年Mirabilis公司推出了世界上第一个即时通信系统ICQ,不到10年间,即时通信(I ...

  5. 基于XMPP的即时通信系统的建立(二)— XMPP详解

    XMPP详解 XMPP(eXtensible Messaging and Presence Protocol,可扩展消息处理和现场协议)是一种在两个地点间传递小型结构化数据的协议.在此基础上,XMPP ...

  6. 转:XMPP协议、MQTT协议、HTTP协议、CoAP协议的基本比较

    一.先看下相关国外的专业数据对四大协议的比较: Protocol                                    CoAP                         XMP ...

  7. iOS开发——网络编程OC篇&(一)XMPP简单介绍与准备

    XMPP简单介绍与准备 一.即时通讯简单介绍 1.简单说明 即时通讯技术(IM)支持用户在线实时交谈.如果要发送一条信息,用户需要打开一个小窗口,以便让用户及其朋友在其中输入信息并让交谈双方都看到交谈 ...

  8. XMPP协议的基本理解

    即时通讯技术简介 即时通讯技术(IM)支持用户在线实时交谈.如果要发送一条信息,用户需要打开一个小窗口,以便让用户及其朋友在其中输入信息并让交谈双方都看到交谈的内容.大多数常用的即时通讯发送程序都会提 ...

  9. 即时通讯协议之XMPP

    目前IM即时通信有四种协议 1.即时信息和空间协议(IMPP) 2.空间和即时信息协议(PRIM) 3.针对即时通讯和空间平衡扩充的进程开始协议SIP 4.XMPP协议: 该协议的前身是Jabber, ...

随机推荐

  1. truncate/drop表非常慢,怎么办?用硬链接,极速体验

    这个这个,我必须花巨大篇幅,记录下今天清空表记录的英雄壮举,可知道一个drop操作,执行了一下午啊一下午,这是要急出翔的节奏..呵呵,下面开始 我的需求:某表因历史原因,积压了1亿条记录,约占360G ...

  2. c和c++关于const的一些区别

    以下参考了网上的一些资料并通过程序验证. 注意,以下情况都是用gcc和g++编译器得到的结果,用vs编译器又会有所不同. 以下说下c和c++中const定义的常量的一些区别: c++中用const定义 ...

  3. php 图片添加文字水印 以及 图片合成(微信快码传播)

    1.图片添加文字水印: $bigImgPath = 'backgroud.png'; $img = imagecreatefromstring(file_get_contents($bigImgPat ...

  4. ruby self.included用法

    ===Module#included 当一个模块混入到类时,如果该模块的included方法已经定义,那么该方法被调用.该方法的唯一参数就是接受混含的类的名字. module M def self.i ...

  5. 通过IIS不能连接远程数据库的问题

    近期遇到一个奇怪的问题:在调试MES程序时发现,如果连接的是远程的SQL SERVER数据库(通过了IIS),则提示连接失败,就是经常见到的数据库不允许远程连接的错误提示: 而且又测试了以下几种情况: ...

  6. java模仿qq好友面板的布局(BoxLayout问题)

    .............. JLabel ll = new JLabel(dlg.getNameText() + ":" + dlg.getIPText(), ii[index] ...

  7. php分享三十三:常量

    一:常量定义 1:在脚本执行期间该值不能改变(除了所谓的魔术常量,它们其实不是常量) 2:常量默认为大小写敏感 3:命名规则:用正则表达式是这样表达的:[a-zA-Z_\x7f-\xff][a-zA- ...

  8. [IR] Evaluation

    无序检索结果的评价方法: Precision
 P
 =
tp/(tp
+
fp)
Recall

 



R
     =
tp/(tp
+
fn)
 Accuracy   = (tp + tn) ...

  9. 《你不知道的javascript》一、函数作用域和块作用域

    函数中的作用域 所谓函数作用域,就是属于这个函数的全部变量都可以在整个函数的范围内使用及复用. function foo(a) { var b=a; function bar(c){ var c=b* ...

  10. 关于SQL SERVER高并发解决方案

    现在大家都比较关心的问题就是在多用户高并发的情况下,如何开发系统,这对我们程序员来说,确实是值得研究,最近找工作面试时也经常被问到,其实我早有去关心和了解这类问题,但一直没有总结一下,导致面试时无法很 ...