码迷,mamicode.com
首页 > 移动开发 > 详细

iOS进阶学习-即时通讯(1)

时间:2016-05-19 10:45:00      阅读:416      评论:0      收藏:0      [点我收藏+]

标签:

一、即时通讯

  1、简介

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

  2、实现方式

  即时通讯有多种实现方式,例如:XMPP、环信、融云等。
下面我们对XMPP的使用进行介绍。

  3、什么是XMPP

  XMPP(XML,Messages,Presence,Protocol)是基于可扩展标记语言(XML)的协议,可用于即时通信(IM)。
——可扩展消息处理现场协议。

  4、XMPP优点

  • 开放:
  • XMPP协议是由JSF开源社区组织开发的,不属于任何的机构和个人,从根本上保证了其开放性。
  • 标准:
  • 互联网工程工作组将XMPP于2002年正式列为认可的实时通讯及Presence技术。
  • 分布式的网络架构:
  • XMPP 协议虽然是基于Client/Server 架构,但是XMPP协议本身并没有这样的限制。网络的架构和电子邮件十分相似,但没有结合任何特定的网络架构,适用范围非常广泛。
  • XMPP 协议具有良好的扩展性:
  • 基于XML 建立起来的应用具有良好的语义完整性和扩展性。
  • XMPP 具有很好的弹性:
  • XMPP 除了可用在即时通信的应用程序,还能用在网络管理、内容供稿、协同工具、档案共享、游戏、远端系统监控等。
  • 安全性:
  • XMPP在Client-to-Server通信和Server-to-Server通信中都使用TLS (Transport Layer Security)协议作为通信通道的加密方法,保证通信的安全。

二、XMPP实现即时通讯

  首先搭建XMPP环境具体操作请参考我的另一篇博客XMPP环境搭建。

四、工程中添加XMPP

   1、创建新工程
  2、导入XMPP框架,XMPPFramework:github下载地址
  3、引入XMPP需要的依赖库 libxml   libresolv
  4、设置路径 /usr/include/libxml2

  技术分享

五、登录、注册

   首先用storyboard搭建框架:

技术分享

  具体代码实现:

  LoginViewController.m

@interface LoginViewController ()
/// 用户名
@property (weak, nonatomic) IBOutlet UITextField *userNameTextField;
/// 密码
@property (weak, nonatomic) IBOutlet UITextField *passwordTextField;

@end

@implementation LoginViewController

- (void)viewDidLoad {
    [super viewDidLoad];

}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    
}
#pragma mark - 登录按钮的响应方法
- (IBAction)loginAction:(id)sender {
    [[XMPPManager sharedXMPPManager] loginWithUserName:self.userNameTextField.text password:self.passwordTextField.text];
}


@end

  RegisterViewController.m

@interface RegistViewController ()<XMPPStreamDelegate>

/// 注册用户名
@property (weak, nonatomic) IBOutlet UITextField *userNameTextField;
/// 注册密码
@property (weak, nonatomic) IBOutlet UITextField *passwordTextField;

@end

@implementation RegistViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    [[XMPPManager sharedXMPPManager].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 sharedXMPPManager] registerWithUserName:self.userNameTextField.text password:self.passwordTextField.text];
}

#pragma mark - 实现XMPPStreamDelegate协议方法
// 实现协议是为了满足需求:注册成功之后跳转(dismiss)回页面
- (void)xmppStreamDidRegister:(XMPPStream *)sender
{
    NSLog(@"注册成功");
    [self dismissViewControllerAnimated:YES completion:nil];
}
- (void)xmppStream:(XMPPStream *)sender didNotRegister:(DDXMLElement *)error
{
    NSLog(@"注册失败:error = %@", error);
}

@end

  XMPPManager.h

@interface XMPPManager : NSObject

/// 声明一个通道的属性
@property (nonatomic, strong) XMPPStream *xmppStream;

+ (XMPPManager *)sharedXMPPManager;

// 登录的方法
- (void)loginWithUserName:(NSString *)userName
                 password:(NSString *)password;

// 注册的方法
- (void)registerWithUserName:(NSString *)userName
                    password:(NSString *)password;

