XMPP 基於XML的點對點通訊協議

XMPP 基於XML的點對點通訊協議數組

 

IM: 即時通訊服務器

XMPP: 基於XML的點對點通訊協議app

1. ejabber: 這個軟件是用來開啓本地服務器使用, 本地服務器地址爲: 127.0.0.1, 全部的電腦都同樣, 開啓服務器的軟件有不少框架

2. Audium: 就是一個聊天工具ide

用局域網聊天工具

1.在同一個WIFI佈局

2.在同一個本地服務器建立帳號atom

3.登錄的時候, 設置好服務器地址, 爲電腦的IP地址spa

XAMPP: 集成了阿帕奇 FTPMy SQL的一個軟件3d

類的擴展有三種方式

1.協議: 須要本身制定協議, 設置代理, 遵照協議, 通常用來傳值(回調)

2.延展: 爲類添加私有方法和私有變量, 通常用於已知類(.h.m都存在的類)

3.類目: 爲類添加方法和屬性(只有settergetter, 沒有實例變量), 必須實現內部聲明的方法, 通常用於系統類的擴展

XMPP的安裝

XMPP安裝須要的軟件

    

安裝ejabberd

選擇ejabberd.app進行安裝

 

 

 

用戶名和密碼填寫完要記住,以後會用到

安裝成功後,在Finder->應用程序->ejabberd-14.07->bin->start點擊start.exec運行,會跳出一個網頁

在網頁上能夠添加帳號和密碼

 

將 軟件添加到Finder->應用程序中,點擊打開app,能夠用ejabberd中註冊的帳號和密碼登錄

詳細代碼:

在工程中添加框架和MI類 

storyboard基本佈局: 

ViewController.m #import "ViewController.h"
//引入頭文件
#import "XMPPFramework.h"
#import "XMPPManager.h"
#import "ContactViewController.h"
#define JID(USER_NAME) [NSString stringWithFormat:@"%@@bogon", USER_NAME]
@interface ViewController ()<XMPPStreamDelegate, UIAlertViewDelegate, XMPPRosterDelegate> @property (weak, nonatomic) IBOutlet UITextField *userNameTF; @property (weak, nonatomic) IBOutlet UITextField *passwordTF; //花名冊
@property (nonatomic, strong) XMPPRoster *roster; //花名冊數組
@property (nonatomic, strong) NSMutableArray *rosterArr; - (IBAction)loginClick:(id)sender; //建立XMPPStream類的屬性
@property (nonatomic, strong) XMPPStream *stream; @end

@implementation ViewController //點擊頁面代理方法
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { //結束編輯狀態
 [self.view endEditing:YES]; } //重寫XMPPStream的getter方法
- (XMPPStream *)stream { if (_stream == nil) { self.stream = [[XMPPStream alloc] init]; _stream.hostName = @"127.0.0.1"; _stream.hostPort = 5222; [_stream addDelegate:self delegateQueue:dispatch_get_main_queue()]; //激活花名冊
 [self.roster activate:_stream]; } return _stream; } //重寫XMPPRoster花名冊方法
- (XMPPRoster *)roster { if (!_roster) { self.roster = [[XMPPRoster alloc] initWithRosterStorage:[XMPPRosterCoreDataStorage sharedInstance] dispatchQueue:dispatch_get_main_queue()]; //配置參數
 [_roster addDelegate:self delegateQueue:dispatch_get_main_queue()]; } return _roster; } - (void)viewDidLoad { [super viewDidLoad]; //記錄stream
    [XMPPManager sharedManager].stream = self.stream; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated.
} //登錄按鈕
- (IBAction)loginClick:(id)sender { //登錄 //1.斷開鏈接
 [self.stream disconnect]; //2.設置JID:設置字符串宏
    self.stream.myJID = [XMPPJID jidWithString: JID(self.userNameTF.text)]; //3.鏈接服務器
    [self.stream connectWithTimeout:-1 error:nil]; } #pragma mark-XMPPStreamDelegate
//鏈接服務器成功
- (void)xmppStreamDidConnect:(XMPPStream *)sender { //鏈接服務器成功之後登錄
 [self.stream authenticateWithPassword:self.passwordTF.text error:nil]; } //鏈接服務器超時
- (void)xmppStreamConnectDidTimeout:(XMPPStream *)sender { NSLog(@"鏈接超時"); } //登錄成功
- (void)xmppStreamDidAuthenticate:(XMPPStream *)sender { //發送登錄成功狀態
    XMPPPresence *presence = [XMPPPresence presence]; [self.stream sendElement:presence]; //記錄當前登錄的JID
    [[NSUserDefaults standardUserDefaults] setObject:[NSString stringWithFormat:@"%@@bogon", self.userNameTF.text] forKey:@"MyJID"]; [[[UIAlertView alloc] initWithTitle:@"登錄成功" message:@"" delegate:self cancelButtonTitle:@"好的" otherButtonTitles: nil] show]; } //登陸失敗
