Search code examples
pythonnetwork-programmingudppython-asyncio

What IP to use in order to perform a UDP broadcast?


I'm writing a very simple service discovery protocol over LAN. The idea is to broadcast to the entire LAN via UDP the connection data of the server.

I am able to pass data from my broadcaster to my listener, but only if I use the address '0.0.0.0'. If I use the local LAN address + .255 (the LAN broadcast address) I cannot send any message.

This is the code of my broadcast.py:

import asyncio
import asyncudp
from socket import gethostbyname, gethostname

def getBroadcastIp():
    ip = gethostbyname(gethostname())
    broadcast_ip = '.'.join(ip.split('.')[:-1]+["255"])
    print(broadcast_ip)
    # return broadcast_ip
    return '0.0.0.0'

async def broadcastUdp():
    bip = getBroadcastIp()
    while True:
        sock = await asyncudp.create_socket(remote_addr=(bip, 50000))
        print("Sending MESSAGE")
        sock.sendto(b'Message', addr=(bip, 50000))
        await asyncio.sleep(3)
        sock.close()

async def main():
    await asyncio.gather(*[
        # I have more stuff here
        asyncio.create_task(broadcastUdp())
    ])

asyncio.run(main())

and this is my listener.py:

import asyncio
import asyncudp
from socket import gethostbyname, gethostname

def getBroadcastIp():
    ip = gethostbyname(gethostname())
    broadcast_ip = '.'.join(ip.split('.')[:-1]+["255"])
    print(broadcast_ip)
    # return broadcast_ip
    return '0.0.0.0'

async def listenUdp():
    bip = getBroadcastIp()
    sock = await asyncudp.create_socket(local_addr=(bip, 50000))
    try:
        while True:
            data, addr = await asyncio.wait_for(sock.recvfrom(), 10)
            print("RECEIVING: ", data)
    except asyncio.TimeoutError:
        print('No data received in 10 seconds.')
        sock.close()


async def main():
    await asyncio.gather(*[
        # I have more stuff here
        asyncio.create_task(listenUdp())
    ])

asyncio.run(main())

Is 0.0.0.0 the right IP for broadcasting or am I missing something else?


Solution

  • Broadcast is basically deprecated because it interrupts every host on the LAN, even those not interested, e.g. routers, printers, etc. Broadcast was eliminated from IPv6, so the application could not be ported, and many companies will reject applications using broadcast for security reasons. The modern way of doing such things uses multicast, and there are several registered multicast discovery protocols. Multicast only interrupts interested devices.

    To build your application, you want the interested devices to subscribe to your predefined multicast group (either register one with IANA, or choose one in the Organization-Local scope, 239.0.0.0/8). When a host properly subscribes to a multicast group, it will send an IGMP request, and that will inform multicast routers and IGMP-snooping switches to send any multicast traffic for that group to the requesting host.

    The multicast source will send to the address of the multicast group address, and all subscribed hosts will receive it, but not interrupt any host not subscribed to the multicast group. The receiving hosts can then respond directly to the source unicast address using their own unicast addresses.