The World’s Leading Microsoft .NET Magazine
   
 
The .NET Addict's Blog

My Top Tags

                                                           

My RSS Feeds








Latest Diggs - Programming

Internet Blogs - Blog Top Sites

Site Hits

Total: 2,551,710
since: 19 Jan 2005

Leopard Code Sample : Sprinkling in some Bonjour

posted Tue 27 Nov 07

In my previous Leopard sample, I took a look at how to use the NSCollectionView to bind to a collection of items with a custom view rendered for each of the items. The main benefit of this control is that you get full animation capabilities, allowing new items added to the collection to fade in, to shuffle in, or whatever other kind of animation you want. Items removed from the collection also animate out.

In this update to the sample, I've decided that my monster compendium should be a collaborative application. As such, I want it to detect all nearby Dungeon Masters who are currently working on monster lists. To do this, I'm going to advertise the presence of my application on the local network with Bonjour. Note that with Leopard, I could advertise it globally as well. I noticed that when I used the empty string for my registration domain (instead of "local.", as you'll see in the code sample), my service actually registered with members.mac.com.

Here's a screenshot of the output of my application:

 

Couple of things to note. The "Nearby Dungeon Masters" list is bound to an array controller that contains a list of discovered services through Bonjour. Also, take a look at the Bonjour logo on the buttons. I didn't draw that, it's one of the any new icons that you can just pick from a dropdown list and have them appear anywhere in your application. This is fantastic because now you don't have to guess or approximate if you're trying to re-use something Apple has as a stock part of the OS.

There's two parts to being aware of other instances of your own application on a LAN. The first part is publishing the presence of your service (I'll consume the service through Distributed Objects in another code sample). The second part is browsing for, and discovering, other services.

To publish the existence of your own service, you can write some really simple code in a controller that looks like this:

 

- (IBAction)publishService:(id)sender

{

pubService = [[NSNetService alloc] initWithDomain:@"local." type:@"_moncom._tcp" name:[dmName stringValue] port:9000];

[pubService publish];

}


 

In the preceding sample, dmName is the text field that contains your own name (the Dungeon Master name). This name will be used as the name of the service when published so you can be quickly and easily identified. Other architectures often use some kind of unique ID as the service name, and you then have to connect to the service to obtain more information. Note the "_moncom._tcp" string. That's the service type. For more information on Bonjour (formerly Rendezvous) services, you can check out Apple's online documentation.

Now you're going to need to start browsing for services. Browsing is something that is a persistent activity. You create an instance of a browser and set the callback, and you will receive callbacks nearly immediately any time anything within your browse criteria takes place. You will be notified nearly immediately when new services of the type you're looking for appear, and when services of that type disappear. Here's the code I have to start my browser:

- (IBAction)startBrowsing:(id)sender

{

NSLog(@"Starting browse.");

browser = [[NSNetServiceBrowser alloc] init];

[browser setDelegate:self];

[browser searchForServicesOfType:@"_moncom._tcp." inDomain:@"local."];

} 

This is pretty simple code. This is an action on a class file I have created called BonjourBrowser. This class ha the method to start browsing, and is the delegate for browsing activities. An interesting quirk that I noticed is that I want to start browsing immediately upon awaking from the NIB. This way, I will detect nearby DMs as soon as the application starts up. To do that, I have the following code in my awakeFromNib: method:

 

- (void)awakeFromNib

{

  [bonjourBrowser performSelector:@selector(startBrowsing:) withObject:self afterDelay:0];

}

 

I was a little confused at first here. The issue is that if I just call startBrowsing: immediately during the NIB awakening, some aspect of Bonjour is not yet available to me, and I will be forever unable to detect services using that browser. However, if I use performSelector: to defer the call to the next event loop cycle, Bonjour has initialized itself and everybody's happy.

Finally, I want to show you the code that I have in the delegate for when a new service is detected. This code is responsible for adding the service into the array controller (which is the data-bound source for the "Nearby Dungeon Masters" NSTableView):

- (void)netServiceBrowser:(NSNetServiceBrowser *)aNetServiceBrowser

  didFindService:(NSNetService *)aNetService

  moreComing:(BOOL)moreComing

{

NSLog(@"Added net service %@", [aNetService name]);

[discoveredServices addObject:aNetService];

}

In the next code sample, I'll show you how to take the list of nearby Dungeon Masters and actually send a monster from your desktop application (created using Core Data) to a remote Dungeon Master using Distributed Objects and resolving remote service addresses through Bonjour.

I'll also post the full source code for this sample after the next blog post. 

tags:        

links: digg this    del.icio.us    technorati    reddit




1. Kevin Hoffman left...
Tue 27 Nov 07 9:30 am

I realize the screenshot completely sucks. I've made it so if you click the picture, you'll see the picture in it's full size, which is around 900 pixels wide. That's what I get for coding on a 17" Macbook Pro


2. John McLaughlin left...
Tue 27 Nov 07 4:18 pm :: http://loghound.com

Hi Kevin,

Thanks for posting these tutorials -- I find them really useful to cut through the clutter and just focus on what it takes to do something (such as this)