- (void)xmppStream:(XMPPStream *)sender didNotAuthenticate:(DDXMLElement *)error { [[[UIAlertView alloc] initWithTitle:@"登錄失敗" message:@"" delegate:self cancelButtonTitle:@"好的" otherButtonTitles: nil] show]; } //接收到消息的代理方法
- (void)xmppStream:(XMPPStream *)sender didReceiveMessage:(XMPPMessage *)message { //若是body的長度爲空
    if (message.body.length == 0) { } else { NSLog(@"message: %@", message); } } #pragma mark - UIAlertViewDelegate
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex { NSLog(@"%ld", buttonIndex); if (buttonIndex == 0) { //觸發sugue
        [self performSegueWithIdentifier:@"modelToContact" sender:nil]; } else { //清空密碼輸入框
        self.passwordTF.text = @""; } } #pragma mark-XMPPRosterDelegate
- (void)xmppRosterDidBeginPopulating:(XMPPRoster *)sender { NSLog(@"開始獲取花名冊"); self.rosterArr = [@[] mutableCopy]; } - (void)xmppRoster:(XMPPRoster *)sender didReceiveRosterItem:(DDXMLElement *)item { NSLog(@"獲取花名冊中"); [self.rosterArr addObject:item]; } - (void)xmppRosterDidEndPopulating:(XMPPRoster *)sender { NSLog(@"結束獲取"); NSLog(@"rosterArr: %@", self.rosterArr); } //屬性傳值
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { if ([segue.identifier isEqualToString:@"modelToContact"]) { ContactViewController *contact = segue.destinationViewController; contact.temArr = self.rosterArr; } } @end
ContactViewController.m #import "ContactViewController.h"
#import "DDXMLElement.h"
#import "ChatViewController.h"

@interface ContactViewController ()<UITableViewDataSource, UITableViewDelegate>
- (IBAction)back:(id)sender; @property (weak, nonatomic) IBOutlet UITableView *tableView; @end

@implementation ContactViewController - (void)viewDidLoad { [super viewDidLoad]; [self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"cell"]; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated.
} #pragma mark-UITableViewDataSource
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return self.temArr.count; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell" forIndexPath:indexPath]; DDXMLElement *friendItem = self.temArr[indexPath.row]; //找到 JID 字符串
    NSString *jidString = [[friendItem attributeForName:@"jid"] stringValue]; cell.textLabel.text = jidString; return cell; } - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { [self performSegueWithIdentifier:@"modelToChat" sender:indexPath]; } #pragma mark - Navigation

// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { if ([segue.identifier isEqualToString:@"modelToChat"]) { ChatViewController *chatVC = segue.destinationViewController; NSIndexPath *index = (NSIndexPath *)sender; chatVC.friendJID = [[self.temArr[index.row] attributeForName:@"jid"] stringValue]; } } - (IBAction)back:(id)sender { [self dismissViewControllerAnimated:YES completion:nil]; } @end
ContactViewController.h #import <UIKit/UIKit.h>

@interface ContactViewController : UIViewController @property (nonatomic, strong) NSMutableArray *temArr; @end
ChatViewController.h #import <UIKit/UIKit.h>

@interface ChatViewController : UIViewController @property (nonatomic, copy)NSString *friendJID; @end
ChatViewController.m #import "ChatViewController.h"
#import "XMPPFramework.h"
#import "XMPPManager.h"

@interface ChatViewController ()<UITableViewDelegate, UITableViewDataSource, UITextFieldDelegate, XMPPStreamDelegate>
- (IBAction)back:(id)sender; @property (weak, nonatomic) IBOutlet UITableView *tableView; @property (weak, nonatomic) IBOutlet UITextField *textField; @end

@implementation ChatViewController - (void)viewDidLoad { [super viewDidLoad]; [self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"cell"]; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated.
} #pragma mark-UITableViewDataSource
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return 10; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell" forIndexPath:indexPath]; cell.textLabel.text = @"123"; return cell; } #pragma mark-XMPPStreamDelegate
- (void)xmppStreamDidConnect:(XMPPStream *)sender { NSLog(@"鏈接服務器成功"); } - (void)xmppStreamConnectDidTimeout:(XMPPStream *)sender { NSLog(@"鏈接服務器超時"); } - (void)xmppStream:(XMPPStream *)sender didSendMessage:(XMPPMessage *)message { NSLog(@"發送成功"); } - (void)xmppStream:(XMPPStream *)sender didFailToSendMessage:(XMPPMessage *)message error:(NSError *)error { NSLog(@"消息發送失敗%@", error); } /* #pragma mark - Navigation // In a storyboard-based application, you will often want to do a little preparation before navigation - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { // Get the new view controller using [segue destinationViewController]. // Pass the selected object to the new view controller. } */

