XMPP Stream 在加入 MUC 房间时断开连接

XMPP Stream gets disconnected on joining a MUC room

我正在使用 XMPPFramework 在我的应用程序中实现群聊功能。一对一聊天工作正常,但是当我通过调用 [xmppRoom joinRoomUsingNickname] 加入房间时,流会断开连接而不会出现任何错误。

我也实现了 xmppStreamDidDisconnect:withError,但它仍然给出 nil 错误。用户在加入房间后也会立即离开房间,因为流会断开连接。我也在使用重新连接模块,但是当它重新连接时,房间不会自动加入。

我也在用 pidgin 测试它,但它在那里工作得很好。立即断开连接的原因可能是什么?

PS:我正在 iPhone 5 运行 和 iOS 9.1

上使用它进行测试

更新:现在出现以下错误 -

Error Domain=GCDAsyncSocketErrorDomain Code=7 "Socket closed by remote peer" UserInfo={NSLocalizedDescription=Socket closed by remote peer}

通常当服务器关闭连接时,您会收到此错误。 服务器关闭连接有两种原因:

  1. 如果客户端空闲,您不会定期发送 ping。
  2. 您正在使用相同的凭据从其他客户端登录, 并且在服务器设置中有设置: 一律踢 - 如果资源冲突,立即踢对方 资源。在服务器 > 服务器设置 > 资源策略中。

请检查服务器设置。 将其用于服务器设置 http://docs.ejabberd.im/admin/guide/installation/

并检查项目中的 App Transport Security Setting。如果未添加,则将以下代码添加到 info.plist

 <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>NSAllowsArbitraryLoads</key>
    <true/>
</dict>
</plist>

试试这个模块

MessageManager.h

//  Created by Deepak MK on 27/11/15.
//

#import <UIKit/UIKit.h>

#import "XMPP.h"
#import <CoreData/CoreData.h>
#import "XMPPFramework.h"
#import "XMPPMessageDeliveryReceipts.h"
#import "XMPPLastActivity.h"
#import "XMPPRosterMemoryStorage.h"
#import "XMPPRoomMemoryStorage.h"
#import "XMPPvCardCoreDataStorage.h"
#import "XMPPvCardTemp.h"
/**
 message manager class manage all message sequence.
 */
@interface MessageManager : NSObject
{

    XMPPStream                                  *xmppStream;

    NSString                                    *password;

    BOOL                                        isOpen;

    BOOL                                        isRegistering;

    id                                          _delgate;

    XMPPRosterCoreDataStorage                    *xmppRosterStorage;

    XMPPRoster                                           *xmppRoster;

    XMPPvCardCoreDataStorage* xmppvCardStorage;
    XMPPvCardTempModule*xmppvCardTempModule;



}

+ (MessageManager *) sharedMessageHandler;

/**
 The stream varible for connecting stream
 */

@property (nonatomic, readonly) XMPPStream          *xmppStream;

/**
 XMPPRoster  varible
 */
@property (nonatomic, strong,readonly) XMPPRoster *xmppRoster;

/**
 XMPPRosterCoreDataStorage  varible 
 */
@property (nonatomic, strong,readonly) XMPPRosterCoreDataStorage *xmppRosterStorage;

/**
 XMPPRoom  varible
 */
@property (nonatomic, strong, readonly)  XMPPRoom *xmppRoom;


/**
 Setting of delegate
 @param delegate class delegate
 */
- (void) setdelegate:(id)delegate;

/**
 Return of delegate
 */
- (id)   delegate;

/**
 connecting stream of Xmpp server
 */

- (void) setupStream;

/**
 Connect user to Xmpp server
 @param jabberID    login user name
 @param myPassword  login password
 */
- (BOOL)connectWithUserId:(NSString*)jabberID withPassword:(NSString*)myPassword;

/**
 Connect user to Xmpp server
 @param userName    login user name
 @param myPassword  login password
 */
- (void) authenticateUserWIthUSerName:(NSString*)userName withPassword:(NSString*)myPassword;


/**
 disconnect user from Xmpp server
 */
