G'day,
I'm trying to write a simple UDP server that listens to a multicast
group. This is roughly what I have so far:
<code>
import socket
port = 5353
addr = '224.0.0.251'
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.setsockopt(socket.SOL_IP, socket.IP_ADD_MEMBERSHIP, socket.inet_aton(addr))
s.bind(("", port))
print "Waiting on port:", port
while 1:
data,addr = s.recvfrom(1024)
print "Received", data, "from", addr
</code>
However when I run it, it bombs out:
Traceback (most recent call last):
File "udpserver.py", line 8, in ?
s.setsockopt(socket.SOL_IP, socket.IP_ADD_MEMBERSHIP, socket.inet_aton(addr))
socket.error: (22, 'Invalid argument')
I'm completely mystified by this. The man page for setsockopt(2) doesn't even mention
EINVAL (at least on my system), and my usual network reference (Stevens, Unix Network
Programming) failed me on this occasion. The documentation refers the man page, which
is nice except that the system call has five arguments and the python call only has three
I did fine one example that was pretty close:
* http://www.pythonapocrypha.com/Chapter15/Chapter15.shtml, which does:
s.setsockopt(SOL_IP,IP_ADD_MEMBERSHIP, inet_aton(addr)+inet_aton(''))
and although the third argument looked a bit silly, it was all I had to work from.
Can anyone enlighten me?
Brad
- --
http://linux.conf.au. 22-25Jan2003. Perth, Aust. I'm registered. Are you?
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.0.6 (GNU/Linux)
Comment: For info see http://www.gnupg.org
iD8DBQE94f+bW6pHgIdAuOMRAtWqAKCAAiAqs0nLkMiohyqrJ7sWC4l4qgCfZppm
uE5k2r4JXerPXtsog2pUU1Y=
=VMh7
-----END PGP SIGNATURE-----
> s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
> s.setsockopt(socket.SOL_IP, socket.IP_ADD_MEMBERSHIP, socket.inet_aton(addr))
> s.bind(("", port))
> However when I run it, it bombs out:
> Traceback (most recent call last):
> File "udpserver.py", line 8, in ?
> s.setsockopt(socket.SOL_IP, socket.IP_ADD_MEMBERSHIP,
> socket.inet_aton(addr))
> socket.error: (22, 'Invalid argument')
From the ip(7) manpage:
IP_ADD_MEMBERSHIP: Join a multicast group. Argument is a struct
ip_mreqn structure.
I don't think the Python setsockopt function is smart enough to see the
IP_ADD_MEMBERSHIP option and build the struct. I suggest you look into
http://www.python.org/doc/current/lib/module-struct.html
and build a struct ip_mreqn
> I'm completely mystified by this. The man page for setsockopt(2) doesn't
> even mention EINVAL (at least on my system)
It is documented in the ip(7) manpage.
> except that the system call has five arguments and the python call only
> has three
because the first argument (the socket) comes from the object and the last
argument's value (data length) is implicit from the data being passed.
On Mon, 25 Nov 2002 23:26, Adam Langley wrote:
<snip>
> From the ip(7) manpage:
> IP_ADD_MEMBERSHIP: Join a multicast group. Argument is a struct
> ip_mreqn structure.
>
> I don't think the Python setsockopt function is smart enough to see the
> IP_ADD_MEMBERSHIP option and build the struct. I suggest you look into
> http://www.python.org/doc/current/lib/module-struct.html
> and build a struct ip_mreqn
Thanks - makes sense, but I'm not there yet. I think I'm creating the
structure properly, but still no joy:
<code>
#This from Python Cookbook, recipe 10.5
#Credits: Alex Martelli, Greg Jorgenen
def dottedQuadtoNum(ip):
"convert decimal dotted quad string to long integer"
return struct.unpack('>L', socket.inet_aton(ip))[0]
port = 5353
addr = '224.0.0.251'
ip_mreqn = struct.pack('IIi', dottedQuadtoNum(addr), 0, 0)
print struct.unpack('IIi', ip_mreqn)
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.setsockopt(socket.SOL_IP, socket.IP_ADD_MEMBERSHIP, ip_mreqn)
</code>
Which produces:
(3758096635L, 0L, 0)
Traceback (most recent call last):
File "udpserver.py", line 18, in ?
s.setsockopt(socket.SOL_IP, socket.IP_ADD_MEMBERSHIP, ip_mreqn)
socket.error: (22, 'Invalid argument')
More ideas?
Brad
- --
http://linux.conf.au. 22-25Jan2003. Perth, Aust. I'm registered. Are you?
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.0.6 (GNU/Linux)
Comment: For info see http://www.gnupg.org
iD8DBQE94pNAW6pHgIdAuOMRArjMAJ9xCCIz9K6fva7CnD/9qfEeH/Tk2ACgsBvJ
BS6SdayFiUrqy3lC4wNoB+o=
=rDsc
-----END PGP SIGNATURE-----
> ip_mreqn = struct.pack('IIi', dottedQuadtoNum(addr), 0, 0)
ip_mreqn = struct.pack ('>IIi', dottedQuadtoNum(addr), 0, 0)
(you always pass IPs in big-endian order to the kernel)
I don't know if that actaully works, but the setsockopt doesn't throw an
exception with that change, at least.
On Tue, 26 Nov 2002 08:16, Brad Hards wrote:
> On Mon, 25 Nov 2002 23:26, Adam Langley wrote:
> <snip>
>
> > From the ip(7) manpage:
> > IP_ADD_MEMBERSHIP: Join a multicast group. Argument is a struct
> > ip_mreqn structure.
> >
> > I don't think the Python setsockopt function is smart enough to see the
> > IP_ADD_MEMBERSHIP option and build the struct. I suggest you look into
> > http://www.python.org/doc/current/lib/module-struct.html
> > and build a struct ip_mreqn
>
> Thanks - makes sense, but I'm not there yet. I think I'm creating the
> structure properly, but still no joy:
I found another example, at http://www.senux.com/linux/network/multicast/
The code seems very roundabout (trying to clean up and simplify now), but it
runs fine, and my toy mDNS server on LInux is getting messages from my iMac
over multicast :)
Brad
- --
http://linux.conf.au. 22-25Jan2003. Perth, Aust. I'm registered. Are you?
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.0.6 (GNU/Linux)
Comment: For info see http://www.gnupg.org
iD8DBQE94qniW6pHgIdAuOMRAsPiAJ4swtiVSzDKXDrkK9vWVlyA4VoHzgCePpK6
45ThE0t3Z53R4EKPFAAcYwo=
=sUIh
-----END PGP SIGNATURE-----