- (IBAction)back:(id)sender { [self dismissViewControllerAnimated:YES completion:nil]; } #pragma mark-UITextFieldDelegate
//點擊return按鈕事件
- (BOOL)textFieldShouldReturn:(UITextField *)textField { //建立消息體
    XMPPMessage *message = [XMPPMessage messageWithType:@"text" to:[XMPPJID jidWithString:self.friendJID]]; //添加消息內容
 [message addBody:textField.text]; //發送消息
 [[XMPPManager sharedManager].stream sendElement:message]; //收回鍵盤
 [textField resignFirstResponder]; return YES; } @end
XMPPManager.h #import <Foundation/Foundation.h>

@interface XMPPManager : NSObject + (XMPPManager *)sharedManager; @property (nonatomic, strong) id stream; @end
XMPPManager.m #import "XMPPManager.h"

@implementation XMPPManager + (XMPPManager *)sharedManager { static XMPPManager *manager = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ manager = [self new]; }); return manager; } @end
NSString+JID.h #import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
@interface UITextField (JID) @property (nonatomic, copy) NSString *jid; @end
NSString+JID.m #import "NSString+JID.h"

@implementation UITextField (JID) - (void)setJid:(UITextField *)jid { } - (NSString *)jid { return [NSString stringWithFormat:@"%@@bogon", self.text]; } @end
RegisterViewController.m #import "RegisterViewController.h"
//引入 XMPP 框架的頭文件
#import "XMPPFramework.h"
@interface RegisterViewController ()<XMPPStreamDelegate> @property (weak, nonatomic) IBOutlet UITextField *userNameTF; @property (weak, nonatomic) IBOutlet UITextField *passwordTF; - (IBAction)registerClick:(id)sender; - (IBAction)goBack:(id)sender; //建立一個 XMPPStream類的屬性
@property (nonatomic, strong) XMPPStream *stream; @end

@implementation RegisterViewController - (void)viewDidLoad { [super viewDidLoad]; //初始化 XMPPStream
    self.stream = [[XMPPStream alloc] init]; //設置服務器地址
    _stream.hostName = @"127.0.0.1"; //設置服務器的端口號
    _stream.hostPort = 5222; //設置XMPPStream代理
 [_stream addDelegate:self delegateQueue:dispatch_get_main_queue()]; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated.
} /* #pragma mark - Navigation // In a storyboard-based application, you will often want to do a little preparation before navigation - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { // Get the new view controller using [segue destinationViewController]. // Pass the selected object to the new view controller. } */

- (IBAction)registerClick:(id)sender { //設置 JID //JID是用戶在聊天服務器中的惟一標識 //JID 有兩部分構成: 用戶名@域名
    self.stream.myJID = [XMPPJID jidWithString:[NSString stringWithFormat:@"%@@bogon", self.userNameTF.text]]; //註冊 //1. 鏈接服務器 //先斷開鏈接
 [self.stream disconnect]; //-1 表明無限大, 直到鏈接上服務器
    [self.stream connectWithTimeout:-1 error:nil]; } - (IBAction)goBack:(id)sender { [self dismissViewControllerAnimated:YES completion:nil]; } #pragma mark-XMPPStreamDelegate
//鏈接服務器超時
- (void)xmppStreamConnectDidTimeout:(XMPPStream *)sender { NSLog(@"%s", __FUNCTION__); } //鏈接服務器成功
- (void)xmppStreamDidConnect:(XMPPStream *)sender { NSLog(@"%s", __FUNCTION__); //2.鏈接服務器成功之後進行註冊
 [self.stream registerWithPassword:self.passwordTF.text error:nil]; } //註冊成功
- (void)xmppStreamDidRegister:(XMPPStream *)sender { [[[UIAlertView alloc] initWithTitle:@"恭喜你" message:@"註冊成功" delegate:self cancelButtonTitle:nil otherButtonTitles:@"前往登錄", nil] show]; } //註冊失敗
- (void)xmppStream:(XMPPStream *)sender didNotRegister:(DDXMLElement *)error { } @end
相關文章
相關標籤/搜索