- (void) disconnect;

/**
 changes the presence to online
 */
- (void) goOnline;

/**
 changes the presence to offline
 */
- (void) goOffline;

/**
 Register new user to xmpp server
 @param userName    new user name
 @param _password   new password
 @param EmailId     new email id
 */
- (void)registerStudentWithUserName:(NSString *)userName withPassword:(NSString *)_password withEmailId:(NSString *)EmailId;


/**
 send message to other user with content
 @param toAdress destination address
 @param content  content of message
 */
- (BOOL)sendMessageTo:(NSString*)toAdress withContents:(NSString*)content;



/**
 This method is used for sending subscribe invitation to user
 @param userID destination address
 */
- (void) sendSubscribeMessageToUser:(NSString*)userID;


/**
 This method is used for setting substate of presence
 @param subState substate of user
 */
- (void) presenceWithStubState:(NSString*)subState;


/**
 This method is used to create new room
 @param ChatRoomJID New room name
 */
- (void) setUpRoom:(NSString *)ChatRoomJID;


/**
 This method is used to destroyRoom
 */
- (void) destroyCreatedRoom;

/**
 This method is used to send message to group
 */
- (BOOL)sendGroupMessageWithBody:(NSString*)_body;



- (void) requestAllMesssage;

@end





/**
 Set of methods to be implemented to act as a restaurant patron
 */
@protocol MessageManagerDelegate <NSObject>

/**
 Methods to be get state of stream
 */
- (void) didGetStreamState:(BOOL)state;

/**
 Methods to be get state of Authentication
 */

- (void) didGetAuthenticationState:(BOOL)state;

/**
 Methods to be get state of registration
 */

- (void) didGetRegistrationState:(BOOL)state WithErrorMessage:(NSString*)errorMessage;

/**
 Methods to get recieved message
 */

- (void) didReceiveMessageWithBody:(NSString *) body;


/**
 Methods to get presence of other user
 */
- (void) didRecievePresence:(NSString*)state withUserName:(NSString*)userName WithSubState:(NSString*)subState;


/**
 Methods to get event of user joined room
 */
- (void) didCreatedOrJoinedRoomWithCreatedRoomName:(NSString*)_roomName;


- (void) didGetUserJoinedToRoomORLeaveRoomWithName:(NSString*)_userName WithPresence:(NSString*)presence;
@end

MessageManager.m

#import "MessageManager.h"

#import "DDLog.h"
#import "DDTTYLogger.h"
#import <CFNetwork/CFNetwork.h>
#if DEBUG
static const int ddLogLevel = LOG_LEVEL_VERBOSE;
#else
static const int ddLogLevel = LOG_LEVEL_INFO;
#endif

#define kBaseXMPPURL        @"XXXXXXXXXX"

@interface MessageManager()


@end

static MessageManager *sharedMessageHandler = nil;

@implementation MessageManager

@synthesize xmppStream;
@synthesize xmppRoster;
@synthesize xmppRosterStorage;
@synthesize xmppRoom;

#pragma mark - self class Delegate
- (void) setdelegate:(id)delegate
{
    _delgate= delegate;
}
- (id)   delegate
{
    return _delgate;
}



#pragma  mark - custom Functions
+ (MessageManager *) sharedMessageHandler
{

    if (sharedMessageHandler == nil)
    {
        sharedMessageHandler = [[super allocWithZone:NULL] init];
    }

    return sharedMessageHandler;
}

+ (id)allocWithZone:(NSZone *)zone {

    return [self sharedMessageHandler];
}

- (id)copyWithZone:(NSZone *)zone {

    return self;
}


#pragma mark - connection setup Functions

/**
 This fuction is used to setup XMPP Stream
 */
- (void)setupStream
{

    // Setup xmpp stream
    //
    // The XMPPStream is the base class for all activity.
    // Everything else plugs into the xmppStream, such as modules/extensions and delegates.

    xmppStream = [[XMPPStream alloc] init];
    [xmppStream setHostName:kBaseXMPPURL];
    [xmppStream addDelegate:self delegateQueue:dispatch_get_main_queue()];

}

