Advertising & Discovering Network Services

Advertise and collect advertisements of network services

The discovery module offers:

  • A UDP broadcast socket which:
    • Listens for and keeps track of service adverts from this and other machines & processes
    • Broadcasts services advertised by this process
  • A ZeroMQ socket which allow any process on this machine to communicate with its broadcast socket

In other words, we have a beacon which listens to instructions from processes on this machine while sending out and listening to adverts broadcast to/from all machines on the network.

The beacon is started automatically in a daemon thread when the first attempt is made to advertise or discover. If another process already has a beacon running (ie if this beacon can’t bind to its port) this beacon thread will shut down with no further action.

The module-level functions to advertise and discover will open a connection to a ZeroMQ socket on this machine (which might be hosted by this or by another process) and will use this socket to send commands to the beacon thread which will update or return its internal list of advertised services.

As an additional convenience, the advertise() function will, if given no specific address, generate a suitable ip:port pair by interrogating the system. This functionality is actually in networkzero.address() (qv).

Introduction

The discovery module implements a UDP beacon in a daemon thread to advertise a directory of name-to-address mappings. The names are added to the directory via the advertise() function, and discovered via discover(). A list of all currently-advertised names can be obtained by calling discover_all().

When a name is advertised, if no address is supplied, one is generated by combining the first of the host’s IP addresses with a port randomly selected from the list of valid dynamic ports [0xC000 - 0xFFFF]. While the selected port is removed from the list for the purposes of the networkzero package, there’s a slim chance that it might be in use by some other process.

Functions

networkzero.discovery.advertise(name, address=None, fail_if_exists=False, ttl_s=20)

Advertise a name at an address

Start to advertise service name at address address. If the address is not supplied, one is constructed and this is returned by the function. ie this is a typical use:

address = nw0.advertise("myservice")
Parameters:
  • name – any text
  • address – either “ip:port” or None
  • fail_if_exists – fail if this name is already registered?
  • ttl_s – the advert will persist for this many seconds other beacons
Returns:

the address given or constructed

networkzero.discovery.discover(name, wait_for_s=60)

Discover a service by name

Look for an advert to a named service:

address = nw0.discover("myservice")
Parameters:
  • name – any text
  • wait_for_s – how many seconds to wait before giving up
Returns:

the address found or None

networkzero.discovery.discover_all()

Produce a list of all known services and their addresses

Ask for all known services as a list of 2-tuples: (name, address) This could, eg, be used to form a dictionary of services:

services = dict(nw0.discover_all())
Returns:a list of 2-tuples [(name, address), ...]
networkzero.discovery.discover_group(group, separator='/', exclude=None)

Produce a list of all services and their addresses in a group

A group is an optional form of namespace within the discovery mechanism. If an advertised name has the form <group><sep><name> it is deemed to belong to <group>. Note that the service’s name is still the full string <group><sep><name>. The group concept is simply for discovery and to assist differentiation, eg, in a classroom group.

Parameters:
  • group – the name of a group prefix
  • separator – the separator character [/]
  • exclude – an iterable of names to exclude (or None)
Returns:

a list of 2-tuples [(name, address), ...]