Section 10.1. Ruby


10.1. Ruby

At publication time, the current version of the Ruby DNS Service Discovery (DNS-SD) interface is 0.6.0. If you use RubyGems to install and manage your Ruby libraries, then you can install Ruby DNS-SD by typing:

 sudo gem install dndsd

If you don't use RubyGems, you can get Ruby DNS-SD by downloading the dnssd-0_6_0.tar.gz file from http://rubyforge.org/projects/dnssd/ and running the three commands shown in the README file:

 ruby setup.rb config ruby setup.rb setup ruby setup.rb install 

In future versions of OS X and other operating systems, it may come preinstalled by default. You can tell if it's already preinstalled with the following command:

 ruby -e "require 'dnssd'"

If there's no error message, then you have the Ruby dnssd package already installed. If it prints "No such file to load...," you will need to install it. Once you have the Ruby DNS-SD API installed, you can experiment with registering, browsing, and resolving from a Ruby program.

10.1.1. Registering a Service in Ruby

The Ruby code to advertise a service is just a few lines:

 require 'dnssd' registration = DNSSD.register("", "_http._tcp", nil, 8080) do |register_reply|   puts "Registration result: #{register_reply.inspect}" end puts "Registration started" sleep 30 registration.stop puts "Registration stopped" 

This code:

  • Tells the Ruby language interpreter that it requires the dnssd package

  • Registers a pretend service of type _http._tcp using the computer's default service name

  • Prints out the advertised name when the service is successfully registered

  • Waits for 30 seconds, then stops the registration and exits

If you save this file as register.rb and run it, you should see something like this:

 % ruby register.rb Registration started Registration result: #<DNSSD::RegisterReply Stuart\032Cheshire's\032PowerBook\ 032G4._http._tcp.local.> Registration stopping 

If you're new to Ruby, some explanation is called for. Ruby supports code blocks as first-class entities, much like integers or strings in other languages. The block of code from do to end is not equivalent to a similar block of code enclosed within curly braces in C. In C, lines of code in a routine execute more or less sequentially. The body of an if or for statement enclosed within curly braces may be executed zero, one, or more times, but it's always executed before the lines that appear later in the routine. In Ruby , the block of code from do to end is actually a parameter passed to the DNSSD.register( ) routine. It doesn't execute at all until DNSSD.register( ) decides it's time to execute it, asynchronously, on an automatically created background thread. If you save the program above as register.rb and then run it by typing ruby register.rb, you'll see that it prints the "Registration started" message before the "Registration result..." message.

Following the "do" keyword, you'll see an identifier enclosed between a pair of vertical bar symbols (the same character as the Unix "pipe" symbol), which names the parameter that is passed to the code block when it executes, rather like the parameter list enclosed in parentheses when you declare a C function.

In some ways, a Ruby code block is somewhat similar to passing a function pointer in a C programthere's some code to execute and a parameter that's passed to that codebut there's one important difference. A Ruby code block is what computer scientists call a closure. It's not just the code but also its environment. Similar to the way the body of an if or for statement may access local variables declared in the enclosing function, the Ruby code block passed to DNSSD.register( ) may access local variables declared in the enclosing function, even though the code block might not even get to execute until after the function that created it has exited. The Ruby interpreter knows that there's a code block that has access to those local variables and makes sure that they continue to remain valid even after the function that declared them has exited.

If you want to register a service with TXT record attributes, Ruby DNS-SD supports that too. The full signature of the DNSSD.register( ) function is as shown here:

 DNSSD.register(name, type, domain, port,    text_record=nil, flags=0, interface=DNSSD::InterfaceAny) {|reply| block } 

Ruby supports automatic default values for unspecified parameters. In this example, we didn't specify anything for text_record, flags or interface, so they automatically got the default values nil, 0, and DNSSD::InterfaceAny. If you want to register a service with TXT record attributes, you just need to pass a hash (key/value) or a string in the proper format for the text_record parameter.

10.1.2. Browsing for Services in Ruby

The general structure of the Ruby code to browse for services follows the same outline as the code to register a service:

 require 'dnssd' browser = DNSSD.browse('_http._tcp') do |browse_reply|   if (browse_reply.flags.to_i & DNSSD::Flags::Add) != 0     puts "Add: #{browse_reply.inspect}"   else     puts "Rmv: #{browse_reply.inspect}"   end end puts "Browsing started" sleep 30 browser.stop puts "Browsing stopped" 

If you save this file as browse.rb and run it, you should see something like this:

 % ruby browse.rb Browsing started Add: #<DNSSD:: BrowseReply Stuart\032Cheshire's\032PowerBook\032G4._ http._tcp.local. interface:lo0> Browsing stopping 

10.1.3. Resolving a Service in Ruby

When you've browsed to discover available services, and the user has picked one, the next step is to resolve the named service to its target host and port number:

 require 'dnssd' name = ARGV.shift puts "Resolving: #{name}" resolver = DNSSD.resolve(name, "_http._tcp", "local") do |resolve_reply|   puts "Resolve result: #{resolve_reply.inspect}" end puts "Resolver started" sleep 30 resolver.stop puts "Resolver stopped" 

If you save this file as resolve.rb and run it, you should see something like this:

 % ruby resolve.rb "Stuart Cheshire's PowerBook G4" Resolving: Stuart Cheshire's PowerBook G4 Resolver started Resolve result: #<DNSSD::ResolveReply Stuart\032Cheshire's\032PowerBook\032G4. _http._tcp.local. interface:en0 target:chesh7.local.:123> Resolver stopped 

In a real program, you'd take the resolve results you get and use them to initiate connections, and as soon as one succeeds, you'd then cancel the ongoing resolve operation.




Zero Configuration Networking. The Definitive Guide
Zero Configuration Networking: The Definitive Guide
ISBN: 0596101007
EAN: 2147483647
Year: 2004
Pages: 97

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net