/** 
 This fuction is used to Connect XMPP With userId and Password 
 */
- (BOOL)connectWithUserId:(NSString*)jabberID withPassword:(NSString*)myPassword
{

    [self setupStream];

    isRegistering=NO;

    if (![xmppStream isDisconnected]) {
        return YES;
    }


    if (jabberID == nil || myPassword == nil) {

        return NO;
    }

    [xmppStream setMyJID:[XMPPJID jidWithString:jabberID]];
    password = myPassword;

    NSError *error = nil;
    if (![xmppStream connectWithTimeout:XMPPStreamTimeoutNone error:&error])
    {
        UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Error"
                                                            message:[NSString stringWithFormat:@"Can't connect to server %@", [error localizedDescription]]
                                                           delegate:nil
                                                  cancelButtonTitle:@"Ok" 
                                                  otherButtonTitles:nil];
        [alertView show];


        return NO;
    }

    return YES;
}


- (void) authenticateUserWIthUSerName:(NSString*)userName withPassword:(NSString*)myPassword
{

    if ([xmppStream isConnected])
    {
        NSError*error =nil;
        [xmppStream setMyJID:[XMPPJID jidWithString:userName]];
        [xmppStream authenticateWithPassword:myPassword error:&error];

    }
    else
    {
        [self connectWithUserId:userName withPassword:myPassword];
    }

}


#pragma mark ---Delegate of Connect
/**
 This fuction is called when stream is connected
 */
- (void)xmppStreamDidConnect:(XMPPStream *)sender {

    isOpen = YES;
    NSError *error = nil;

    NSLog(@"Stream Connected");
    if (!isRegistering)
    {
        if([[self delegate] respondsToSelector:@selector(didGetStreamState:)])
        {
            [[self delegate]didGetStreamState:YES];
        }

        [xmppStream authenticateWithPassword:password error:&error];
    }
    else
    {
        [xmppStream registerWithPassword:password error:&error];
    }


}

/**
 This fuction is called when User is Authenticated
 */
- (void)xmppStreamDidAuthenticate:(XMPPStream *)sender {

    [self goOnline];
    NSLog(@"Stream Authenticated");
    if([[self delegate] respondsToSelector:@selector(didGetAuthenticationState:)])
    {
        [[self delegate]didGetAuthenticationState:YES];
    }



//    if ([xmppStream isAuthenticated]) {
//        NSLog(@"authenticated");
//        xmppvCardStorage = [[XMPPvCardCoreDataStorage alloc] initWithInMemoryStore];
//        xmppvCardTempModule = [[XMPPvCardTempModule alloc] initWithvCardStorage:xmppvCardStorage];
//        [xmppvCardTempModule activate:[self xmppStream]];
//        [xmppvCardTempModule addDelegate:self delegateQueue:dispatch_get_main_queue()];
//        [xmppvCardTempModule fetchvCardTempForJID:[sender myJID] ignoreStorage:YES];
//    }

}

- (void)xmppvCardTempModule:(XMPPvCardTempModule *)vCardTempModule didReceivevCardTemp:(XMPPvCardTemp *)vCardTemp forJID:(XMPPJID *)jid{


    NSLog(@"Delegate is called");
    XMPPvCardTemp *vCard = [xmppvCardStorage vCardTempForJID:jid xmppStream:xmppStream];
    NSLog(@"Stored card: %@",vCard);
    NSLog(@"%@", vCard.description);
    NSLog(@"%@", vCard.name);
    NSLog(@"%@", vCard.emailAddresses);
    NSLog(@"%@", vCard.formattedName);
    NSLog(@"%@", vCard.givenName);
    NSLog(@"%@", vCard.middleName);

}

/**
 This fuction is called when User is  not Authenticated
 */
- (void)xmppStream:(XMPPStream *)sender didNotAuthenticate:(NSXMLElement *)error
{
    NSLog(@"Not Authenticated");

    if([[self delegate] respondsToSelector:@selector(didGetAuthenticationState:)])
    {
        [[self delegate]didGetAuthenticationState:NO];
    }
}