One point: I believe with Leopard wide area bonjour support is enabled -- It's hard to find a lot of details on it (or perhaps I haven't looked hard enough) but I believe it registered with members.mac.com in support of 'back to my mac' (e.g. if you had two computers with your .mac account they could share bonjour data).

There is supposedly a way to do wide area bonjour with folks like tz0.com and dyndns.com such that your app would actually 'register' itself as having a 'monster service' on the open internet so that friends who were not in your domain could find you (and I believe 10.5 also has support for an authentication framework so you could make sure it was just friends!) -- That would make a slick addition to bonjour (but sadly I just haven't been able to track down many details).

Anyway keep up the good work. -jm


3. Adam Thorsen left...
Fri 30 Nov 07 1:23 pm

I'm really looking forward to your next post. I haven't yet found any working examples of distributed objects.


4. Kevin Hoffman left...

Wide-Area Bonjour is enabled, and yes, my .mac Bonjour registration was part of that feature. I also agree that I believe there's some Bonjour magic making "Back to my Mac" possible. I have yet to delve into either of those very thoroughly, only just now exploring in any real detail the capabilities of Bonjour for LAN-based peer discovery.


Tag Related Posts

MobileMe vs. Live Mesh Throwdown - Round 1

Wed 16 Jul 08 10:33 A GMT-05

Building Model Classes in C# and Cocoa

Sun 15 Jun 08 3:13 P GMT-05
tags:            

MobileMe vs. Live Mesh - Round 1

Wed 11 Jun 08 12:20 A GMT-05

My Macbook Air is masculine, dammit!

Mon 17 Mar 08 6:59 P GMT-05
tags:          

iPhone Underrated as a Gaming Device?

Fri 14 Mar 08 1:50 P GMT-05
tags:        

My take on the iPhone SDK

Sat 08 Mar 08 1:39 P GMT-05

Jobs says "not likely" to Flash on the iPhone

Thu 06 Mar 08 1:39 A GMT-05
tags:          

My Macbook Air Review

Sun 02 Mar 08 4:20 P GMT-05

iPhone Roadmap March 6th

Fri 29 Feb 08 10:41 P GMT-05
tags:        

Video of the Macbook Air in Action

Wed 20 Feb 08 3:04 P GMT-05

Macbook Airはきれいですよ!

Sun 17 Feb 08 2:38 A GMT-05

Why is O'Reilly Condoning iPhone Hacking?

Mon 11 Feb 08 3:55 P GMT-05

Evaluating my next laptop purchase

Wed 06 Feb 08 8:40 P GMT-05

The iPhone SDK key has been leaked! Oh Noez!!!1

Tue 29 Jan 08 11:36 A GMT-05
tags:        

Why Geeks just don't "get" the Macbook Air

Thu 17 Jan 08 2:30 P GMT-05

Popcorn + TiVo + Macbook Pro + iPhone == Hell Yeah!

Tue 15 Jan 08 3:11 P GMT-05
tags:          

How my ADC membership changed my life

Mon 31 Dec 07 3:57 P GMT-05
tags:      

Leopard Code Sample : Sprinkling in some Bonjour

Tue 27 Nov 07 2:32 P GMT-05
tags:        

Leopard Sample: A Bound NSCollectionView

Mon 29 Oct 07 1:41 A GMT-05

My Leopard Installation Experience

Sun 28 Oct 07 12:57 P GMT-05
tags:    

Leopard is out - let the code samples begin!

Fri 26 Oct 07 10:09 A GMT-05
tags:          

My life is complete : iPhone SDK is CONFIRMED.

Wed 17 Oct 07 6:38 P GMT-05
tags:          

Leopard Shipping October 26th!!

Tue 16 Oct 07 4:59 P GMT-05
tags:        

My iPhone Review

Mon 23 Jul 07 1:09 P GMT-05
tags:        

Microsoft Codename Acropolis - Unwrapped

Wed 20 Jun 07 3:22 P GMT-05
tags:              

The dreaded language bleed-over has begun

Tue 19 Jun 07 6:23 P GMT-05
tags:        

My TiVo is using Bonjour...

Mon 18 Jun 07 12:57 A GMT-05
tags:    

Exploring the Delegate Design Pattern

Mon 14 May 07 6:30 P GMT-05

Core Data - Almost too Easy?

Wed 18 Apr 07 2:23 P GMT-05

Exploring the MVC Pattern in WPF

Tue 10 Apr 07 12:51 P GMT-05
tags:                      

An experience with the Leopard beta

Mon 26 Mar 07 7:45 P GMT-05
tags:                

WPF Bindings == WTF Bindings?

Mon 12 Mar 07 6:31 P GMT-05

Objective-C Categories vs C# 3.5 Language Extensions

Mon 26 Feb 07 1:05 P GMT-05
tags:                

Cocoa Programming vs. WPF : NIB vs XAML

Tue 20 Feb 07 2:09 P GMT-05

Cocoa Bindings vs. WPF Binding

Thu 15 Feb 07 5:41 P GMT-05
tags: