By now, with knowledge of the dns-sd command-line tool and the C API, the register/browse/resolve operations should be quite familiar. One difference to be aware of is that, whereas the DNSServiceDiscovery C API follows the established Berkeley Sockets convention that port numbers are always given in network byte order, the standard Java networking APIs use port numbers in host integer byte order, and the DNSServiceDiscovery Java API adheres to that established Java convention. Another difference you will notice is that the Java API has two register methods and two browse methods. Whereas the C API always requires you to pass the full set of parameters for any given call (passing zero or NULL to indicate default values), the Java API makes use of method overloading to provide variants. If you don't want to limit browsing to a particular interface, you're happy to let the system pick the domain(s) to browse, and you don't need to specify any special flags, then you can just leave out those parameters completely and use the simpler version of the browse( ) method.

These three methods provide access to some of the more specialized DNS-SD functionality: enumerating the list of wide-area domains recommended for this network, querying for a specific individual named DNS Resource Record Set (RRSet), and signaling to the daemon that you believe a particular DNS Resource Record in its cache may be stale and out of date. The way they work is exactly equivalent to their counterparts in the C API.

As a simple example, you can browse for a service of type _example._tcp from the command line using:

dns-sd -B _example._tcp

In a Java program, you can accomplish the same task using a call to DNSSD.browse, as shown in the example below, where myBrowseListener is an instance of a class that implements the BrowseListener interface:

DNSSDService b = DNSSD.browse("_example._tcp", myBrowseListener);

The result of the DNSSD.browse( ) call is a reference to the newly created DNSSDService object, which you need to keep so that you can call b.stop( ) when it's time to stop the ongoing operation. If you never call b.stop( ), then the asynchronous operation you've initiated will run forever, consuming network bandwidth, memory, and CPU time until your program eventually exits! Typically, a program would call DNSSD.browse( ) when a user brings up a window to browse the network, and call b.stop( ) when the user closes that window.

It is common for the object making the DNSSD.browse call to implement the BrowseListener interface itself, in which case, you would substitute this in place of myBrowseListener.

In addition to the classes detailed above, the DNSSD class contains the following utility methods:

DNS-SD uses structured service names, containing an instance name, a service type, and a domain. In the on-the-wire format used in DNS packets, the three components are concatenated into a single, fully qualified DNS name. If you need to mix and match the service-oriented DNS-SD APIs with conventional low-level DNS APIs, you'll need to know the right fully qualified DNS name to use for a particular service. The constructFullName( ) call builds the correct fully qualified DNS name from DNS-SD's serviceName, regtype, and domain. The name is also properly escaped according to the standard DNS conventions; for example, if the instance name contains a dot (.), then it will appear as (\.) in the escaped DNS name, as required by the standard DNS APIs.

On machines with multiple physical interfaces, DNS-SD allows you to optionally restrict registering, browsing, and resolving to a single physical interface. To do this, you pass an interface index value when making the API calls. Because Java has historically not provided APIs for working with interface indexes, the Java DNS-SD API provides a couple of helper functions, getIfIndexForName( ) and getNameForIfIndex( ), which convert from an interface name to its index value, and vice versa.

The DNSSD class also includes constants (of type public final static int) that are used in various places by the API. For example, when you register a service, if a different service of that type already exists with the same name, Multicast DNS will normally pick a new unique name for you automatically. If, instead, you would like the service registration to simply fail and signal an error so that you can write your own code to select a new name, then you would pass the flag value NO_AUTO_RENAME when calling DNSSD.register( ).