#pragma mark - Stream disconnection

/**
 This fuction is used to disconnet user
 */
- (void)disconnect
{
    [self goOffline];
    [xmppStream disconnect];
}

#pragma mark ---Delegate of disconnect
/**
 This fuction is called when stream is disConnected
 */
- (void)xmppStreamDidDisconnect:(XMPPStream *)sender withError:(NSError *)error
{
    NSLog(@"Stream Disconnected");
    if([[self delegate] respondsToSelector:@selector(didGetStreamState:)])
    {
        [[self delegate]didGetStreamState:NO];
    }
}




#pragma mark - setting presence

/** 
 This fuction is used change the presence to online 
 */
- (void)goOnline
{
    XMPPPresence *presence = [XMPPPresence presence];
    [xmppStream sendElement:presence];
}

/**
 This fuction is used change the presence to Ofline 
 */
- (void)goOffline
{
    XMPPPresence *presence = [XMPPPresence presenceWithType:@"unavailable"];
    [xmppStream sendElement:presence];
}


/**
 This fuction is used change the presence substate
 */
- (void) presenceWithStubState:(NSString*)subState
{
    XMPPPresence *presence = [XMPPPresence presence];// type="available" is implicit

    NSXMLElement *status = [NSXMLElement elementWithName:@"status"];
    [status setStringValue:subState];
    [presence addChild:status];

    [xmppStream sendElement:presence];
}

/**
 This fuction is called when other user state is changed
 */
- (void)xmppStream:(XMPPStream *)sender didReceivePresence:(XMPPPresence *)presence
{
    DDLogVerbose(@"%@: %@ - %@", THIS_FILE, THIS_METHOD, [presence fromStr]);


    NSString *presenceType = [presence type];            // online/offline
    NSString *myUsername = [[sender myJID] user];
    NSString *presenceFromUser = [[presence from] user];
    NSString* presenceState= [presence status];

    NSLog(@"%@  is %@ state %@",presenceFromUser,presenceType,presenceState);

    if (![presenceFromUser isEqualToString:myUsername])
    {

        if ([presenceType isEqualToString:@"available"])
        {
            if([[self delegate] respondsToSelector:@selector(didRecievePresence:withUserName:WithSubState:)])
            {
                [[self delegate] didRecievePresence:presenceType withUserName:presenceFromUser WithSubState:presenceState];
            }

        }

        else if  ([presenceType isEqualToString:@"unavailable"]) {

             if([[self delegate] respondsToSelector:@selector(didRecievePresence:withUserName:WithSubState:)])
             {
                 [[self delegate] didRecievePresence:presenceType withUserName:presenceFromUser WithSubState:presenceState];
             }

        }
        else if  ([presenceType isEqualToString:@"subscribe"])
        {

            [xmppRoster subscribePresenceToUser:[presence from]];
            [self goOnline];
        }
        else if  ([presenceType isEqualToString:@"subscribed"])
        {
            [xmppRoster subscribePresenceToUser:[presence from]];
        }

    }
    if (xmppRoom)
    {
        [xmppRoom fetchMembersList];
    }


}

#pragma mark - subscription
- (void) sendSubscribeMessageToUser:(NSString*)userID
{
    XMPPJID* jbid=  [XMPPJID jidWithString:userID];
    XMPPPresence *presence = [XMPPPresence presenceWithType:@"subscribe" to:jbid];
    [xmppStream sendElement:presence];
}


#pragma mark - XMPP delegates
/**
 This fuction is called when new IQ is received 
 */
- (BOOL)xmppStream:(XMPPStream *)sender didReceiveIQ:(XMPPIQ *)iq {

    return NO;

}



#pragma mark - RegistrationFunction

/**
 This fuction is user to retister new user
   if stream is connected the it will directly call registeration function
    otherwise it will connect stream and then call registeration process 
 */

