你的位置:首页 > 操作系统

[操作系统]iOS学习42即时通信之XMPP1


1. 即时通信

 1> 概述

  即时通讯(Instant Messaging)是目前Internet上最为流行的通讯方式,各种各样的即时通讯软件也层出不穷,服务提供商也提供了越来越丰富的通讯服务功能。

  即时通讯有多种实现方式,例如:XMPP、环信、融云等。

 2> XMPP(可扩展消息处理现场协议)

  XMPP(可扩展消息处理现场协议))是基于可扩展标记语言(

 3> XMPP的优点

  • 开放

  XMPP协议是由JSF开源社区组织开发的,不属于任何的机构和个人,从根本上保证了其开放性。

  • 标准

  互联网工程工作组将XMPP于2002年正式列为认可的实时通讯及Presence技术。

  • 分布式的网络架构

  XMPP 协议虽然是基于Client/Server 架构,但是XMPP协议本身并没有这样的限制。网络的架构和电子邮件十分相似,但没有结合任何特定的网络架构,适用范围非常广泛。

  • XMPP 协议具有良好的扩展性

  基于

  • XMPP 具有很好的弹性

  XMPP 除了可用在即时通信的应用程序,还能用在网络管理、内容供稿、协同工具、档案共享、游戏、远端系统监控等。

  • 安全性

  XMPP在Client-to-Server通信和Server-to-Server通信中都使用TLS (Transport Layer Security)协议作为通信通道的加密方法,保证通信的安全。

  XMPP环境的搭建的步骤详见XMPP环境的搭建

2. 工程中添加XMPP

  将XMPP协议第三方文件拖入工程,下载地址:https://github.com/AlonerOwl/XMPPFramework

 2> 初始化XMPP通道

    //初始化通道    self.xmppStream = [[XMPPStream alloc] init];    //openfire服务器IP地址    self.xmppStream.hostName = kHostName;    //openfire服务器端口 默认5222    self.xmppStream.hostPort = kHostPort;    //添加代理    [self.xmppStream addDelegate:self delegateQueue:dispatch_get_main_queue()     ];

 3> 连接服务器代码所需方法

 4> 登录代码所需方法

 5> 注册代码所需方法

 

  XMPPManager.m

#import "XMPPManager.h"static XMPPManager *xmppManager = nil;// 枚举记录状态typedef NS_ENUM(NSUInteger, ConnectToServerPurpose) {  ConnectToServerPurposeLogin,  ConnectToServerPurposeRegister};// 遵循协议@interface XMPPManager () <XMPPStreamDelegate>/// 用户名@property (nonatomic, copy) NSString *username;/// 密码@property (nonatomic, copy) NSString *password;/// 记录当前的状态,判断是登录还是注册@property (nonatomic) ConnectToServerPurpose connectToServer;@end@implementation XMPPManager+ (XMPPManager *)shareXMPPManager{  static dispatch_once_t onceToken;  dispatch_once(&onceToken, ^{    xmppManager = [XMPPManager new];  });  return xmppManager;}#pragma mark - 1.创建通道- (instancetype)init{  self = [super init];  if (self) {    //初始化对象    self.xmppStream = [XMPPStream new];        // 设置服务器    [self settingUpServer];  }  return self;}// 设置服务器- (void)settingUpServer{  // 设置opfire服务器  self.xmppStream.hostName = kHostName;  // 设置服务器端口号  self.xmppStream.hostPort = kHostPort;  // 添加代理  [self.xmppStream addDelegate:self delegateQueue:dispatch_get_main_queue()];}#pragma mark - 登录的方法- (void)loginWithUsername:(NSString *)username         password:(NSString *)password{  self.username = username;  self.password = password;    // 记录登录状态  self.connectToServer = ConnectToServerPurposeLogin;    // 连接服务器  [self linkServer];}#pragma mark - 注册的方法- (void)registerWithUsername:(NSString *)username          password:(NSString *)password{  self.username = username;  self.password = password;  // 记录注册状态  self.connectToServer = ConnectToServerPurposeRegister;    // 连接服务器  [self linkServer];}#pragma mark - 连接服务器- (void)linkServer{  // 要连接服务器,要有用户身份认证  // 身份证  // 参数1:用户名  // 参数2:域名  // 参数3:资源  XMPPJID *jid = [XMPPJID jidWithUser:self.username domain:kDomin resource:kResource];    self.xmppStream.myJID = jid;    // 如果当前聊天工具处于连接状态或已经连接,此时,你需要去切断连接【此逻辑不唯一】  if ([self.xmppStream isConnected] || [self.xmppStream isConnecting]) {    // 断开连接    [self disConnectToServer];  }    // 设置连接超时  NSError *error = nil;  [self.xmppStream connectWithTimeout:30 error:&error];  if (error) {    NSLog(@"连接超时");  }  }#pragma mark - 断开连接(自己写的)- (void)disConnectToServer{  // 当前用户不可用(下线了)  XMPPPresence *presence = [XMPPPresence presenceWithType:@"unavailable"];  // 告诉通道用户不可用(下线了)  [self.xmppStream sendElement:presence];  // 使用通道失去连接  [self.xmppStream disconnect];}#pragma mark - XMPPStreamDelegate协议方法#pragma mark 连接超时- (void)xmppStreamConnectDidTimeout:(XMPPStream *)sender{  NSLog(@"连接超时");}#pragma mark 连接成功- (void)xmppStreamDidConnect:(XMPPStream *)sender{  NSLog(@"连接成功");    // 认证密码//  [self.xmppStream authenticateWithPassword:self.password error:nil];    // 区分登录和注册进行密码验证  switch (self.connectToServer) {    case ConnectToServerPurposeLogin:      // 登录认证      [self.xmppStream authenticateWithPassword:self.password error:nil];      break;          case ConnectToServerPurposeRegister:      // 注册的认证      [self.xmppStream registerWithPassword:self.password error:nil];      break;          default:      break;  }}#pragma mark 断开连接- (void)xmppStreamDidDisconnect:(XMPPStream *)sender withError:(NSError *)error{  // 1. 自己动手断开  // 2. 被动断开  if (error) {    NSLog(@"断开连接,error == %@", error);  }}#pragma mark 认证失败- (void)xmppStream:(XMPPStream *)sender didNotAuthenticate:(DD)error{  NSLog(@"认证失败:error = %@", error);}#pragma mark 认证成功- (void)xmppStreamDidAuthenticate:(XMPPStream *)sender{  // 当前用户可用(上线了)  XMPPPresence *presence = [XMPPPresence presenceWithType:@"available"];  // 告诉通道用户可用(上线了)  [self.xmppStream sendElement:presence];    NSLog(@"认证成功");}@end

  • 登录界面

  LoginViewController.m

#import "LoginViewController.h"#import "XMPPManager.h"@interface LoginViewController ()/// 用户输入框@property (weak, nonatomic) IBOutlet UITextField *usernameTextField;/// 密码输入框@property (weak, nonatomic) IBOutlet UITextField *passwordTextField;@end@implementation LoginViewController- (void)viewDidLoad {  [super viewDidLoad];  // Do any additional setup after loading the view.}- (void)didReceiveMemoryWarning {  [super didReceiveMemoryWarning];  // Dispose of any resources that can be recreated.}- (IBAction)loginAction:(UIButton *)sender{  [[XMPPManager shareXMPPManager] loginWithUsername:self.usernameTextField.text password:self.passwordTextField.text];}@end

  • 注册界面

   RegisterViewController.m

#import "RegisterViewController.h"#import "XMPPManager.h"@interface RegisterViewController () <XMPPStreamDelegate>@property (weak, nonatomic) IBOutlet UITextField *registerUNTextField;@property (weak, nonatomic) IBOutlet UITextField *registerPWTextField;@end@implementation RegisterViewController- (void)viewDidLoad {  [super viewDidLoad];  // Do any additional setup after loading the view.    // 添加代理  [[XMPPManager shareXMPPManager].xmppStream addDelegate:self delegateQueue:dispatch_get_main_queue()];}- (void)didReceiveMemoryWarning {  [super didReceiveMemoryWarning];  // Dispose of any resources that can be recreated.}// 按钮点击事件- (IBAction)registerAction:(id)sender{  [[XMPPManager shareXMPPManager] registerWithUsername:self.registerUNTextField.text password:self.registerPWTextField.text];}#pragma mark - XMPPStreamDelegate实现协议方法// 注册成功后,dismiss到登录界面- (void)xmppStreamDidRegister:(XMPPStream *)sender{  NSLog(@"注册成功");  [self dismissViewControllerAnimated:YES completion:nil];}// 注册失败- (void)xmppStream:(XMPPStream *)sender didNotRegister:(DD)error{  NSLog(@"注册失败:%@", error);}@end