Anyone used IP multicast (demo/sockets/mcast.py) on NT? I'm gett ing a WSAEFAULT error

Mike Fletcher mfletch at tpresence.com
Mon Jul 10 16:07:16 EDT 2000


Okay, discovered information:

1) Winsock uses a 4-byte integer (in little-endian format) for TTL, so you
need to use 'I' as the struct format string.
2) Winsock has a quirk that certain implementations require that a socket be
bound before you set any multicast variables.
3) Dr. Dobbs seems to think that Winsock requires that the sender also
subscribe to the group.

Doing all that (within a check for win32 platform) gets me to the point
where the system pretends to run properly, but doesn't actually get any data
through the pipe (no error messages, just nothing happening).  With loopback
enabled (supposed to be default), the sender should be able to read data
sent to the group on it's sending port.  As of yet, no luck.

The revised demo is below.  Help appreciated.
Mike


8<_____________ mcast.py ____________
# Send/receive UDP multicast packets.
# Requires that your OS kernel supports IP multicast.
# This is built-in on SGI, still optional for most other vendors.
#
# Usage:
#   mcast -s (sender)
#   mcast -b (sender, using broadcast instead multicast)
#   mcast    (receivers)

##MYPORT = 8123
##MYGROUP = '225.0.0.250'
MYPORT = 4711
MYGROUP = '234.5.6.7'
TTL = 1

import sys
import time
import struct
import regsub, string
from socket import *


def address_to_bytes( address ):
	bytes = map(
		chr,
		map(
			string.atoi,
			string.split(
				address,
				'.',
			),
		)
	)
	return string.join( bytes, "")
	

# Main program
def main():
	flags = sys.argv[1:]
	#
	if flags:
		sender(flags[0])
	else:
		receiver()


# Sender subroutine (only one per local area network)
def sender(flag):
	mcastSocket = socket(AF_INET, SOCK_DGRAM)
	if flag == '-b':
		mcastSocket.setsockopt(SOL_SOCKET, SO_BROADCAST, 1)
		mygroup = '<broadcast>'
	else:
		mygroup = MYGROUP
		# set time-to-live option on the socket
		
		if sys.platform == "win32":
##			mcastSocket.bind( ("", 10000))
			mcastSocket.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
			mcastSocket.setblocking( 0)
			mcastSocket.bind( ("", MYPORT))
			ttl = struct.pack( 'I', TTL ) # winsock uses a
little-endian 4-byte integer
			# Construct struct mreq from grpaddr and ifaddr
			ifaddr = INADDR_ANY
			mreq = struct.pack('>4sl',
address_to_bytes(mygroup), ifaddr)
			# Add group membership
			mcastSocket.setsockopt(IPPROTO_IP,
IP_ADD_MEMBERSHIP, mreq)
			## following shouldn't be necessary, as loop back is
the default
##			mcastSocket.setsockopt(IPPROTO_IP,
IP_MULTICAST_LOOP, '\001\000\000\000')
			mcastSocket.setsockopt(IPPROTO_IP, IP_MULTICAST_TTL,
ttl)
			#
		else:
			ttl = struct.pack('B', TTL )
##		print `ttl`
##		import pdb
##		pdb.set_trace()
			mcastSocket.setsockopt(IPPROTO_IP, IP_MULTICAST_TTL,
ttl)
	while 1:
		print 'sending'
		data = `time.time()`
##		data = data + (1400 - len(data)) * '\0'
		mcastSocket.sendto(data, (mygroup, MYPORT))
		try:
			data = mcastSocket.recvfrom( 1500 )
			print 'got data', data
		except:
			pass
		time.sleep(1)
		

# Receiver subroutine (as many as you like)
def receiver():
	# Open and initialize the socket
	mcastSocket = openmcastsock(MYGROUP, MYPORT)
	#
	# Loop, printing any data we receive
	while 1:
##		print 'receive'
		try:
			data, sender = mcastSocket.recvfrom(1500)
			while data[-1:] == '\0': data = data[:-1] # Strip
trailing \0's
			print sender, ':', `data`
		except error, value:
			if value.args[0] == 10035:
				pass
			else:
				raise
		time.sleep( 0.05)


# Open a UDP socket, bind it to a port and select a multicast group
def openmcastsock(group, port):
	# Import modules used only here
	import struct
	#
	# Create a socket
	mcastSocket = socket(AF_INET, SOCK_DGRAM)
	mcastSocket.setblocking( 0)
	#
	# Allow multiple copies of this program on one machine
	# (not strictly needed)
	mcastSocket.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
	#
	# Bind it to the port
	mcastSocket.bind(('', port))
	#
	# Look up multicast group address in name server
	# (doesn't hurt if it is already in ddd.ddd.ddd.ddd format)
	group = gethostbyname(group)
	#
	# Construct binary group address
	#
	# Construct struct mreq from grpaddr and ifaddr
	ifaddr = INADDR_ANY
	mreq = struct.pack('>4sl', address_to_bytes(group), ifaddr)
	print `mreq`
	#
	# Add group membership
	mcastSocket.setsockopt(IPPROTO_IP, IP_ADD_MEMBERSHIP, mreq)
	#
	return mcastSocket


main()




More information about the Python-list mailing list