- (void)registerStudentWithUserName:(NSString *)userName withPassword:(NSString *)_password withEmailId:(NSString *)EmailId
{

    if (xmppStream==nil)
    {
        [self setupStream];
    }


    [xmppStream setMyJID:[XMPPJID jidWithString:userName]];
    NSLog(@"Attempting registration for username %@",xmppStream.myJID.bare);
    password=_password;
    NSError *error = nil;
    BOOL success;

    if(![ xmppStream isConnected])
    {
         success = [[self xmppStream] connectWithTimeout:XMPPStreamTimeoutNone error:&error];
        isRegistering=YES;
    }
    else
    {
        success = [[self xmppStream] registerWithPassword:_password error:&error];
    }

    if (success)
    {
        NSLog(@"succeed ");
        isRegistering=YES;
    }
    else
    {
        if([[self delegate] respondsToSelector:@selector(didGetRegistrationState:WithErrorMessage:)])
        {
            [[self delegate]didGetRegistrationState:YES WithErrorMessage:@"Stream not connected"];
        }
    }

}

#pragma mark ---delegates of registrtaion


/**
 This fuction is called when new user is registered 
 */
- (void)xmppStreamDidRegister:(XMPPStream *)sender{




    if([[self delegate] respondsToSelector:@selector(didGetRegistrationState:WithErrorMessage:)])
    {
        [[self delegate]didGetRegistrationState:YES WithErrorMessage:@"Registration with XMPP Successful!"];
    }


}


/**
 This fuction is called when registeration process failed 
 */
- (void)xmppStream:(XMPPStream *)sender didNotRegister:(NSXMLElement *)error{

//    DDXMLElement *errorXML = [error elementForName:@"error"];
//    NSString *errorCode  = [[errorXML attributeForName:@"code"] stringValue];

//    NSString *regError = [NSString stringWithFormat:@"ERROR :- %@",error.description];
//    
//    
//    if([errorCode isEqualToString:@"409"])
//    {
//        regError=@"Username Already Exists!";
//    }
//    else
//    {
//        regError= @"Server not connected";
//    }
    if([[self delegate] respondsToSelector:@selector(didGetRegistrationState:WithErrorMessage:)])
    {
        [[self delegate]didGetRegistrationState:NO WithErrorMessage:@"Username Already Exists!"];
    }

}



#pragma mark - send  and recieve message
/**
 This fuction is used to send message to other user with contents of body
 */



//-(void)sendMessageTo:(NSString*)toAdress withContents:(NSString*)messageStr
//{
//    
//    
//    if([messageStr length]> 0)
//    {
//        
//        NSXMLElement *body = [NSXMLElement elementWithName:@"body"];
//        [body setStringValue:messageStr];
//        
//        NSXMLElement *message = [NSXMLElement elementWithName:@"message"];
//        [message addAttributeWithName:@"type" stringValue:@"chat"];
//        [message addAttributeWithName:@"to" stringValue:toAdress];
//        [message addChild:body];
//        
//        [self.xmppStream sendElement:message];
//    }
//}



- (BOOL)sendMessageTo:(NSString*)toAdress withContents:(NSString*)content
{

    if([content length]> 0)
    {

        NSXMLElement *body = [NSXMLElement elementWithName:@"body"];
        [body setStringValue:content];

        NSXMLElement *message = [NSXMLElement elementWithName:@"message"];
        [message addAttributeWithName:@"type" stringValue:@"chat"];
        [message addAttributeWithName:@"to" stringValue:toAdress];
        [message addChild:body];

        [self.xmppStream sendElement:message];
    }
    return YES;
}

#pragma mark  recieve message
/**
 This fuction is called when new message arrived
 */

- (void)xmppStream:(XMPPStream *)sender didReceiveMessage:(XMPPMessage *)message
{
    DDLogVerbose(@"%@: %@", THIS_FILE, THIS_METHOD);

    // A simple example of inbound message handling.
    if ([message body])
    {
        NSString *body = [[message elementForName:@"body"] stringValue];
        if([[self delegate] respondsToSelector:@selector(didReceiveMessageWithBody:)])
        {
            [[self delegate] didReceiveMessageWithBody:body];
        }

    }
}



