1. 即时通信
1> 概述
即时通讯(Instant Messaging)是目前Internet上最为流行的通讯方式,各种各样的即时通讯软件也层出不穷,服务提供商也提供了越来越丰富的通讯服务功能。
即时通讯有多种实现方式,例如:XMPP、环信、融云等。
2> XMPP(可扩展消息处理现场协议)
XMPP(XML Messages Presence Protocol(可扩展消息处理现场协议))是基于可扩展标记语言(XML)的协议,可用于即时通信(IM)。
3> XMPP的优点
- 开放
XMPP协议是由JSF开源社区组织开发的,不属于任何的机构和个人,从根本上保证了其开放性。
- 标准
互联网工程工作组将XMPP于2002年正式列为认可的实时通讯及Presence技术。
- 分布式的网络架构
XMPP 协议虽然是基于Client/Server 架构,但是XMPP协议本身并没有这样的限制。网络的架构和电子邮件十分相似,但没有结合任何特定的网络架构,适用范围非常广泛。
- 具有良好的扩展性
基于XML 建立起来的应用具有良好的语义完整性和扩展性。
- 具有很好的弹性
XMPP 除了可用在即时通信的应用程序,还能用在网络管理、内容供稿、协同工具、档案共享、游戏、远端系统监控等。
- 安全性
XMPP在Client-to-Server通信和Server-to-Server通信中都使用TLS (Transport Layer Security)协议作为通信通道的加密方法,保证通信的安全。
XMPP环境的搭建的步骤详见XMPP环境的搭建
2. 工程中添加XMPP
将XMPP协议第三方文件拖入工程,下载地址:https://github.com/AlonerOwl/XMPPFramework
3. 登录、注册
1> 界面搭建
界面采用Storyboard,效果图如下:
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> 注册代码所需方法
aaarticlea/png;base64,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EAgEAoFAIBAI1BeBMGzri1QzzPf666/LUUcdNU5P/vvvv8sRRxxR7zI++eQTOe644+qdPzIGAoFAINDUEfjwww/l9NNPH6fH+Oqrr+Tuu++WL7/8Un788Uf59ttva/zFPtLjBHFc3EQQmEgbelasa2ykXkSkeR6/9dZbsvjii8vIkSNljjnmKAvCH3/8IYsttphsvvnm0qdPH5l88slL8r399tuy9NJLCwZuXfLTTz9Jp06dZJppppETTzyxRvY555xT5p133hrpkdA0EAi90jTeU9RywiPQuXNneemll0yXzjDDDLL//vubLj366KNr/KjJ1FNPLf3795e///5bjj32WBk+fLgMGTJEIAWWW245OeCAA2SLLbaocR1PtfHGG8sdd9wx4R8w7hgIjGcE0vGl4i+Pjec6RPGNCIHLL79crr/++rI1mmSSSWSDDTaQVq1a1Ti/zTbbyK677iq33HKL7LTTTvLAAw/IvffeKzfccIMMGzbM8n/99dfy119/Sc+ePfPrp5pqKjNcJ574/w6D7777TjbaaCP59NNPZfrpp5fu3bvn+fny66+/yscffyyDBw+W9u3bl5yLg0AgEAgEmioC1157rbz88sty6aWXSosWLeTggw+WZ555Rvbee2/Zfffd5fHHH5e77rpLzjrrLDNWe/ToIa+++qoss8wypi+32morOfXUU+XWW28ViIabbrpJLrzwQjN6n3rqKZl99tnll19+kdVWW00WXnjhpgpT1DsQqDcCYdjWG6rqzbjUUksJbKnL1VdfLbACm222mRmbnl785DpkiSWWkOeee06OOeYYGTp0qGCwYhAjKGrEj/k+2WSTSfrzdyh1jORRo0YJ4Q9t27YlWy4wEyj5QYMGyUILLZSnx5dAIBAIBJoyAh988IHstddeZpiut956csopp5jOhLGFud12223lggsukK233tq+86ywuNNNN520bNlSCD9AP3KM3r344ouNiNhzzz2NZOC6gQMHyg477CBt2rSR448/vinDFXUPBOqFQIQi1Aum5pWJsIL555/flG1dT+4GMeED5aSuUITLLrtM9ttvP3O9oeQfeeQROfnkk2WPPfYw4/e3334zo/e1116Tp59+2tiHcveJtMaPQOoqavy1jRoGAuMfAUgEvF5//vlnyc1mnHFGCzFgfcKNN95oBi+s66STTmqM7jfffGPf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zDLLyO+//y4wu0sttZSdf/fdd42thQlGSKd8hHwROmZQxL8qRyAM2wov+Ktvv5XDzjpXTth/P+lz/oUy+WSTyTmH97Lcbwx5X8688ipzsbeZY3Y5oNuOssISi9u5X377Tc6/5jp5eNBzMt3UU8sW661tn5+rQbfzZpvI86+/IRiVh+66c17W2VddrUbnxzKzupO21Pxd11lbrh94nzz87LPyx59/yoGnnC4tWkwiu26+mSzYto38qbFXXPPwoGflr7/+ljVW7CCH7NpNJpt0UnlKDVXCDjBAT77scll/lU5237ZzziHDPhklnZZdxu476OVXZYt117b8btgOHzVK2s45p52HsX1PGYO9t91aHnxmkNx03wPy6ZdfWl0wiLuus5assOQSlvdnjQE76ty+xujOMN20svuWXWWj1Vezc8V/M7ecSbZWQxoG1+X194YYnsO1fisutaTiuYNhf94RvWWaqaaSm+9/UNnjgfKdutHatWkj+263tSzerp38pe62866+Vh76F4elF1lIDthpR30vH8rHn38uO3TZyG8hp/a7wjDx98S1h5x2hpy4fw+Zasop5e7HHper77xHPvx4pMwz++yy9frrGT4U8JHicnb/q+XAnXeUPn0vkjnUvXd8z32t7Kc1XKPvNddbiMXqHZaXzdZcI79nfAkEAoFAoDYERowYId9//70svvjisscee1jWbt265eFajz/+uOy0007ykYaGuWDYYqSGBAKBQHkEIhShPC7y7Q8/CO76Y9SoXXeVleXoffa0nCM+/VRw62+13rryQL+LZcdNush+J5ykRt9Xdv64Cy6WJ14YLPuoQXho913kyRdfkv6336VG4vDR12uM7dsfjHYHYVztdezxsl6nleWWc8+SHjtsK9fePVC+/f4HmXeuOWWWVi2l5QwzSPtFFjbWtvVMM1oZffpeKJ989rn0O+FYuerUE4WQhbOuHGDnRmqc1jNqtJ6nxnXPHbfP2VgM2+GffGJ5MNpHffmF7LXNVjL4rbfMeOYEhiX3RYZ9/HFe5zlmmUXmmm1WmWbqqawu7ZVBJs3lkhtvlo7tl5LrzjxVNltrTTn87PPkXTWKKwmxvK6YP/3iS9nliKNkpaWXkmtOP1nWWbmjnHxJP3lBJwDf//iTGel9r71ejuuxj1x/5mnG/l50/U1W9DV33WPv6OI+R8nlikVLZSau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cS0mrg8ExgkB2vbzzz9ftgzafyoYDM8991yaZN+///57efjhh0vSP/vss7xfvvnmm/Ljjz+WnP/uu+/k5ZdftjyvvfaafPPNNyXnOeCa66+/Xi655JKxGrRrFPgfJIDZgQceKD/88EN+96+++kp69OghfNZX/vnnH5l99tnNiKnrmjPOOEP23XffurI1yvO0iyOPPLLWur3++uvStm1bufzyy8vme/DBB+X2228ve25cEkeOHCkrrriiYVscE5hIMH7cdtttFW8xdOhQWXLJJWXGGWe0v1lnnVVuuukmGTZsmCy44ILSunVr+5t55pllyy23rFhOeuLGG2+0PklfXW655aRr1671aiNexuOPPy6PPPKIH8ZnLQhU/OWxWq6JU/8RAr169ZLzzz9f1lxzTRk+fLjsvffeNtjMOeecVqP+/fvLtttuK5NNNtl/VMPab7vOOuuYMTv99NPbQPjJJ5/I2muvLVdeeaUpD64eNGiQKcutt966YmHMep1BOfXUU+Wss84SFAwDCgNQp06d5MQTT5Sll166Yhn1PUGZhx9+uFDnDTfcsM7LrrrqKqHuk08+eZ15I0MgMCYIjBo1StZYYw158sknpX379vmlZ555ptx1113yxBNP5Gm77rqrPProo/L+++9LmzZt8nR0CMbn008/LR07drT01Vdf3Yy5aaaZRjBW6F877bST9OvXTyaZZBKhLO4500wzCRNJDED6LRNQBn50EUbEDDPMIO3atZODDz5Y9tlnHznllFOs/Pfee08wnlddddW8Ho3pC3XbZZdd5O2337ZqYXAss8wygj4FUwyhbbbZRvyXjdAF6B3ylJO///7bWF+MfQyg2gQjmsnGhJIhQ4YI7Wi11Var9y15n+UYRtoCZAXvddJJJy0pD6z69OljbQx2tHv37vLAAw+Yrj/uuOPkt99+s/ywqh988IH07Nkzv36hhRaSvfbaKz8emy/zzjuvTcZ4l7Tv++67T77++uu8qN13392Y06WWWipPo/0zjiCPPfaYve+nnnrKjmnL9KcpppjC6v7QQw9ZOm2GtpMKY9O9994rP/30U5psGNFnVlllFZl22mnlwgsvlOOPP94w2mqrrWTnnXeuYWyffvrpZjhjnIP3r7/+mpMsU045pUw33XQl94iD0QiEYdtEWgKMIUwlAwyGG8Jslw6C/PXXX9Yx6MTzzDOP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" alt="" />
6> 全部代码(方法的使用详见代码注释)
- 封装的XMPP控制器代码:
XMPPManager.h
#import <Foundation/Foundation.h> #import "XMPPFramework.h" @interface XMPPManager : NSObject /// 声明XMPP通道属性
@property (nonatomic, strong) XMPPStream *xmppStream; + (XMPPManager *)shareXMPPManager; // 登录方法
- (void)loginWithUsername:(NSString *)username
password:(NSString *)password;
// 注册方法
- (void)registerWithUsername:(NSString *)username
password:(NSString *)password; @end
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: 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:(DDXMLElement *)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:(DDXMLElement *)error
{
NSLog(@"注册失败:%@", error);
} @end
未完待续...