1.建立一个新工程html
2.导入XMPP框架git
最新的XMPP框架下载地址:https://github.com/robbiehanson/XMPPFrameworkgithub
将XMPP的几个文件夹拖进工程中,须要的文件以下:服务器
而后把Sample_XMPPFramework.h更名为XMPPFramework.h框架
接下来导入两个依赖库:libresolv.dylib和libxml2.dylib,而后添加header search:dom
再添加一个pch文件socket
在pch文件中添加以下代码:工具
#ifdef __OBJC__ #import <UIKit/UIKit.h> #import "XMPPFramework.h" #endif再而后设置工程的pch文件
$SRCROOT后面是项目名/pch文件名。post
作完以上步骤,项目就能够编译成功啦!atom
如今开始搭建项目的登陆界面:
首先封装一个XMPP工具类:JKXMPPTool
.h文件
#import <Foundation/Foundation.h> @interface JKXMPPTool : NSObject<XMPPStreamDelegate> @property (nonatomic, strong) XMPPStream *xmppStream; // 模块 @property (nonatomic, strong) XMPPAutoPing *xmppAutoPing; @property (nonatomic, strong) XMPPReconnect *xmppReconnect; @property (nonatomic, assign) BOOL xmppNeedRegister; @property (nonatomic, copy) NSString *myPassword; + (instancetype)sharedInstance; - (void)loginWithJID:(XMPPJID *)JID andPassword:(NSString *)password; - (void)registerWithJID:(XMPPJID *)JID andPassword:(NSString *)password; @end.m文件
#import "JKXMPPTool.h" @implementation JKXMPPTool static JKXMPPTool *_instance; + (instancetype)sharedInstance { static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ _instance = [JKXMPPTool new]; }); return _instance; } - (XMPPStream *)xmppStream { if (!_xmppStream) { _xmppStream = [[XMPPStream alloc] init]; //socket 链接的时候 要知道host port 而后connect [self.xmppStream setHostName:kXMPP_HOST]; [self.xmppStream setHostPort:kXMPP_PORT]; //为何是addDelegate? 由于xmppFramework 大量使用了多播代理multicast-delegate ,代理通常是1对1的,可是这个多播代理是一对多得,并且能够在任意时候添加或者删除 [self.xmppStream addDelegate:self delegateQueue:dispatch_get_main_queue()]; } return _xmppStream; } - (void)loginWithJID:(XMPPJID *)JID andPassword:(NSString *)password { // 1.创建TCP链接 // 2.把我本身的jid与这个TCP链接绑定起来(即便匿名登陆,依然得设置JID,只是咱们能够设置一个任意的JID,例如<span style="font-family: Arial, Helvetica, sans-serif;">anonymous@<domain></span>) // 3.认证(登陆:验证jid与密码是否正确,加密方式 不可能以明文发送)--(出席:怎样告诉服务器我上线,以及我得上线状态 //这句话会在xmppStream之后发送XML的时候加上 <message from="JID"> [self.xmppStream setMyJID:JID]; self.myPassword = password; self.xmppNeedRegister = NO; [self.xmppStream connectWithTimeout:XMPPStreamTimeoutNone error:nil]; } //注册方法里没有调用auth方法 - (void)registerWithJID:(XMPPJID *)JID andPassword:(NSString *)password { [self.xmppStream setMyJID:JID]; self.myPassword = password; self.xmppNeedRegister = YES; [self.xmppStream connectWithTimeout:XMPPStreamTimeoutNone error:nil]; } - (void)goOnline { // 发送一个<presence/> 默认值avaliable 在线 是指服务器收到空的presence 会认为是这个 XMPPPresence *presence = [XMPPPresence presence]; //发送复杂一点的出席状态 //<presence type="avaliable"> // <status>我很忙</status> // <show>xa</show> // </presence> [presence addChild:[DDXMLNode elementWithName:@"status" stringValue:@"我如今很忙"]]; [presence addChild:[DDXMLNode elementWithName:@"show" stringValue:@"xa"]]; [self.xmppStream sendElement:presence]; } #pragma mark ===== XMPPStream delegate ======= //socket 链接创建成功 - (void)xmppStream:(XMPPStream *)sender socketDidConnect:(GCDAsyncSocket *)socket { NSLog(@"%s",__func__); } //这个是xml流初始化成功 - (void)xmppStreamDidConnect:(XMPPStream *)sender { NSLog(@"%s",__func__); //匿名登陆 会随机生成一个username和JID,这个是在服务器的内存中随机生成,不会写入服务器的数据表,例如生成的jid为<p class="p1"><span class="s1">1nv8l4khxg@im.joker.cn/1nv8l4khxg</span></p> //为了防止客户端匿名登陆,服务器有策略关闭匿名 // [self.xmppStream authenticateAnonymously:nil]; if (self.xmppNeedRegister) { [self.xmppStream registerWithPassword:self.myPassword error:nil]; } else { [self.xmppStream authenticateWithPassword:self.myPassword error:nil]; } } - (void)xmppStreamDidDisconnect:(XMPPStream *)sender withError:(NSError *)error { NSLog(@"%s",__func__); } //登陆失败 - (void)xmppStream:(XMPPStream *)sender didNotAuthenticate:(DDXMLElement *)error { NSLog(@"%s",__func__); } //登陆成功 - (void)xmppStreamDidAuthenticate:(XMPPStream *)sender { NSLog(@"%s",__func__); [self goOnline]; [[NSNotificationCenter defaultCenter] postNotificationName:kLOGIN_SUCCESS object:nil]; } @end
而后是登陆功能:
登陆按钮的action以下:
#pragma mark - click event /** 登陆事件 */ - (IBAction)loginClick:(id)sender { NSString *username = _usernameField.text; NSString *password = _passwordField.text; NSString *message = nil; if (username.length <= 0) { message = @"用户名未填写"; } else if (password.length <= 0) { message = @"密码未填写"; } if (message.length > 0) { UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:nil message:message delegate:nil cancelButtonTitle:@"我知道了" otherButtonTitles:nil]; [alertView show]; } else { [[JKXMPPTool sharedInstance] loginWithJID:[XMPPJID jidWithUser:username domain:@"im.joker.cn" resource:@"iOS"] andPassword:password]; } }用通知返回登陆成功的消息
- (void)loginSuccess { NSLog(@"loginSuccess"); [self performSegueWithIdentifier:@"loginSegue" sender:self]; }
再而后实现注册的功能:
- (IBAction)registAction:(id)sender { NSString *username = _usernameField.text; NSString *password = _passwordField.text; NSString *confirm = _confirmField.text; NSString *message = nil; if (username.length <= 0) { message = @"用户名未填写"; } else if (password.length <= 0) { message = @"密码未填写"; } else if (confirm.length <= 0) { message = @"确认密码未填写"; } if (message.length > 0) { UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:nil message:message delegate:nil cancelButtonTitle:@"我知道了" otherButtonTitles:nil]; [alertView show]; } else if (![password isEqualToString:confirm]) { message = @"密码与确认密码不一致"; UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:nil message:message delegate:nil cancelButtonTitle:@"我知道了" otherButtonTitles:nil]; [alertView show]; } else { [[JKXMPPTool sharedInstance] registerWithJID:[XMPPJID jidWithUser:username domain:@"im.joker.cn" resource:@"iOS"] andPassword:password]; } }由于注册时,不须要进行认证,注册会直接返回BOOL结果,因此改进链接代理方法:
//这个是xml流初始化成功 - (void)xmppStreamDidConnect:(XMPPStream *)sender { NSLog(@"%s",__func__); if (self.xmppNeedRegister) { BOOL result = [self.xmppStream registerWithPassword:self.myPassword error:nil]; NSNumber *number = [NSNumber numberWithBool:result]; [[NSNotificationCenter defaultCenter] postNotificationName:kREGIST_RESULT object:number]; } else { [self.xmppStream authenticateWithPassword:self.myPassword error:nil]; } }
下载地址:点击下载