demo https://github.com/gwh111/testxmpp
xmpp介绍
中文官方http://wiki.jabbercn.org/%E9%A6%96%E9%A1%B5
ios库下载https://github.com/robbiehanson/XMPPFramework
重连问题https://www.jianshu.com/p/d9de0267c52a
推荐使用pod
pod 'XMPPFramework', '~> 3.7.0'
导入
import XMPPFramework // swift
@import XMPPFramework; //objective-c
Module 'XMPPFramework' not found
参考https://blog.csdn.net/yuedong56/article/details/38120101
XEP-0198: Stream Management
h文件
#import
@interface XMPPHelper : NSObject
//@property(nonatomic,assign) BOOL isConnecting;
+ (instancetype)getInstance;
- (BOOL)initWithUserName:(NSString *)userName andPassword:(NSString *)password andHostName:(NSString *)hostName andDomain:(NSString*)domain andHostPort:(UInt16)hostPort andInfoDic:(NSDictionary *)infoDic;
- (BOOL)connect;
- (void)disconnect;
- (BOOL)isConnected;
@end
初始化参数说明
userName 用户名
password 密码
hostName 主机名 如10.5.190.1
domain 域名 如qpmjcore-98-1/smack
hostPort 端口号 如5222
类说明
XMPPJID 根据初始化数据构造的发送地址
XMPPStream 输入输出流
XMPPStreamManagement 输入输出流的管理
XMPPStreamManagementMemoryStorage 数据永久存储
XMPPReconnect 重连模块
接收消息和发送消息通过
- (void)xmppStream:(XMPPStream *)sender didReceiveMessage:(XMPPMessage *)message{
NSString *messageBody = [[message elementForName:@"body"] stringValue];
// [ShareCallback xmppPushMsg:messageBody];
// int su=[_xmppStream supportsStreamManagement];
// [self sendMessage:@"aaa" to:_jid];
//
// NSXMLElement *enable = [NSXMLElement elementWithName:@"r" xmlns:@"urn:xmpp:sm:3"];
// [[self xmppStream] sendElement:enable];
}
- (void)sendMessage:(NSString *)message to:(XMPPJID *)jid
{
XMPPMessage* newMessage = [[XMPPMessage alloc] initWithType:@"chat" to:jid];
[newMessage addBody:message]; //消息内容
[_xmppStream sendElement:newMessage];
}
- (void)xmppStream:(XMPPStream *)sender didSendMessage:(XMPPMessage *)message{
}
在建立连接,验证通过后开启流管理enableStreamManagementWithResumption
这里有一个XEP-0198协议 https://xmpp.org/extensions/xep-0198.html
If YES, the resume attribute will be included. E.g.
在客户端就是通过发送一个element来开启,开启后在每接收到一定消息后会通过上面提到的Acks /r和/a的标签来验证消息
可以通过
- (void)xmppStream:(XMPPStream *)sender didSendCustomElement:(NSXMLElement *)element{
NSLog(@"didSendCustomElement%@",element);
}
- (void)xmppStream:(XMPPStream *)sender didReceiveCustomElement:(NSXMLElement *)element{
NSLog(@"didReceiveCustomElement%@",element);
}
来查看/r和/a的标签
demo https://github.com/gwh111/testxmpp
更新:
xmpp断线重连模块
//接入断线重连模块
_xmppReconnect = [[XMPPReconnect alloc] init];
_xmppReconnect.reconnectTimerInterval=5;
_xmppReconnect.reconnectDelay=0;
[_xmppReconnect setAutoReconnect:YES];
[_xmppReconnect activate:self.xmppStream];
[_xmppReconnect addDelegate:self delegateQueue:dispatch_get_global_queue(0, 0)];
#pragma mark - XMPPReconnectDelegate
- (void)xmppReconnect:(XMPPReconnect *)sender didDetectAccidentalDisconnect:(SCNetworkConnectionFlags)connectionFlags {
NSLog(@"xmpp意外断开连接。");
[ShareCallback xmppCallback:@"disconnect"];
[self disconnect];
}
- (BOOL)xmppReconnect:(XMPPReconnect *)sender shouldAttemptAutoReconnect:(SCNetworkConnectionFlags)connectionFlags {
return YES;
}
xmpp顶号 在另一台设备登录
- (void)xmppStream:(XMPPStream *)sender didReceiveError:(id)error
{
NSLog(@"收到错误消息%@",error);
if ([error isKindOfClass:[DDXMLElement class]]) {
DDXMLElement *er=error;
if ([er.description containsString:@"conflict"]) {
[ShareCallback xmppCallback:@"resign"];
[self disconnect];
return;
}
}
[ShareCallback xmppCallback:@"fail"];
//
// [ShareCallback xmppPushError:error];
}
xmpp的ping
XMPPAutoPing *xmppAutoPing = [[XMPPAutoPing alloc] init];
xmppAutoPing.pingInterval = 10.0;
[xmppAutoPing activate:_xmppStream];
[xmppAutoPing addDelegate:self delegateQueue:dispatch_get_global_queue(0, 0)];
#pragma mark- XMPPAutoPingDelegate
- (void)xmppAutoPingDidReceivePong:(XMPPAutoPing *)sender{
}
- (void)xmppAutoPingDidTimeout:(XMPPAutoPing *)sender {
[ShareCallback xmppCallback:@"fail"];
[self disconnect];
}