Receiving Broadcast Packets in Python
Asked Answered
P

3

32

I have the following code which sends a udp packet that is broadcasted in the subnet.

from socket import *
s=socket(AF_INET, SOCK_DGRAM)
s.setsockopt(SOL_SOCKET, SO_BROADCAST, 1)
s.sendto('this is testing',('255.255.255.255',12345))

The following code is for receiving the broadcast packet.

from socket import *
s=socket(AF_INET, SOCK_DGRAM)
s.bind(('172.30.102.141',12345))
m=s.recvfrom(1024)
print m[0]

The problem is that its not receiving any broadcast packet. However, it is successfully receiving normal udp packets sent to that port.

My machine was obviously receiving the broadcast packet, which I tested using netcat.

$ netcat -lu -p 12345                                             
this is testing^C

So, where exactly is the problem?

Photofluorography answered 5/4, 2014 at 8:43 Comment(3)
You might want to check your IP because i tried the method provided by you with my IP and it worked perfectly. while the answer given by @John Zwinck also works fine.Multure
how is an ip address with 5 octets valid? how does it not error out?Deface
I have just tested out that on MacOS 11.7, the command netcat -lu -p 12345 does not receive UDP broadcast.Tiatiana
F
32

Try binding to the default address:

s.bind(('',12345))
Feeze answered 5/4, 2014 at 10:4 Comment(7)
I believe, there must be space between the quotes for it to work. ' ' rather than ''Multure
That indeed worked! What if there is more than one ip-address for the machine?Photofluorography
@nitish712: it will listen to all interfaces.Feeze
@JohnZwinck But how to make this, to listen on a specific interface? I actually don't want packets from all interfaces.Photofluorography
From what @Multure said, your original code should work for a single interface. But you must make sure you are giving the right IP address--the interface address.Feeze
There seems to be a problem with my machine I guess. I have been giving the right IP-Address though.Photofluorography
@Photofluorography to listen on a specific interface, you need to specify that interface's broadcast ip. This has been outlined in my answer to this question.Ier
I
23

I believe the solution outlined in the accepted answer solves the issue, but not in exactly the right way. You shouldn't use the normal interface IP, but the broadcast IP which is used to send the message. For example if ifconfig is:


inet addr:10.0.2.2 Bcast:10.0.2.255 Mask:255.255.255.0
then the server should use s.bind(('10.0.2.255',12345)), not 10.0.2.2 (in OP's case he should use 255.255.255.255). The reason the accepted answer works is because ' ' tells the server to accept packets from all addresses, while specifying the IP address, filters it.

' ' is the hammer, specifying the correct broadcast address is the scalpel. And in many cases, though possibly not OP's, it is important that a server listen only the specified IP address (e.g. you want to accept requests only from a private network - the above code would accept requests from any external network too), for security purposes if nothing else.
Ier answered 3/9, 2015 at 10:3 Comment(8)
If you're using broadcast and not multicast, how do you get broadcasts from anything other than a directly connected layer 2 network? Unless you mean that you only want to listen for broadcasts on a specific network, like a vpn?Oleaginous
@FilipHaglund as long as you're in the same layer 3 network (subnet) the above code should work fine. IP based broadcast is a network layer (layer 3) feature, not link layer (layer 2). If you wish to receive broadcast packets from any connected interface, the accepted answer should be okay. Clarifying your question might help me answer you better.Ier
@AbrahamPhilip say If want to discover this broadcast on my android device connected to the same wifi (or PC connected to android device's hotspot) is it possible? It's not python specific I know.Reisman
@PhaniRithvij yup, the same principle should work on Android or a PC program, you just need to make a UDP listening socket in whichever language you're using and set it to listen on whatever the broadcast address of your Wi-Fi network is.Ier
How do I get the broadcast address through Python's socket module?Foliated
@Foliated check out #6243776 . In short it looks like you'll need to install the netifaces package for a truly cross platform way of getting the broadcast address of an interface. You need to know which interface's broadcast address you want of course. I've typically written Linux-specific implementations for this which use the output of the 'ip addr' command.Ier
While the above works for me to receive broadcast packets over the specific network interface, it doesn't allow me to receive targeted packets directed to the machine's IP address. Is there a way to listen to both 10.0.2.255 and 10.0.2.XXX - whatever XXX is for my machine?Freeborn
To the best of my knowledge each server socket can only bind to one IP address or ALL IP addresses. You have two approaches here: 1. Create two server sockets that listen on the two IPs (broadcast and the machine's) 2. Create a single server socket listening on '', and then have code after that which immediately closes an established connection which is not destined to the IP addresses you care about.Ier
F
1
s=socket(AF_INET, SOCK_DGRAM)
s.bind(('',1234))
while(1):
    m=s.recvfrom(4096)
    print 'len(m)='+str(len(m))
    print 'len(m[0])='+str(len(m[0]))    
    print m[0]

    print 'len(m[1])='+str(len(m[1]))    
    print m[1]  
Firooc answered 4/5, 2017 at 3:5 Comment(1)
Answering with code only is not a good solution. Read this how-to-ask to follow the SO guidelines.Tinny

© 2022 - 2024 — McMap. All rights reserved.