ONJava.com -- The Independent Source for Enterprise Java
oreilly.comSafari Books Online.Conferences.

advertisement

AddThis Social Bookmark Button

Zero Configuration Networking: Using the Java APIs, Part 1
Pages: 1, 2, 3, 4, 5

Complete TestRegister program listing

Example 8-1 shows a complete listing, which you can compile with javac, to advertise a named service using DNS-SD. This program uses new ServerSocket(0); to get a unique port number assigned by the system so that it can advertise it via DNS-SD, but it does not include code to actually provide any real service on this port. In this example, the program just waits for 30 seconds doing nothing, then calls b.stop( ) and exits.

Example 8-1. Java program to advertise a named service using DNS-SD
import java.net.*;
import com.apple.dnssd.*;

class TestRegister implements RegisterListener
  {
  // Display error message on failure
  public void operationFailed(DNSSDService service, int errorCode)
    {
    System.out.println("Registration failed " + errorCode);
    }

  // Display registered name on success
  public void serviceRegistered(DNSSDRegistration registration, int flags,
    String serviceName, String regType, String domain)
    {
    System.out.println("Registered Name  : " + serviceName);
    System.out.println("           Type  : " + regType);
    System.out.println("           Domain: " + domain);
    }

  // Do the registration
  public TestRegister(String name, int port)
    throws DNSSDException, InterruptedException
    {
    System.out.println("Registration Starting");
    System.out.println("Requested Name: " + name);
    System.out.println("          Port: " + port);
    DNSSDRegistration r = DNSSD.register(name, "_example._tcp", port, this);
    Thread.sleep(30000);  // Wait thirty seconds, then exit
    System.out.println("Registration Stopping");
    r.stop(  );
    }

  public static void main(String[] args)
    {
    if (args.length > 1)
      {
      System.out.println("Usage: java TestRegister name");
      System.exit(-1);
      }
    else
      {
      try
        {
        // If name specified, use it, else use default name
        String name = (args.length > 0) ? args[0] : null;
        // Let system allocate us an available port to listen on
        ServerSocket s = new ServerSocket(0);
        new TestRegister(name, s.getLocalPort(  ));
        }
      catch(Exception e)
        {
        e.printStackTrace(  );
        System.exit(-1);
        }
      }
    }
  }

Testing the registration program

The easiest way to verify that the program successfully registers a service is to start up dns-sd and start browsing for services of type _example._tcp using the command:

% dns-sd -B _example._tcp
Browsing for _example._tcp

Open a separate terminal window and compile TestRegister.java:

% javac TestRegister.java

Now you can run the TestRegister program by executing:

% java TestRegister "My Chosen Name"
Registration Starting
Requested Name: My Chosen Name
          Port: 51619

After a one-second pause, when it has confirmed that the name is indeed unique, it also prints:

Registered Name  : My Chosen Name
           Type  : _example._tcp.
           Domain: local.

In the first terminal window, where you are running dns-sd, you will now see that "My Chosen Name" appears. After 30 seconds, the program will display "Registration Stopping" and exit, and in the dns-sd window you should see a remove event as the named service goes away.

With our TestRegister program, we can also demonstrate name conflict detection and automatic renaming. Run the TestRegister program again in the second terminal window and, while it is still running, quickly open a third terminal window and run the same command again:

% java TestRegister "My Chosen Name"
Registration Starting
Requested Name: My Chosen Name
          Port: 51625
Registered Name  : My Chosen Name (2)
           Type  : _example._tcp.
           Domain: local.

This time you'll see that, because the name "My Chosen Name" was already in use for a different advertised service, the second instance was automatically renamed to "My Chosen Name (2)."

One detail worth noting here is that a conflict is detected because we have two different instances of our program running, listening on different ports. Two different instances of a service can't use the same name; when browsing, the user would see only one service instance instead of two, and one or the other service would be rendered inaccessible. However, if instead of having two different instances on different ports, we had just one service instance running, listening on one port, and we simply registered that service twice with the exact same parameters—same name, same type, same host, and same port—then no conflict would be reported. Registering the same service twice is arguably a programming error, but it's not a conflict because the two registrations are in complete agreement. The API permits duplicate registrations like this to allow for proxy servers where (perhaps for fault-tolerance reasons) a given service may be deliberately advertised by multiple proxies.

This simple example highlighted the code you need to write to register an instance of a service in a Java application. What you have done is advertised that a named service of a particular type is available on this machine at the specified port. You have not set up the code to listen on that port or to react when your service is contacted. The section "An Extended Example: Tic-Tac-Toe" at the end of this chapter will take you through this additional step.

Daniel H. Steinberg is the editor for the new series of Mac Developer titles for the Pragmatic Programmers. He writes feature articles for Apple's ADC web site and is a regular contributor to Mac Devcenter. He has presented at Apple's Worldwide Developer Conference, MacWorld, MacHack and other Mac developer conferences.

Stuart Cheshire is currently a Senior Scientist with Apple Computer, specializing in Internet Protocols.


View catalog information for Zero Configuration Networking: The Definitive Guide

Return to ONJava.com.