I need to use multicast in Python application, after googling a bit I found snippets of code that works, here it is:
# UDP multicast examples, Hugo Vincent, 2005-05-14.
import socket
import sys
import struct
def send(data, port=50000, addr='239.192.1.100'):
"""send(data[, port[, addr]]) - multicasts a UDP datagram."""
# Create the socket
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# Make the socket multicast-aware, and set TTL.
s.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 20) # Change TTL (=20) to suit
s.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_LOOP, 1)
# Send the data
s.sendto(data, (addr, port))
def recv(port=50000, addr="239.192.1.100", buf_size=1024):
"""recv([port[, addr[,buf_size]]]) - waits for a datagram and returns the data."""
# Create the socket
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# Set some options to make it multicast-friendly
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
try:
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)
except AttributeError:
pass # Some systems don't support SO_REUSEPORT
s.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 20)
# Bind to the port
s.bind(('', port))
# Set some more multicast options
intf = socket.gethostbyname(socket.gethostname())
s.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_IF, socket.inet_aton(intf))
mreq = struct.pack("4sl", socket.inet_aton(addr), socket.INADDR_ANY)
s.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq)
# Receive the data, then unregister multicast receive membership, then close the port
data, sender_addr = s.recvfrom(buf_size)
s.setsockopt(socket.SOL_IP, socket.IP_DROP_MEMBERSHIP, socket.inet_aton(addr) + socket.inet_aton('0.0.0.0'))
s.close()
return data
if __name__=="__main__":
if sys.argv[1] == "recv":
print recv()
else:
send("a")
I have a problem with bind and multicast.
As I understand if I bind my socket on which I will receive messages, in this case it will filter the traffic. ('',port) means I want to receive all traffic that comes on this socket and this port, regardless of the destination ip of the packet (same as 0.0.0.0), lets call this case 1.
Also this works if I have bind((addr,port)). I will receive all packets with destination ip being this multicast group (of course I also need to join this multicast group), this is case 2.
Now as I said both of these works, but only on Linux.
I tried my little program on windows machine, first case is working but when I try the other one I am getting
Traceback (most recent call last):
File "test.py", line 51, in <module>
print recv()
File "test.py", line 32, in recv
s.bind((addr, port))
File "C:\Python27\lib\socket.py", line 224, in meth
return getattr(self._sock,name)(*args)
socket.error: [Errno 10049] The requested address is not valid in its context
I am no expert on windows systems (I mainly do my development on Linux) but I am interested why my code fails with this error only on windows systems (I used windows 7 btw).