jRendezvous: Java and Rendezvous Working Togetherby Seth Ladd
To Apple's credit, they design with the user in mind. This is true not only for their user interface components, but for the internals of their products as well. For instance, beginning with OS X 10.2 (Jaguar), even the networking experience is user friendly. With the introduction of Rendezvous, Apple has introduced the ease of use of AppleTalk to a standards compliant IP network.
While there are no standard development languages for Mac OS X, Java developers will feel right at home. The Java runtime and JDK are shipped and ready to run, allowing the vast amount of Java applications and applets to run natively on OS X. The Java "Write Once, Run Anywhere" promise continues to be press on.
With Rendezvous making IP networking simple, and Java making cross platform network programming possible, we see the possibility for a beautiful friendship. An implementation of Rendezvous for Java, called jRendezvous, now allows Java programs running anywhere (not just Mac OS X) to participate in Rendezvous networks. With jRendezvous, Java programs can listen for, and advertise, services on the network with ease.
With the release of Jaguar (OS X 10.2), Apple introduced Rendezvous, their branding of their Zeroconf implementation. Zeroconf is a set of IETF standards for a Zero Configuration IP network. A Zero Configuration network means two things. The network itself does not need to have a DHCP or DNS server installed for clients to use. Any client that connects to the network will obtain an IP address through standard negotiation protocols. A Zero Configuration network also means that clients can discover services on the network. For instance, a client does not need to be preconfigured with an IP address of a printer. Through Rendezvous's discovery mechanisms, the client will automatically become aware of all Rendezvous-enabled printers on the network. It is this second Rendezvous feature we will look at closely with jRendezvous.
There is already a great collection of Rendezvous and zeroconf information available. If you are unfamiliar with either, you might want to investigate these resources:
- IETF's Zeroconf Working Group
- Apple rendezvous and Zeroconf
- Apple Developer - Rendezvous
- DNS-Based Service Discovery
Specifying a Service
Much of what is discussed below concerns either listening for or advertising a service. While a service's implementation is orthogonal to Rendezvous, the way it is named is well specified. Before we look at the classes and interfaces of jRendezvous, it is important to understand Rendezvous's service naming. jRendezvous follows the standards specified in DNS-Based Service Discovery, so we will review them now.
Rendezvous services are specified with a Service Instance Name. It is constructed from three parts: an instance name, a service name, and a domain name.
The instance name is any arbitrary UTF-8 encoded text. It has a maximum of 63 octets. The text of the instance name can have any combination of characters, and usually distinguishes a service from others within its type.
A service name is specified with an application protocol name and a
transport protocol name. The protocol name must be registered with IANA's
assigned application port numbers. An example of an application
protocol name is
_http. The transport protocol value can
_udp. Notice the underscores
preceding the names, they are required.
The domain name is a standard DNS domain name. For instance, both "brivo.com" and "math.dept.university.example.edu" are valid here. Also valid is simply "foo.local.", which indicates a machine on the local link.
jRendezvous often uses what it calls a type name. It is a combination
of the service name and a domain name in the form of "local.".
A type name of
_http._tcp.local. would identify all instances
of HTTP servers running over TCP on the local link. The type name is
used when a service browser wishes to search for services of a particular
A fully qualified Service Instance Name is formed by combining all
name parts. An example Service Instance Name is
Server._http._tcp.local.. A Rendezvous Service advertisement
includes a server name with the service name. The server name tells
clients what machine is hosting the service. While this server name
resolves to a physical IP address, clients should never cache that
address. Rendezvous works so well because services may move around on
the network, even changing IP addresses. Clients should cache the
Service Instance Name instead, allowing the service the flexibility of
Warning: jRendezvous, at the time of this writing, has a bug regarding the server name of services. In fact, it doesn't support it at all. It assumes the service name is the same as a server name. This might be true for some situations, but for many, it is not a safe assumption. For instance, many different web services may be hosted on a single physical server. "Seth's Web Site" and "Justin's Web Site" are distinct services, but would be hard to tell apart if they had to be named "www". I have provided a patch for this, so don't worry.
jRendezvous is the work of Arthur van Hoff while at Strangeberry. Its current version, 0.1.2, supports service discovery and registration. It's available for download via Strangeberry's public FTP server (though the examples only work with my patched version, see below). jRendezvous is licensed under the LGPL. This makes it available for both proprietary and open software.
Because of the bug mentioned above, I strongly encourage you to download the patched version of the library. I have provided both the source and the compiled jar. The source and jar provided are considered patched to the full jRendezvous distribution from Strangeberry. The Strangeberry distribution has the license and javadocs. To get the full experience, please get the native package, and then the patched sources and jar.
Package, Class, and Interface Tour
Let's dive into the structure of jRendezvous. Luckily, there are both sample programs and tools built on jRendezvous. There is plenty of code to read to gain a deep understanding of this library.
From a user's perspective, there are three main classes that are
We will be looking at the
classes. With just these three classes, a Java program can both advertise
and discover services.
Rendezvous class is the main workhorse of the
To begin using this class, simply create an instance with the default
Rendezvous rendezvous = new Rendezvous();
There are three methods provided by the
we will look at.
public synchronized void addServiceListener(String type, ServiceListener listener)
public void requestServiceInfo(String type, String name)
public void registerService(ServiceInfo info)
addServiceListener is used to register a
to be notified of services arriving and leaving the network. The
requestServiceInfo method is used to obtain a full
ServiceInfo object encapsulating a service. And the
registerService method advertises a local service for the
network to discover.
To be notified of services on the network, create an implementation
interface and pass it to the
rendezvous instance using
addServiceListener method. You also need to specify
the type of the service you want the listener to listen for.
The callbacks from the
ServiceListener class include:
public void addService(Rendezvous rendezvous, String type, String name)
public void resolveService(Rendezvous rendezvous, String type, String name, ServiceInfo info
public void removeService(Rendezvous rendezvous, String type, String name)
addService method is called by the
object when a service is first discovered on the network. All that is
known at this point is the type and its instance name. To fully
resolve the service, use the
from the passed
rendezvous object. Once the service is
resolved and more information is known, the
resolveService method is called giving your listener a
ServiceInfo object. The
removeService callback is called when a service has been
removed from the network.
To see the
ServiceListener in action, there's a small
included in the jRendezvous download. The example class is
demonstrates a simple listener registered with a
Rendezvous object. Luckily, jRendezvous doesn't need any
other third party libraries on the classpath. To run this sample, use
the following command (assuming you have the java executable on the
path) from the directory where you unzipped the jRendezvous
java -cp jrendezvous.jar com.strangeberry.rendezvous.sample.SampleListener
The class, by default, listens for advertisements to the
type. If you have OS X's default Apache installation running, you should
see the users' home WWW directories being advertised. This is due to
the mod_rendezvous_apple Apache module bundled by Apple starting at
OS X 10.2.4. This example class outputs the Rendezvous network conversations
so you can watch and learn what is going on under the hood.
The final class we will look at is the
It's an encapsulation of a Service. The
will advertise a
ServiceInfo object to the network. Note
that an instance of the
ServiceInfo doesn't have to be
the same object as the service itself. The service's advertisement and
the service can be two separate things. It is more useful to have
their lifecycles connected, though. If the service leaves the network,
ServiceInfo object should cease to be advertised as
Remember the bug mentioned above? The native version of the class did not allow a server name to be declared. The following constructor is recommended and can only be found in the patched version.
public ServiceInfo(String type, String name, InetAddress interface,
int port, Hashtable props, String serverName)
To sum up the included Javadocs, this constructor creates a
object from a service type name, an instance name, the interface the
service is running on, the port the service is listening to, a hashtable
of service specific properties, and the hostname of the server where
the service lives. An example follows:
Hashtable props = new Hashtable(); props.put("path", "/index.html"); ServiceInfo info = new ServiceInfo( "_http._tcp.local.", "Seth's Web Site", InetAddress.getByName("foo.example.com"), 80, props, "foo.example.com");
The jRendezvous download provides
as a sample service registration to study. When run, it advertises a
local web server (that may or may not actually be there) on port 80.
Using the following command, you should see a "Hello, World"
web server in Safari's Rendezvous bookmarks. If a page is actually served
is dependent on a web server running on that port. This illustrates
the potential separation of the service advertisement from the service
java -cp jrendezvous.jar com.strangeberry.rendezvous.sample.SampleRegistration
Pages: 1, 2