iPhone平台下基于XMPP的IM研究

       空闲之余,看了下iphone平台下xmpp的使用。我是个懒人不喜欢重复发明轮子,也许这也就是为什么我写的代码难登大雅之堂的原因吧,呵呵!

      XmppFramework 是一个开源项目,使用Objective-C实现了XMPP协议,它和前面所说的smack使用起来一样的方便,不过官网上提供的资料远不及smack。

     源码地址:http://code.google.com/p/xmppframework/,目前需要使用git才能download到源码,。

   

    PC客户端使用Spark,不知是否是我的黑苹果原因,spark装上不能运行(郁闷中...)

    服务器使用Openfire

    数据库我使用还是MySQL

    怎样将XMPPFramework添加到我们自己的项目中,请参考http://kongkongbrain.blog.163.com/blog/static/17819901320114235295322/,感谢这位兄弟,因为网上关于这个框架的使用文章太少了。

     代码步骤:

1、初始化XMPPStream 

xmppStream = [[XMPPStream alloc] init];

xmppStream.hostName = @"127.0.0.1";

xmppStream.hostPort = 5222;

[xmppStreamaddDelegate:selfdelegateQueue:dispatch_get_main_queue()];

XmppFramework的消息监听方式使用delegate。在smack中我们使用的是listener,其实都一样。


2、设置JID;(注意JID的Domain一定要用主机名,不要用IP地址。我的疏忽让我晚上熬到了3点多)

xmppStream.myJID = [XMPPJID jidWithString:[NSString stringWithFormat:@"%@@liu-lavymatoMacBook-Pro.local",myJID]];

3、连接服务器

NSError *error = nil;

[xmppStream connect:&error];

接下来就是一系列依次调用delegate的方法

xmppStreamWillConnect

socketDidConnect

xmppStreamDidConnect 在这个方法中我们需要调用:         [xmppStreamauthenticateWithPassword:myPassworderror:&error]

验证成功:xmppStreamDidAuthenticate:

验证失败:xmppStream: didNotAuthenticate:


//
//  XmppTest1AppDelegate.h
//  XmppTest1
//
//  Created by liu lavy on 11-10-2.
//  Copyright 2011 __MyCompanyName__. All rights reserved.
//

#import <UIKit/UIKit.h>
#import "XMPPFramework.h"

@class XmppTest1ViewController;

@interface XmppTest1AppDelegate : NSObject <UIApplicationDelegate, XMPPRosterDelegate> {
    UIWindow *window;
    XmppTest1ViewController *viewController;
	XMPPStream *xmppStream;
	XMPPReconnect *xmppReconnect;
	NSString *myPassword;
}

@property (nonatomic, retain) IBOutlet UIWindow *window;
@property (nonatomic, retain) IBOutlet XmppTest1ViewController *viewController;

@property (nonatomic, retain) XMPPStream *xmppStream;
@property (nonatomic, readonly) XMPPReconnect *xmppReconnect;
@property (nonatomic, retain) NSString *myPassword;


-(BOOL) connect:(NSString *)myJID password:(NSString *)myPassword;
-(BOOL) authenticate;
-(void) disConnect;
@end


//
//  XmppTest1AppDelegate.m
//  XmppTest1
//
//  Created by liu lavy on 11-10-2.
//  Copyright 2011 __MyCompanyName__. All rights reserved.
//

#import "XmppTest1AppDelegate.h"
#import "XmppTest1ViewController.h"
#import "DDLog.h"
#import "DDTTYLogger.h"

#if DEBUG
static const int ddLogLevel = LOG_LEVEL_VERBOSE;
#else
static const int ddLogLevel = LOG_LEVEL_VERBOSE;
#endif

@interface XmppTest1AppDelegate(PrivateMethod)
-(void) setupStream;
-(void) teardownStream;
@end

@implementation XmppTest1AppDelegate

@synthesize window;
@synthesize viewController;
@synthesize xmppStream;
@synthesize xmppReconnect;
@synthesize myPassword;

#pragma mark -
#pragma mark Application lifecycle

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {    
    [DDLog addLogger:[DDTTYLogger sharedInstance]];

    self.window.rootViewController = self.viewController;
    [self.window makeKeyAndVisible];
	
	[self setupStream];
    return YES;
}

-(void) setupStream {
	NSAssert(xmppStream == nil, @"Method setupStream invoked multiple times");
	xmppStream = [[XMPPStream alloc] init];
	xmppReconnect = [[XMPPReconnect alloc] init];
	[xmppReconnect activate:xmppStream];
	
	[xmppStream addDelegate:self delegateQueue:dispatch_get_main_queue()];
	[xmppReconnect addDelegate:self delegateQueue:dispatch_get_main_queue()];
	
	xmppStream.hostName = @"127.0.0.1";
	xmppStream.hostPort = 5222;
}

-(void) teardownStream {
	[xmppStream removeDelegate:self];
	[xmppReconnect deactivate];
	[xmppStream disconnect];
	xmppStream = nil;
	xmppReconnect = nil;
}