@end

  XMPPManager.m

 

#import "XMPPManager.h"


static XMPPManager *manager = nil;

// 记录状态
typedef NS_ENUM(NSUInteger, ConnectToServerPurpose) {
    ConnectToServerPurposeLogin,
    ConnectToServerPurposeRegister,
};

@interface XMPPManager ()<XMPPStreamDelegate>
/// 记录当前状态(登录/注册)
@property (nonatomic) ConnectToServerPurpose connectToServer;
/// 用户名
@property (nonatomic, strong) NSString *userName;
/// 密码
@property (nonatomic, strong) NSString *password;
/// 注册的用户名
@property (nonatomic, strong) NSString *registerUserName;
/// 注册的密码
@property (nonatomic, strong) NSString *registerPassword;


@end

@implementation XMPPManager

+ (XMPPManager *)sharedXMPPManager
{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        manager = [[XMPPManager alloc] init];
        
    });
    return manager;
}

#pragma mark - 1.创建通道
- (instancetype)init
{
    self = [super init];
    if (self) {
        // 初始化通道
        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()];
        
    }
    return self;
}

#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.registerUserName = userName;
    self.registerPassword = password;
    // 记录注册状态
    self.connectToServer = ConnectToServerPurposeRegister;
    // 连接服务器
    [self linkServer];
    
    
}
#pragma mark - 连接服务器
- (void)linkServer
{
    NSString *string = [[NSString alloc] init];
    switch (self.connectToServer) {
        case ConnectToServerPurposeLogin:
            string = [NSString stringWithFormat:@"%@", self.userName];
            break;
        case ConnectToServerPurposeRegister:
            string = [NSString stringWithFormat:@"%@", self.registerUserName];
            break;
        default:
            break;
    }
    // 要连接服务器,要有用户身份认证
    // 身份证
    // 第一个参数:用户名
    // 第二个参数:域名
    // 第三个参数:资源
    XMPPJID *jid = [XMPPJID jidWithUser:string domain:kDomin resource:kResource];
    // 通过通道进行身份验证
    self.xmppStream.myJID = jid;
    
    // 如果当前聊天工具处于连接状态或者已经连接,此时,需要切断连接(此逻辑不唯一,根据需求而定)
    if ([self.xmppStream isConnected] || [self.xmppStream isConnecting]) {
        // 切断连接
        [self disConnectedToServer];
    }
    // 设置连接超时
    NSError *error = nil;
    [self.xmppStream connectWithTimeout:30 error:&error];
    if (error) {
        NSLog(@"服务器连接超时");
    }
}
#pragma mark - 断开连接
- (void)disConnectedToServer
{
    // 当前用户下线了
    XMPPPresence *presence = [XMPPPresence presenceWithType:@"unavailable"];
    // 告诉通道下线了
    [self.xmppStream sendElement:presence];
    // 使通道失去连接
    [self.xmppStream disconnect];
   
}

#pragma mark - XMPPStreamDelegate协议方法
// 连接超时
- (void)xmppStreamConnectDidTimeout:(XMPPStream *)sender
{
    NSLog(@"连接超时");
}

// 连接成功
- (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.registerPassword error:nil];
            break;
        default:
            break;
    }

}
// 断开连接
- (void)xmppStreamDidDisconnect:(XMPPStream *)sender withError:(NSError *)error
{
    // 自己手动断开
    // 被动断开
    if (error) {
        NSLog(@"断开连接,erroe = @%@", error);
    }
}
// 认证失败
- (void)xmppStream:(XMPPStream *)sender didNotAuthenticate:(DDXMLElement *)error
{
    NSLog(@"认证失败:error = %@", error);
}
// 认证成功
- (void)xmppStreamDidAuthenticate:(XMPPStream *)sender
{
    // 上线
    XMPPPresence *presence = [XMPPPresence presenceWithType:@"available"];
    [self.xmppStream sendElement:presence];
    NSLog(@"认证成功");
    
}

 

  未完待续...

 

iOS进阶学习-即时通讯(1)

标签:

原文地址:http://www.cnblogs.com/soley/p/5503978.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!