#pragma mark - create new room

/**
 This fuction is used to setup room with roomId
 */
-(void)setUpRoom:(NSString *)ChatRoomJID
{
    if (!ChatRoomJID)
    {
        return;
    }
    // Configure xmppRoom
    XMPPRoomMemoryStorage *roomMemoryStorage = [[XMPPRoomMemoryStorage alloc] init];

    XMPPJID *roomJID = [XMPPJID jidWithString:ChatRoomJID];

    xmppRoom = [[XMPPRoom alloc] initWithRoomStorage:roomMemoryStorage jid:roomJID dispatchQueue:dispatch_get_main_queue()];

    [xmppRoom activate:xmppStream];
    [xmppRoom addDelegate:self delegateQueue:dispatch_get_main_queue()];

    NSXMLElement *history = [NSXMLElement elementWithName:@"history"];
    [history addAttributeWithName:@" maxchars" stringValue:@"0"];
    [xmppRoom joinRoomUsingNickname:xmppStream.myJID.user
                            history:history
                           password:nil];


    [self performSelector:@selector(ConfigureNewRoom:) withObject:nil afterDelay:4];

}

/**
 This fuction is used configure new
 */
- (void)ConfigureNewRoom:(id)sender
{
    [xmppRoom configureRoomUsingOptions:nil];
    [xmppRoom fetchConfigurationForm];
    [xmppRoom fetchBanList];
    [xmppRoom fetchMembersList];
    [xmppRoom fetchModeratorsList];

}

/**
 This fuction is called when new room is created
 */
- (void)xmppRoomDidCreate:(XMPPRoom *)sender
{
    DDLogInfo(@"%@: %@", THIS_FILE, THIS_METHOD);

    // I am inviting friends after room is created


}

/**
 This fuction is called when user joined room
 */
- (void)xmppRoomDidJoin:(XMPPRoom *)sender
{
    [sender fetchMembersList];
    [sender fetchConfigurationForm];
    [self requestAllMesssage];
    DDLogInfo(@"%@: %@", THIS_FILE, THIS_METHOD);
    if([[self delegate] respondsToSelector:@selector(didCreatedOrJoinedRoomWithCreatedRoomName:)])
    {
        [[self delegate] didCreatedOrJoinedRoomWithCreatedRoomName:sender.myRoomJID.bare];
    }

}

- (void)xmppRoom:(XMPPRoom *)sender didFetchMembersList:(NSArray *)items
{

}

- (void)xmppRoom:(XMPPRoom *)sender occupantDidJoin:(XMPPJID *)occupantJID withPresence:(XMPPPresence *)presence
{
    if([[self delegate] respondsToSelector:@selector(didGetUserJoinedToRoomORLeaveRoomWithName:WithPresence:)])
    {
//        id details =occupantJID;
//        NSString* string = (NSString*)details;
         [[self delegate] didGetUserJoinedToRoomORLeaveRoomWithName:[occupantJID resource] WithPresence:[presence type]];
    }

}
- (void)xmppRoom:(XMPPRoom *)sender occupantDidLeave:(XMPPJID *)occupantJID withPresence:(XMPPPresence *)presence
{
    if([[self delegate] respondsToSelector:@selector(didGetUserJoinedToRoomORLeaveRoomWithName:WithPresence:)])
    {
        [[self delegate] didGetUserJoinedToRoomORLeaveRoomWithName:[occupantJID resource] WithPresence:[presence type]];
    }
}
- (void)xmppRoom:(XMPPRoom *)sender occupantDidUpdate:(XMPPJID *)occupantJID withPresence:(XMPPPresence *)presence
{
    if([[self delegate] respondsToSelector:@selector(didGetUserJoinedToRoomORLeaveRoomWithName:WithPresence:)])
    {
        [[self delegate] didGetUserJoinedToRoomORLeaveRoomWithName:[occupantJID resource] WithPresence:[presence type]];
    }
}


