IOS -- XMPPFramework 即时聊天(3:XMPPFramework 实现连接服务器)

1.首先我来认识这些对象名词的含义。

  • XMPPStream:xmpp基础服务类

  • XMPPRoster:好友列表类

  • XMPPRosterCoreDataStorage:好友列表(用户账号)在core data中的操作类

  • XMPPvCardCoreDataStorage:好友名片(昵称,签名,性别,年龄等信息)在core data中的操作类

  • XMPPvCardTemp:好友名片实体类,从数据库里取出来的都是它

  • xmppvCardAvatarModule:好友头像

  • XMPPReconnect:如果失去连接,自动重连

  • XMPPRoom:提供多用户聊天支持

  • XMPPPubSub:发布订阅

2.开始实现 (在XMPPService.m中)

static XMPPService *sharedService;
+ (XMPPService *)sharedInstance{
    
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        sharedService = [[XMPPService alloc]init];
        
        [sharedService setupStream];
    });
    return sharedService;
}

上面是实现一个XMPPService单例,下面是 [sharedService setupStream] 的方法实现

- (void)setupStream{
    xmppStream = [[XMPPStream alloc]init];
    [xmppStream addDelegate:self delegateQueue:dispatch_get_main_queue()];
    
    xmppReconnect = [[XMPPReconnect alloc] init];
    [xmppReconnect activate:xmppStream];
    
    xmppRosterStorage = [[XMPPRosterCoreDataStorage alloc] init];
    xmppRoster = [[XMPPRoster alloc] initWithRosterStorage:xmppRosterStorage];
    [xmppRoster activate:xmppStream];
    [xmppRoster addDelegate:self delegateQueue:dispatch_get_main_queue()];
    
    [xmppStream setHostName:kXMPPHost];
    [xmppStream setHostPort:5222];
    
    if (![self connect]) {
        //做连接失败的提示
    };
}

a.新建一个XMPPStream对象 并添加delegate方法  [xmppStream addDelegate:self delegateQueue:dispatch_get_main_queue()];

其中参数delegateQueue 为委托回调所使用的 GCD 队列,dispatch_get_main_queue() 获取主线程 GCD 队列

b.创建XMPPReconnect对象 它实现聊天时断线的重连机制。

c.创建XMPPRoster对象 它为花名册,其实就是好友列表,并添加它的存储策略。

d.设置hostname 和 hostport 其中 kXMPPHost 的形式类似“121.40.xxx.xxx”  hostport端口号是可选的,默认是 5222

e.下面是[self connect]的实现

- (BOOL)connect{
    if (![xmppStream isDisconnected]) {
        return YES;
    }
    
    NSString *myJID = [[NSUserDefaults standardUserDefaults] stringForKey:kXMPPmyJID];
    NSString *myPassword = [[NSUserDefaults standardUserDefaults] stringForKey:kXMPPmyPassword];

    if (myJID == nil || myPassword == nil) {
        return NO;
    }
    
    [xmppStream setMyJID:[XMPPJID jidWithUser:myJID domain:@"openfire" resource:@"ios"]];
    password=myPassword;
    
    NSError *error ;
    if (![xmppStream connectWithTimeout:XMPPStreamTimeoutNone error:&error]) {
        NSLog(@"my connected error : %@",error.description);
        return NO;
    }
    
    return YES;
}

a. [xmppStream setMyJID:[XMPPJID jidWithUser:myJID domain:@"openfire" resource:@"ios"]]这里setMyJID是由三部分组成的 :用户名,域名和资源名。列如  test1@openfire/ios

b.[xmppStream connectWithTimeout:XMPPStreamTimeoutNone error:&error]  使用该方法来进行与服务器连接。

c.一旦连接成功就会走下面xmppstream的代理方法。

#pragma mark - XMPPStreamDelegate
//连接
- (void)xmppStreamWillConnect:(XMPPStream *)sender
{
    NSLog(@"xmppStreamWillConnect");
}
- (void)xmppStreamDidConnect:(XMPPStream *)sender
{
    NSLog(@"开始连接服务器的时候:xmppStreamDidConnect");
    self.isXmppConnected = YES;
    if ([[NSUserDefaults standardUserDefaults]objectForKey:kXMPPmyPassword]) {
        NSError *error ;
        if (![xmppStream authenticateWithPassword:password error:&error]) {
            NSLog(@"error authenticate : %@",error.description);
        }
    }
}


