Question

I am looking for a way for clients in a LAN to find all the instances of my server application without any configuration. Instead of hacking something myself, I'd like to use an existing solution. Personally, I need it to be done in Python, but I'd happy to hear about solutions in any other language.

So why am I not using avahi or OpenSLP or some other Zeroconf/SLP solution? Well, there are a couple of additional criteria, and I'm under the impression neither of the aforementioned systems matches them.

I'm looking for a solution that is:

  • Flexible. It must not require superuser rights, i.e. only use ports>1024.
  • Solid. It must allow multiple services of the same and different service type on a single machine and continue advertising the services even when the instance that started the advertisement server stops or crashes.
  • Portable. It must run nearly everywhere, or at least on *BSD, Debian/gentoo/RedHat/SuSe Linux, Mac OS X, Solaris and Windows NT.
  • Light. Ideally, one Python script would be the whole solution. I'm not in the least interested in address autoconfiguration or something like that, although I'd begrudgingly accept a solution that has lots of features I don't need. Furthermore, any one-time setup is a strict no-no.

I expect something like this:

def registerService(service): # (type, port)
    if listen(multicast, someport):
        if fork() == child:
            services = [service]
            for q in queriesToMe():
                if q == DISCOVERY:
                    answer(filter(q.criteria, services))
                elif q == ADVERTISE and q.sender == "localhost":
                    services.append(q.service)
    else:
        advertiseAt("localhost", service)
Was it helpful?

Solution

I wrote an application/library (currently Python and CLI interface) that matches all these critera. It's called minusconf. Turns out forking is not even necessary.

OTHER TIPS

For node discovery in a LAN I've used Twisted and UDP Multicast. Hope it helps you too.

Link to the twisted documentation that explains how to do it: https://twistedmatrix.com/documents/current/core/howto/udp.html#auto3

Here is a basic implementation of a server/client based in the twisted's code. It answers itself if you run once, but all the checking code and extra features were removed in order to make it simpler to read.

from twisted.internet.protocol import DatagramProtocol
from twisted.internet import reactor

class MulticastPingPong(DatagramProtocol):
    MULTICAST_ADDR = ('228.0.0.5', 8005)
    CMD_PING = "PING"
    CMD_PONG = "PONG"

    def startProtocol(self):
        """
        Called after protocol has started listening.
        """
        # Set the TTL>1 so multicast will cross router hops:
        self.transport.setTTL(5)
        # Join a specific multicast group:
        self.transport.joinGroup(self.MULTICAST_ADDR[0])

        self.send_alive()

    def send_alive(self):
        """
        Sends a multicast signal asking for clients.
        The receivers will reply if they want to be found.
        """
        self.transport.write(self.CMD_PING, self.MULTICAST_ADDR)

    def datagramReceived(self, datagram, address):
        print "Datagram %s received from %s" % (repr(datagram), repr(address))

        if datagram.startswith(self.CMD_PING):
            # someone publishes itself, we reply that we are here
            self.transport.write(self.CMD_PONG, address)
        elif datagram.startswith(self.CMD_PONG):
            # someone reply to our publish message
            print "Got client: ", address[0], address[1]


if __name__ == '__main__':
    reactor.listenMulticast(8005, MulticastPingPong(), listenMultiple=True)
    reactor.run()

I assume you have control over the client apps, not just the server app, in which case Pyro might work well for you.

Flexible: uses non privileged ports.

Solid: It has been well maintained for many years.

Portable: pure Python and well tested on multiple platforms.

Light: I think Pyro is light for what you're getting. Maybe asking for one Python script is unrealistic for a network naming service?

Even if you don't want to actually use the "remote object" paradigm of Pyro, you still might be able to just use its naming service.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top