-(BOOL) connect:(NSString *)myJID password:(NSString *)password {
	if([xmppStream isConnected]) {
		[self disConnect];
	}
	self.myPassword = password;
	if(!myPassword|| [myPassword length] == 0) {
		UIAlertView *alertViewValidate = [[UIAlertView alloc] initWithTitle:@"连接失败" 
																	message:@"密码不能为空" 
																   delegate:nil
														  cancelButtonTitle:@"OK" 
														  otherButtonTitles:nil];
		[alertViewValidate show];
		[alertViewValidate release];
		return NO;
	}
	
	NSError *error = nil;
	XMPPJID *myXmppJID = [XMPPJID jidWithString:[NSString stringWithFormat:@"%@@liu-lavymatoMacBook-Pro.local",myJID]];
	//XMPPJID *myXmppJID = [XMPPJID jidWithString:@"test1@liu-lavymatoMacBook-Pro.local"];
	xmppStream.myJID = myXmppJID;
	//NSLog(@"%@", [NSString stringWithFormat:@"%d",[xmppStream connect:&error]]);
	if(![xmppStream connect:&error]) {
		UIAlertView *alertViewFailedConn = [[UIAlertView alloc] initWithTitle:@"连接失败" 
																	  message:@"详细请查看控制台" 
																	 delegate:nil
															cancelButtonTitle:@"OK"
															otherButtonTitles:nil];
		[alertViewFailedConn show];
		[alertViewFailedConn release];
		DDLogError(@"Error connecting: %@", error);
		return NO;
	}
	DDLogVerbose(@"连接成功");
	return YES;
}

-(BOOL) authenticate {
	return YES;
}

-(void) disConnect {
	XMPPPresence *presence = [XMPPPresence presenceWithType:@"unavailable"];
	[[self xmppStream] sendElement:presence];
	[xmppStream disconnect];
}

#pragma mark XMPPStream Delegate

- (void)xmppStreamWillConnect:(XMPPStream *)sender {
	DDLogVerbose(@"%@: %@", THIS_FILE, THIS_METHOD);
}

- (void)xmppStream:(XMPPStream *)sender socketDidConnect:(GCDAsyncSocket *)socket  {
	DDLogVerbose(@"%@: %@", THIS_FILE, THIS_METHOD);
}

- (void)xmppStreamDidConnect:(XMPPStream *)sender {
	DDLogVerbose(@"%@: %@", THIS_FILE, THIS_METHOD);
	DDLogVerbose(@"jid is %@@%@, password is %@", xmppStream.myJID.user, xmppStream.myJID.domain, myPassword);
	NSError *error;
	if(![xmppStream authenticateWithPassword:myPassword error:&error]) {
		UIAlertView *alertViewFailedConn = [[UIAlertView alloc] initWithTitle:@"验证失败" 
																	  message:@"详细请查看控制台" 
																	 delegate:nil
															cancelButtonTitle:@"OK"
															otherButtonTitles:nil];
		[alertViewFailedConn show];
		[alertViewFailedConn release];
		DDLogError(@"Error authenticating: %@", error);
		return;
	}
}

- (void)xmppStreamDidAuthenticate:(XMPPStream *)sender {
	DDLogVerbose(@"%@: %@", THIS_FILE, THIS_METHOD);
	XMPPPresence *presence = [XMPPPresence presence];
	[xmppStream sendElement:presence];
}

- (void)xmppStream:(XMPPStream *)sender didNotAuthenticate:(NSXMLElement *)error{
	DDLogVerbose(@"%@: %@", xmppStream.myJID.user, xmppStream.myJID.domain);
}

- (void)xmppStream:(XMPPStream *)sender didReceiveError:(id)error
{
	DDLogVerbose(@"%@: %@", THIS_FILE, THIS_METHOD);
}

- (void)xmppStreamDidSecure:(XMPPStream *)sender {
	DDLogVerbose(@"%@: %@", THIS_FILE, THIS_METHOD);
}

- (void)xmppStream:(XMPPStream *)sender willSecureWithSettings:(NSMutableDictionary *)settings {
	DDLogVerbose(@"%@: %@", THIS_FILE, THIS_METHOD);
	//[settings setObject:[NSNumber numberWithBool:YES] forKey:(NSString *)kCFStreamSSLAllowsAnyRoot];
	//[settings setObject:[NSNull null] forKey:(NSString *)kCFStreamSSLLevel];
	NSString *expectedCertName = nil;
	
	NSString *serverDomain = xmppStream.hostName;
	NSString *virtualDomain = [xmppStream.myJID domain];
	
	if ([serverDomain isEqualToString:@"talk.google.com"])
	{
		if ([virtualDomain isEqualToString:@"gmail.com"])
		{
			expectedCertName = virtualDomain;
		}
		else
		{
			expectedCertName = serverDomain;
		}
	}
	else if (serverDomain == nil)
	{
		expectedCertName = virtualDomain;
	}
	else
	{
		expectedCertName = serverDomain;
	}
	
	if (expectedCertName)
	{
		[settings setObject:expectedCertName forKey:(NSString *)kCFStreamSSLPeerName];
	}
}

