Section 10.2. Python


10.2. Python

Python programmers can access DNS-SD functionality via the SWIG interface definition created by Tom Uram, Argonne National Laboratory. At time of writing, you can get it from http://www.mcs.anl.gov/fl/research/accessgrid/bonjour-py/bonjour-py.html or from the link on the DNS-SD web site http://www.dns-sd.org/. All of these examples are included in the bonjour-py package, along with a more involved example: a graphical service browser built using the wxPython GUI toolkit. To build the Python interfaces using SWIG, you'll need to have SWIG installed; you can get that from http://sourceforge.net/projects/swig/.

10.2.1. Registering a Service in Python

The Python code to advertise a service is a little longer than the Ruby code, but it's still quite simple:

 import sys import time import select import socket import bonjour # Callback for service registration  def RegisterCallback(sdRef, flags, errorCode, name, regtype, domain, context):     print "Service registered:", name, regtype, domain if len(sys.argv) < 4:     print "Usage: register.py servicename regtype port"     sys.exit(1) servicename = sys.argv[1] regtype = sys.argv[2] port = int(sys.argv[3]) # Allocate a service discovery reference and register the specified service flags = 0 interfaceIndex = 0 domain = '' host = '' txtLen = 0 txtRecord = '' userdata = None serviceRef = bonjour.AllocateDNSServiceRef(  ) ret = bonjour.pyDNSServiceRegister(serviceRef,                                    flags,                                    interfaceIndex,                                    servicename,                                    regtype,                                    domain,                                    host,                                    port,                                    txtLen,                                    txtRecord,                                    RegisterCallback,                                    userdata) if ret != bonjour.kDNSServiceErr_NoError:     print "error %d returned; exiting" % ret     sys.exit(ret) # Get the socket and loop fd = bonjour.DNSServiceRefSockFD(serviceRef) while 1:     ret = select.select([fd], [], [])     ret = bonjour.DNSServiceProcessResult(serviceRef) # Deallocate the service discovery ref bonjour.DNSServiceRefDeallocate(serviceRef) 

This code:

  • Defines the callback function to be invoked when the registration succeeds

  • Calls bonjour.pyDNSServiceRegister to register the service

  • Accesses the serviceRef's file descriptor, adding it to a select( ) set and calling bonjour.DNSServiceProcessResult( ) each time data arrives on that socket

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

 % python register.py "" _http._tcp 123 Service registered: Stuart Cheshire's PowerBook G4 _http._tcp. local. 

In this case, we're just using an empty string name to advertise the service using the system default name, but as with the other APIs, if you want something else you can specify an explicit name instead.

10.2.2. Browsing for Services in Python

It should be little surprise by now to see that the outline of the browsing code looks a lot like the service registration code:

 import sys import select import bonjour # Callback for service browsing def BrowseCallback(sdRef, flags, interfaceIndex,     errorCode, serviceName, regtype, replyDomain, userdata):     if flags & bonjour.kDNSServiceFlagsAdd:         print "Service added:   ", serviceName, regtype, replyDomain, interfaceIndex     else:         print "Service removed: ", serviceName, regtype, replyDomain, interfaceIndex if len(sys.argv) < 2:     print "Usage: browse.py regtype"     sys.exit(1) regtype = sys.argv[1] # Allocate a service discovery ref and browse for the specified service type flags = 0 interfaceIndex = 0 domain = '' userdata = None serviceRef = bonjour.AllocateDNSServiceRef(  ) ret = bonjour.pyDNSServiceBrowse(serviceRef,                                     flags,                                     interfaceIndex,                                     regtype,                                     domain,                                     BrowseCallback,                                     userdata) if ret != bonjour.kDNSServiceErr_NoError:     print "ret = %d; exiting" % ret     sys.exit(1) # Get socket descriptor and loop fd = bonjour.DNSServiceRefSockFD(serviceRef) while 1:     ret = select.select([fd], [], [])     ret = bonjour.DNSServiceProcessResult(serviceRef) # Deallocate the service discovery ref bonjour.DNSServiceRefDeallocate(serviceRef) 

This code:

  • Defines the callback function to be invoked when results are found

  • Calls bonjour.pyDNSServiceBrowse to start the browse operation running

  • Accesses the serviceRef's file descriptor, adding it to a select( ) set and calling bonjour.DNSServiceProcessResult( ) each time data arrives on that socket

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

 % python browse.py _http._tcp Service added:    Stuart Cheshire's PowerBook G4 _http._tcp. local. 4 

This browse operation will run indefinitely, reporting as services come and go, until you press Ctrl-C to stop it.

10.2.3. Resolving a Service in Python

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:

 iimport sys import select import bonjour # Callback for service resolving def ResolveCallback(sdRef, flags, interfaceIndex,                     errorCode, fullname, hosttarget,                     port, txtLen, txtRecord, userdata):     print "Service:", fullname     print "is at", hosttarget, ":", port if len(sys.argv) < 4:     print "Usage: resolve.py serviceName serviceType serviceDomain"     sys.exit(1) serviceName   = sys.argv[1] serviceType   = sys.argv[2] serviceDomain = sys.argv[3] # Allocate a service discovery ref and resolve the named service flags = 0 interfaceIndex = 0 userdata = None serviceRef = bonjour.AllocateDNSServiceRef(  ) ret = bonjour.pyDNSServiceResolve(serviceRef,                                   flags,                                   interfaceIndex,                                   serviceName,                                   serviceType,                                   serviceDomain,                                   ResolveCallback,                                   userdata); if ret != bonjour.kDNSServiceErr_NoError:     print "ret = %d; exiting" % ret     sys.exit(1) # Get socket descriptor and loop fd = bonjour.DNSServiceRefSockFD(serviceRef) while 1:     ret = select.select([fd], [], [])     ret = bonjour.DNSServiceProcessResult(serviceRef) # Deallocate the service discovery ref bonjour.DNSServiceRefDeallocate(serviceRef) 

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

 % python resolve.py "Stuart Cheshire's PowerBook G4" _http._tcp. local. Service: Stuart\032Cheshire's\032PowerBook\032G4._http._tcp.local. is at chesh7.local. : 123 

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