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 2
Pages: 1, 2, 3, 4, 5, 6

On the receiving side, to read records other than the standard SRV and TXT pair (which are retrieved using the resolve call), clients use DNSSD's queryRecord( ) method, providing a QueryListener object to receive the asynchronous results. A QueryListener object needs to implement the queryAnswered( ) method:


queryAnswered(DNSSDService query, int flags, int ifIndex,
  String fullName, int rrtype, int rrclass, byte[] rdata, int ttl)

Whenever an answer becomes available, the queryAnswered( ) method is called. Due to a quirk of the API, the queryAnswered( ) method is also called if a previously valid answer expires. You can tell if the answer is coming or going by checking bit 1 (value 2) of the flags field (the kDNSServiceFlagsAdd flag of the C API). If (flags & 2) is nonzero, then a new answer is being added; if zero, then a previous answer is being removed.

The queryAnswered( ) method is given the raw bytes of the DNS resource record; it is the responsibility of the queryAnswered( ) method to know how to interpret the DNS record type it requested.

There is another style of update that iChat performs. Your status message is stored as a key/value attribute in the service's TXT record, and whenever you update your status message, iChat doesn't de-register its service and register a new one; instead, it just updates the TXT record to contain the new data. To perform this kind of update, you don't need to add another TXT record to the service. All services implicitly have a TXT record, even if you didn't specify one. If you don't specify a TXT record when registering a service, then the service automatically gets an empty TXT record containing no key/value attributes. (Strictly speaking, to comply with the DNS rules for the format of DNS TXT records, the service gets a TXT record containing a single empty string.)

Before you can use the update method to provide new data, you need an object upon which to invoke that method. To get the object representing the service's standard TXT record, upon which to perform updates, the Java DNS-SD API provides the DNSSDRegistration.getTXTRecord( ) method. The update method requires you to provide properly formatted DNS TXT record data, and this is where the TXTRecord's getRawBytes( ) method comes in handy:


DNSRecord record = registration.getTXTRecord(  );
byte rawbytes[] = txtRecord.getRawBytes(  );
record.update(0, rawbytes, 0);

As with other DNS-SD methods, passing zero for the flags and zero for the record TTL causes sensible default values to be used.

Example 8-5 shows a complete listing that you can compile with javac, which first registers a service with the default empty TXT record, then at ten-second intervals updates the TXT record to say status=ready, status=steady, and finally, status=go. The change compared to Example 8-1 is indicated by the comment, "New code to update TXT record begins here."

Example 8-5. Java program to advertise a service and update its TXT record

import java.net.*;
import com.apple.dnssd.*;

class TestRegisterWithUpdates 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 TestRegisterWithUpdates(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);

    // New code to update TXT record begins here

    TXTRecord txtRecord = new TXTRecord(  );
    txtRecord.set("txtvers", "1");

    Thread.sleep(10000);  // Wait ten seconds before updating TXT record
    txtRecord.set("status", "Ready");
    System.out.println("Ready");
    r.getTXTRecord(  ).update(0, txtRecord.getRawBytes(  ), 0);

    Thread.sleep(5000);
    txtRecord.set("status", "Steady");
    System.out.println("Steady");
    r.getTXTRecord(  ).update(0, txtRecord.getRawBytes(  ), 0);

    Thread.sleep(5000);
    txtRecord.set("status", "Go");
    System.out.println("Go");
    r.getTXTRecord(  ).update(0, txtRecord.getRawBytes(  ), 0);

    // New code to update TXT record ends

    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 TestRegisterWithUpdates 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 TestRegisterWithUpdates(name, s.getLocalPort(  ));
        }
      catch (Exception e)
        {
        e.printStackTrace(  );
        System.exit(-1);
        }
      }
    }
  }

Pages: 1, 2, 3, 4, 5, 6

Next Pagearrow