Sending broadcast in Python
Asked Answered
F

2

5

I am trying to learn to code sockets (in Python 3), I am simply trying to send a broadcast from a server and receive it from a client.

My problem is that whenever I try to send the packets to 255.255.255.255, it seems nothing is actually sent. I tried to find the packets with wireshark but except on the loopback interface, I can't find any.

I can successfully send a message between the two computers when manually inputting the IP, and I also see the packets in wireshark.

Here's the code for the client

import socket


sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
sock.bind(("0.0.0.0", 5005))
while True:
    # sock.sendto(bytes("hello", "utf-8"), ip_co)
    data, addr = sock.recvfrom(1024)
    print(data)

And here's the code for the server

import socket
from time import sleep

def main():
    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)  # UDP
    sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
    #  sock.settimeout(2)
    while True:

        sock.sendto(bytes("test", "utf-8"), ("255.255.255.255", 5005))

        sleep(1)


main()

Sorry if the code is ugly, I am very new to sockets and to python.

Furunculosis answered 25/9, 2020 at 14:59 Comment(0)
Y
11

The reason is that you are broadcasting on one interface and listening on another. See this answer UDP-Broadcast on all interfaces.

You need to broadcast on all interfaces, for example using the following (purely for demonstration) code. However, keep in mind that broadcasting over IP is a legacy feature which has been dropped from IPv6. Use multicasting instead.

import socket
from time import sleep

def main():
    interfaces = socket.getaddrinfo(host=socket.gethostname(), port=None, family=socket.AF_INET)
    allips = [ip[-1][0] for ip in interfaces]

    msg = b'hello world'
    while True:

        for ip in allips:
            print(f'sending on {ip}')
            sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)  # UDP
            sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
            sock.bind((ip,0))
            sock.sendto(msg, ("255.255.255.255", 5005))
            sock.close()

        sleep(2)


main()
Yb answered 25/9, 2020 at 15:40 Comment(3)
Thank you for your help, I understood from that answer that I need to find the broadcast address for the specific interface that I want to broacast to, tried it and it worked ! However I would like to make my server work on any network without having to manually input an IP, which I can do using the mask I think... My problem now is to actually find what mask the network is usingFurunculosis
I have updated the answer to show how to obtain a list of all IPs and then broadcast over all the interfaces. This code is purely for demonstration - it is neither the most robust nor the most efficient. You may also wish to add the loopback address to the list allips.Yb
Actually you do not need the allips list, you can just sendto 255.255.255.255, remove the sock.bind((ip,0)) and it will work. Moreover, the method getaddrinfo do not return the actual IPs, some times in some OSs it will return 127.0.1.1, so the solution of sock.bind((ip,0)) will not workStrode
S
3

If you are here to just know how to send broadcast and the solution of Mario don't work for you, because you are getting list of ips as 127.0.1.1, so there is a simpler solution:

with socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP) as sock:
    sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
    sock.sendto(msg, ("255.255.255.255", 5005))

Notice that the disadvantage here is that it will not go throw all the network interfaces, like Mario solution, just the one per the OS IP table. So keep in mind...

Strode answered 1/4, 2022 at 13:32 Comment(1)
I must say this does not work for me (Win10, Python 3.8) according to Wireshark 4.2.5 monitoring of a particular network interface of interest. But the variant by Mario is working well, so it seems binding to IP address is necessary.Hungerford

© 2022 - 2024 — McMap. All rights reserved.