- (void) requestAllMesssage
{

//    <presence
//    from='hag66@shakespeare.lit/pda'
//    id='n13mt3l'
//    to='coven@chat.shakespeare.lit/thirdwitch'>
//    <x xmlns='http://jabber.org/protocol/muc'>
//    <history since='1970-01-01T00:00:00Z'/>
//    </x>
//    </presence>
//    
//    NSXMLElement *iQ = [NSXMLElement elementWithName:@"presence"];
//    [iQ addAttributeWithName:@"type" stringValue:@"get"];
//    [iQ addAttributeWithName:@"id" stringValue:@"n13mt3l"];
//    
//    NSXMLElement *retrieve = [NSXMLElement elementWithName:@"retrieve"];
//    [retrieve addAttributeWithName:@"xmlns" stringValue:@"urn:xmpp:archive"];
//    [retrieve addAttributeWithName:@"history since" stringValue:@"1970-01-01T00:00:00Z"];
//    
//    NSXMLElement *set = [NSXMLElement elementWithName:@"set"];
//    [set addAttributeWithName:@"xmlns" stringValue:@"http://jabber.org/protocol/muc"];
//    
//    [retrieve addChild:set];
//    [iQ addChild:retrieve];
//    
//    [xmppStream sendElement:iQ];




}

- (void)xmppRoom:(XMPPRoom *)sender didFetchConfigurationForm:(NSXMLElement *)configForm
{
    DDLogInfo(@"%@: %@", THIS_FILE, THIS_METHOD);

    NSXMLElement *newConfig = [configForm copy];
    NSArray *fields = [newConfig elementsForName:@"field"];

    for (NSXMLElement *field in fields)
    {
        NSString *var = [field attributeStringValueForName:@"var"];

        // Make Room Persistent
        if ([var isEqualToString:@"muc#roomconfig_persistentroom"])
        {

            [field removeChildAtIndex:0];
            [field addChild:[NSXMLElement elementWithName:@"value" stringValue:@"1"]];
        }

        if ([var isEqualToString:@"roomconfig_enablelogging"])
        {

            [field removeChildAtIndex:0];
            [field addChild:[NSXMLElement elementWithName:@"value" stringValue:@"1"]];
        }

        if ([var isEqualToString:@"muc#roomconfig_maxusers"])
        {

            [field removeChildAtIndex:0];
            [field addChild:[NSXMLElement elementWithName:@"value" stringValue:@"100"]];
        }


    }
    //    [sender configureRoomUsingOptions:newConfig];
}

/**
 This fuction is used to destroy created room
 */
- (void) destroyCreatedRoom
{
    [xmppRoom destroyRoom];

}


- (BOOL)sendGroupMessageWithBody:(NSString*)_body
{

    [xmppRoom sendMessageWithBody:_body];
    return YES;
}


@end

实际问题是我在创建房间后更改房间的主题。删除更改房间主题的代码后,它开始正常工作。这是我使用的代码 -

-(XMPPRoom *)createRoom:(XMPPJID *)roomJid withSubject:(NSString*)subject{
    XMPPRoomMemoryStorage *roomStorage = [[XMPPRoomMemoryStorage alloc]init];
    XMPPRoom *xmppRoom = [[XMPPRoom alloc] initWithRoomStorage:roomStorage
                                                           jid:roomJid
                                                 dispatchQueue:dispatch_get_main_queue()];

    [xmppRoom activate:self.xmppStream];
    [xmppRoom addDelegate:self delegateQueue:dispatch_get_main_queue()];
//    if(subject){
//        [xmppRoom changeRoomSubject:subject];
//    }
    return xmppRoom;
}
-(GroupCore *)createRoomAndGroup:(XMPPJID *)roomJid withSubject:(NSString*)subject{
    XMPPRoom* xmppRoom = [self createRoom:roomJid withSubject:subject];
    GroupCore* group = [appDelegate.coreDataController addGroup:xmppRoom withOptions:CreateOnly];
    if(!xmppRoom.roomSubject){
        group.name = subject;
    }
    //[appDelegate saveContext];
//    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 5 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
//        [group joinRoom];
//    });
    return group;
}