Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python service discovery: Advertise a service across a local network

I have a "server" python script running on one of the local network machines, which waits for clients to connect, and passes them some work to do. The server and client code have both been written, and are working as expected...

The problem is, this server might be running from any machine in the local network, so I can't hard code the address in the script... I immediately wondered if I can make a machine advertise about its existence, and clients can respond to that. Is that doable in Python with the standard library? I really don't have time to download twisted or tornado and learn about them, unfortunately, so I need something simple.

I tried to think more about it, and realized I can have a single static IP machine where servers register/unregister from and clients can look for servers from there. Kind of like a torrent tracker, I think. This'll have to do if I can't do the service advertising approach easily.

like image 321
Mazyod Avatar asked Jan 13 '14 10:01

Mazyod


1 Answers

An easy way to do service announcement/discovery on the local network is by broadcasting UDP packets.

Constants:

PORT = 50000
MAGIC = "fna349fn" #to make sure we don't confuse or get confused by other programs

Announcement:

from time import sleep
from socket import socket, AF_INET, SOCK_DGRAM, SOL_SOCKET, SO_BROADCAST, gethostbyname, gethostname

s = socket(AF_INET, SOCK_DGRAM) #create UDP socket
s.bind(('', 0))
s.setsockopt(SOL_SOCKET, SO_BROADCAST, 1) #this is a broadcast socket
my_ip= gethostbyname(gethostname()) #get our IP. Be careful if you have multiple network interfaces or IPs

while 1:
    data = MAGIC+my_ip
    s.sendto(data, ('<broadcast>', PORT))
    print "sent service announcement"
    sleep(5)

Discovery:

from socket import socket, AF_INET, SOCK_DGRAM

s = socket(AF_INET, SOCK_DGRAM) #create UDP socket
s.bind(('', PORT))

while 1:
    data, addr = s.recvfrom(1024) #wait for a packet
    if data.startswith(MAGIC):
        print "got service announcement from", data[len(MAGIC):]

This code was adapted from the demo on python.org

like image 175
loopbackbee Avatar answered Oct 13 '22 20:10

loopbackbee