- (void)xmppStream:(XMPPStream *)sender didReceiveMessage:(XMPPMessage *)message {
	
}

- (void)xmppStreamDidDisconnect:(XMPPStream *)sender withError:(NSError *)error {
	DDLogVerbose(@"%@: %@", THIS_FILE, THIS_METHOD);
	
	//if (!isXmppConnected) {
//		DDLogError(@"Unable to connect to server. Check xmppStream.hostName");
//	}
}

- (void)xmppStream:(XMPPStream *)sender didReceivePresence:(XMPPPresence *)presence {
	DDLogVerbose(@"%@: %@ - %@", THIS_FILE, THIS_METHOD, [presence fromStr]);
}

- (void)xmppRoster:(XMPPRoster *)sender didReceiveBuddyRequest:(XMPPPresence *)presence {
	
}

- (void)applicationWillResignActive:(UIApplication *)application {
    /*
     Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
     Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
     */
}


- (void)applicationDidEnterBackground:(UIApplication *)application {
    /*
     Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 
     If your application supports background execution, called instead of applicationWillTerminate: when the user quits.
     */
	DDLogVerbose(@"%@: %@", THIS_FILE, THIS_METHOD);
	
}


- (void)applicationWillEnterForeground:(UIApplication *)application {
    DDLogVerbose(@"%@: %@", THIS_FILE, THIS_METHOD);
}


- (void)applicationDidBecomeActive:(UIApplication *)application {
    /*
     Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
     */
}


- (void)applicationWillTerminate:(UIApplication *)application {
    /*
     Called when the application is about to terminate.
     See also applicationDidEnterBackground:.
     */
}


#pragma mark -
#pragma mark Memory management

- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application {
    /*
     Free up as much memory as possible by purging cached data objects that can be recreated (or reloaded from disk) later.
     */
}


- (void)dealloc {
	[self teardownStream];
	[xmppStream release];
	[xmppReconnect release];
	[myPassword release];
	
    [viewController release];
    [window release];
    [super dealloc];
}


@end


//
//  XmppTest1ViewController.h
//  XmppTest1
//
//  Created by liu lavy on 11-10-2.
//  Copyright 2011 __MyCompanyName__. All rights reserved.
//

#import <UIKit/UIKit.h>

@interface XmppTest1ViewController : UIViewController {
	UITextField *fieldJid;
	UITextField *fieldPwd;
}

@property (nonatomic, retain) IBOutlet UITextField *fieldJid;
@property (nonatomic, retain) IBOutlet UITextField *fieldPwd;

-(IBAction) login:(id)sender;
-(IBAction) textFieldDownEditing:(id)sender;
-(IBAction) backgroundTap:(id)sender;
@end


//
//  XmppTest1ViewController.m
//  XmppTest1
//
//  Created by liu lavy on 11-10-2.
//  Copyright 2011 __MyCompanyName__. All rights reserved.
//

#import "XmppTest1ViewController.h"
#import "XMPPFramework.h"
#import "DDLog.h"
#import "XmppTest1AppDelegate.h"

#if DEBUG
static const int ddLogLevel = LOG_LEVEL_VERBOSE;
#else
static const int ddLogLevel = LOG_LEVEL_INFO;
#endif


@implementation XmppTest1ViewController
@synthesize fieldJid;
@synthesize fieldPwd;
-(XmppTest1AppDelegate *) appDelegate {
	return (XmppTest1AppDelegate *)[[UIApplication sharedApplication] delegate];
}

-(IBAction) login:(id)sender {
	NSString *myJID = fieldJid.text;
	NSString *password = fieldPwd.text;
	if([[self appDelegate] connect:myJID password:password]) {
		
	}
}

-(IBAction) textFieldDownEditing:(id)sender {
	[sender resignFirstResponder];
}

-(IBAction) backgroundTap:(id)sender {
	[fieldJid resignFirstResponder];
	[fieldPwd resignFirstResponder];
}

/*
// The designated initializer. Override to perform setup that is required before the view is loaded.
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // Custom initialization
    }
    return self;
}
*/

/*
// Implement loadView to create a view hierarchy programmatically, without using a nib.
- (void)loadView {
}
*/



// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
		
}



/*
// Override to allow orientations other than the default portrait orientation.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
    // Return YES for supported orientations
    return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
*/

- (void)didReceiveMemoryWarning {
	// Releases the view if it doesn't have a superview.
    [super didReceiveMemoryWarning];
	
	// Release any cached data, images, etc that aren't in use.
}

- (void)viewDidUnload {
	fieldJid = nil;
	fieldPwd = nil;
	
}


- (void)dealloc {
	[fieldJid release];
	[fieldPwd release];
    [super dealloc];
}

@end

当然我也是看XMPPFramework里面的例子学习的,那是个好东西,下一步该学习怎样通过服务器发送消息了。



  • 0
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 17
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 17
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值