• 给我一个及时的问候——XMPP


     

    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 = 5222;
      // 设置代理在主线程里面
            [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 - 1 inSection:0]] 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 0:
                
        // 拒绝来自fromJID的加入
                [self.XMPPRoSter rejectPresenceSubscriptionRequestFrom:self.fromJID];
                break;
                
        // 接受来自fromJID的数据
            case 1:
                [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 - 1 inSection:0] 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 - 1 inSection:0] atScrollPosition:UITableViewScrollPositionBottom animated:YES];
    }

    这样我们的消息类也处理完成了,运行程序可以看到:

     

    首先是保证我们的服务器都已经开启:

    接着注册

     

    然后点击注册:

    接着登陆

    此时点击登陆后我们跳转到的是好友列表界面因为没有添加好友所以目前是空的

     

    我们打开Spark登陆我们之前在服务器中注册的一个账号

    添加windsSunShine为好友:

    此时我们的模拟器会收到邀请信息:

    选择加入就成功添加好友,然后点击聊天就可以把你的问候传递给你的朋友啦~~~

    具体的代码可以上我的GitHub上下载欢迎点星:

     欢迎转载,请注明转载和原文出处:http://www.cnblogs.com/windsSunShine/p/4986234.html

  • 相关阅读:
    大胆决定+细致用功, 才可能改变命运
    采用用同步编程的方式实现跨进程异步获取数据
    关于DataGridViewComboBoxCell修改后提交数据源
    学习:如何具有坚韧的性格
    汉语-成语:坚韧不拔
    汉语-词语:坚韧
    阿里云-OSS-Help-SKD参考-.NET:前言
    阿里云-OSS-OSS管理控制台:Bucket列表
    阿里云-OSS-OSS管理控制台:概览
    汉语-词语:推理
  • 原文地址:https://www.cnblogs.com/windsSunShine/p/4986234.html
Copyright © 2020-2023  润新知