XMPP推送通知导致消息中出现问题(延迟和重复)
XMPP推送通知导致消息中出现问题(延迟+重复) 我已经使用XMPP+Ejabberd成功创建了一个聊天应用程序 没有推送通知: 无论是单人聊天还是集体聊天,都能完美地工作 使用推送通知: 有时,一切都很完美。通知被触发,消息被接收,没有任何延迟或重复 有时不会触发任何通知(当应用程序处于后台时),但会完美地接收消息 有时会触发通知,但会延迟和重复接收消息 服务器端的所有内容都已正确配置。他们建议通过确保每个会话都与一个持久性资源连接、使用空白保持连接稳定以及在连接丢失时使用同一资源重新绑定来解决问题 我有流管理,xmppStream.enableBackgroundingOnSocket和应用程序提供IP语音服务后台模式启用 当用户注销或应用程序终止时,我将断开流并发送不可用的状态 下面是我的xmpp流推送通知和连接/断开连接的代码 我正在为这个拔头发。如果你们有任何想法,请告诉我 谢谢XMPP推送通知导致消息中出现问题(延迟和重复),xmpp,apple-push-notifications,ejabberd,xmppframework,ejabberd-saas,Xmpp,Apple Push Notifications,Ejabberd,Xmppframework,Ejabberd Saas,XMPP推送通知导致消息中出现问题(延迟+重复) 我已经使用XMPP+Ejabberd成功创建了一个聊天应用程序 没有推送通知: 无论是单人聊天还是集体聊天,都能完美地工作 使用推送通知: 有时,一切都很完美。通知被触发,消息被接收,没有任何延迟或重复 有时不会触发任何通知(当应用程序处于后台时),但会完美地接收消息 有时会触发通知,但会延迟和重复接收消息 服务器端的所有内容都已正确配置。他们建议通过确保每个会话都与一个持久性资源连接、使用空白保持连接稳定以及在连接丢失时使用同一资源重新绑定来解
#pragma mark - Connect/Disconnect
- (BOOL)connect {
if (!_xmppStream) {
NSLog(@"Setting up Stream");
[self setupStream];
}
if (![_xmppStream isDisconnected]) {
return YES;
}
NSString *jabberID = [[NSUserDefaults standardUserDefaults] stringForKey:@"userID"];
NSString *myPassword = [[NSUserDefaults standardUserDefaults] stringForKey:@"userPassword"];
if (jabberID == nil || myPassword == nil) {
return NO;
}
[_xmppStream setMyJID:[XMPPJID jidWithString:jabberID]];
_password = myPassword;
NSError *error = nil;
if (![_xmppStream connectWithTimeout:XMPPStreamTimeoutNone error:&error]){
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Error" message:[NSString stringWithFormat:@"Can't connect to server! %@", [error localizedDescription]] delegate:nil cancelButtonTitle:@"Ok" otherButtonTitles:nil];
[alert show];
return NO;
}
return YES;
}
- (void)disconnect {
[self goOffline];
[self teardownStream];
}
- (void)xmppStreamDidAuthenticate:(XMPPStream *)sender {
[self goOnline];
//Stream Management
NSXMLElement *enable = [NSXMLElement elementWithName:@"enable" xmlns:@"urn:xmpp:sm:3"];
[enable addAttributeWithName:@"resume" stringValue:@"true"];
[_xsm.xmppStream sendElement:enable];
//Push
[self configurePushNotifications];
//
}
-(void)configurePushNotifications{
NSString *jabberID = [[NSUserDefaults standardUserDefaults] stringForKey:@"userID"];
NSXMLElement *iq = [NSXMLElement elementWithName:@"iq"];
[iq addAttributeWithName:@"type" stringValue:@"set"];
[iq addAttributeWithName:@"id" stringValue:idString];
NSXMLElement *push = [NSXMLElement elementWithName:@"push" xmlns:@"p1:push"];
NSXMLElement *keepalive = [NSXMLElement elementWithName:@"keepalive"];
[keepalive addAttributeWithName:@"max" integerValue:30];
NSXMLElement *session = [NSXMLElement elementWithName:@"session"];
[session addAttributeWithName:@"duration" integerValue:60];
NSXMLElement *body = [NSXMLElement elementWithName:@"body"];
[body addAttributeWithName:@"send" stringValue:@"all"];
[body addAttributeWithName:@"groupchat" stringValue:@"true"];
[body addAttributeWithName:@"from" stringValue:jabberID];
NSXMLElement *status = [NSXMLElement elementWithName:@"status"];
[status addAttributeWithName:@"type" stringValue:[NSString stringWithFormat:@"New message from %@",jabberID]];
NSXMLElement *offline = [NSXMLElement elementWithName:@"offline" stringValue:@"true"];
[push addChild:keepalive];
[push addChild:session];
[push addChild:body];
[push addChild:status];
[push addChild:offline];
NSXMLElement *notification = [NSXMLElement elementWithName:@"notification"];
[notification addChild:[NSXMLElement elementWithName:@"type" stringValue:@"applepush"]];
[notification addChild:[NSXMLElement elementWithName:@"id" stringValue:_userDeviceToken]];
[push addChild:notification];
NSXMLElement *appid = [NSXMLElement elementWithName:@"appid" stringValue:@"appid"];
[push addChild:appid];
[iq addChild:push];
[[self xmppStream] sendElement:iq];
}
- (void)setupStream {
_xmppStream = [[XMPPStream alloc] init];
_xmppStream.hostName = kHostName;
_xmppStream.hostPort = kHostPort;
_xmppStream.enableBackgroundingOnSocket = YES;
[_xmppStream addDelegate:self delegateQueue:dispatch_get_main_queue()];
//XMPPReconnect
_xmppReconnect = [[XMPPReconnect alloc] init];
[_xmppReconnect activate:_xmppStream];
//Stream Management
_xsm = [[XMPPStreamManagement alloc] init];
[_xsm enableStreamManagementWithResumption:YES maxTimeout:0];
[_xsm activate:_xmppStream];
//Last Activity
_xmppLastActivity = [[XMPPLastActivity alloc] initWithDispatchQueue:dispatch_get_main_queue()];
[_xmppLastActivity addDelegate:self delegateQueue:dispatch_get_main_queue()];
[_xmppLastActivity activate:_xmppStream];
}
- (void)goOnline {
XMPPPresence *presence = [XMPPPresence presence];
[[self xmppStream] sendElement:presence];
}
- (void)goOffline {
XMPPPresence *presence = [XMPPPresence presenceWithType:@"unavailable"];
[[self xmppStream] sendElement:presence];
}
- (void)teardownStream {
[_xmppStream disconnect];
[_xmppStream removeDelegate:self];
[_xmppReconnect removeDelegate:self];
[_xmppLastActivity removeDelegate:self];
[_xmppReconnect deactivate];
_xmppStream = nil;
_xmppReconnect = nil;
_xmppLastActivity = nil;
}
您应该通知流管理以断开会话和连接 在拆卸中调用此断开连接方法:
[self.stream disconnectAfterSending];
您需要确保在连接到ejabberd时正在传递资源。资源应该在第一次安装应用程序和随后登录时随机生成,您应该始终使用相同的资源。否则,将在服务器上的每个新登录名上创建一个新的长时间运行的分离会话,并将消息路由到所有挂起的会话。当这些到期时,它们将再次路由等
在XMPP中,资源基本上是设备的标识符。您需要生成JID,以便使用表单字符串登录”user@domain/resource“您是否在60秒或..之后收到状况不良的推送通知?您使用哪个模块进行推送通知。ejabberd社区版中没有此类模块。您正在使用ejabberd SaaS吗?是的。有时一条消息会使用两次。我很确定我的会话有问题。@MickëlRémond是的ejabberd SaaS。这对ejabberd SaaS无效。您的意思是这样设置:[[u xmppStream setMyJID:[XMPPJID jidWithString:jabberID]];叽叽喳喳=user@domain/udid,当用户注销,另一个用户允许用户2登录时,它应该像jabberID=user2@domain/udid udid:在第一次安装时生成。我不建议使用udid。只需在第一次安装时生成一个短的随机字符串,比如6到8个字符长。比如:“RX2eE7”。Udid太长,将消耗大量带宽。是的,我将生成一个随机数。将进行测试并返回给您。谢谢。哦,伙计。看起来延迟和重复问题已经消失。仍然存在一些错误:1)有时即使我关闭了会话并断开了连接,我仍可以看到用户在线。2) 用户注销时会收到推送通知。可能是因为此原因(NSXMLElement*offline=[NSXMLElement elementWithName:@“offline”stringValue:@“true”;)。仍面临推送通知问题(后台应用程序登录用户)@Mickaël Rémond