d.一旦连接成功后就会走 xmppStreamDidContent方法,我们在这个方法里进行用户验证。

[xmppStream authenticateWithPassword:password error:&error]这个关键代码 用来进行用户密码验证的。

self.isXmppConnected = YES;是我用来判断是否与服务器连接的变量 你们可以忽略他。

e.在如果验证成功的话 会调用[self goOnlie].如果没成功的话会走 didNotAuthenticate

//验证
- (void)xmppStreamDidAuthenticate:(XMPPStream *)sender
{
    NSLog(@"验证成功:xmppStreamDidAuthenticate");
    [self goOnline];
}
- (void)xmppStream:(XMPPStream *)sender didNotAuthenticate:(NSXMLElement *)error
{
    NSLog(@"验证失败:didNotAuthenticate:%@",error.description);
}

- (NSString *)xmppStream:(XMPPStream *)sender alternativeResourceForConflictingResource:(NSString *)conflictingResource
{
    NSLog(@"alternativeResourceForConflictingResource: %@",conflictingResource);
    return @"XMPPIOS";
}

- (BOOL)xmppStream:(XMPPStream *)sender didReceiveIQ:(XMPPIQ *)iq
{
    NSLog(@"didReceiveIQ: %@",iq.description);
    return YES;
}

在当前用户已经与后台openfire连接,但是状态是未登录状态,所以此时,当前用户发送状态告知后台,这样其他的用户才能收到当前用户的上线通知。

- (void)goOnline
{
    XMPPPresence *presence = [XMPPPresence presence];
    [xmppStream sendElement:presence];
}

f.当你成功上线后 你就会收到一堆在线用户的消息 然后代理方法疯狂的调用着 微笑 微笑

/接受到好友状态更新
//接收添加好友信息 available 上线 away 离开 do not disturb 忙碌 unavailable 下线
- (void)xmppStream:(XMPPStream *)sender didReceivePresence:(XMPPPresence *)presence
{
    NSLog(@"好友状态更新:didReceivePresence: %@",presence.description);
}
- (void)xmppStream:(XMPPStream *)sender didReceiveError:(NSXMLElement *)error
{
    NSLog(@"didReceiveError: %@",error.description);
}
- (void)xmppStream:(XMPPStream *)sender didSendIQ:(XMPPIQ *)iq
{
    NSLog(@"didSendIQ:%@",iq.description);
}
- (void)xmppStream:(XMPPStream *)sender didSendPresence:(XMPPPresence *)presence
{
    NSLog(@"didSendPresence:%@",presence.description);
}
- (void)xmppStream:(XMPPStream *)sender didFailToSendIQ:(XMPPIQ *)iq error:(NSError *)error
{
    NSLog(@"didFailToSendIQ:%@",error.description);
}
- (void)xmppStream:(XMPPStream *)sender didFailToSendMessage:(XMPPMessage *)message error:(NSError *)error
{
    NSLog(@"didFailToSendMessage:%@",error.description);
    NSLog(@"发送失败,麻烦检查下网络");
}
- (void)xmppStream:(XMPPStream *)sender didFailToSendPresence:(XMPPPresence *)presence error:(NSError *)error
{
    NSLog(@"didFailToSendPresence:%@",error.description);
}
- (void)xmppStreamWasToldToDisconnect:(XMPPStream *)sender
{
    NSLog(@"xmppStreamWasToldToDisconnect");
}
- (void)xmppStreamConnectDidTimeout:(XMPPStream *)sender
{
    NSLog(@"xmppStreamConnectDidTimeout");
}
- (void)xmppStreamDidDisconnect:(XMPPStream *)sender withError:(NSError *)error
{
    NSLog(@"连接断开的时候:xmppStreamDidDisconnect: %@",error.description);
    self.isXmppConnected = NO;
}

上面都是xmppstream的代理方法。好比最后一个DidDisconnect方法 就是在你与服务器断开连接时调用的。(有可能是你正常离线 也可能是你意外掉线)。


Over。


©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页