blob: 25fde79fddaee7d6bd3a0919687f4c25d7b9414e [file] [log] [blame]
Gregory P. Smith6493d782009-05-03 18:42:15 +00001#!/usr/bin/env python
2#
Guido van Rossum50d5e8a1995-03-04 22:57:56 +00003# Send/receive UDP multicast packets.
4# Requires that your OS kernel supports IP multicast.
Guido van Rossum50d5e8a1995-03-04 22:57:56 +00005#
Guido van Rossum4fab6a51992-09-08 21:19:55 +00006# Usage:
Gregory P. Smith6493d782009-05-03 18:42:15 +00007# mcast -s (sender, IPv4)
8# mcast -s -6 (sender, IPv6)
9# mcast (receivers, IPv4)
10# mcast -6 (receivers, IPv6)
Guido van Rossum4fab6a51992-09-08 21:19:55 +000011
12MYPORT = 8123
Gregory P. Smith6493d782009-05-03 18:42:15 +000013MYGROUP_4 = '225.0.0.250'
14MYGROUP_6 = 'ff15:7079:7468:6f6e:6465:6d6f:6d63:6173'
15MYTTL = 1 # Increase to reach other networks
Guido van Rossum4fab6a51992-09-08 21:19:55 +000016
Gregory P. Smith6493d782009-05-03 18:42:15 +000017import ipaddr
Guido van Rossum4fab6a51992-09-08 21:19:55 +000018import time
19import struct
Gregory P. Smith6493d782009-05-03 18:42:15 +000020import socket
21import sys
Guido van Rossum4fab6a51992-09-08 21:19:55 +000022
Guido van Rossumbd07b311992-11-16 16:54:45 +000023def main():
Gregory P. Smith6493d782009-05-03 18:42:15 +000024 group = MYGROUP_6 if "-6" in sys.argv[1:] else MYGROUP_4
Guido van Rossum4fab6a51992-09-08 21:19:55 +000025
Gregory P. Smith6493d782009-05-03 18:42:15 +000026 if "-s" in sys.argv[1:]:
27 sender(group)
Tim Peterse6ddc8b2004-07-18 05:56:09 +000028 else:
Gregory P. Smith6493d782009-05-03 18:42:15 +000029 receiver(group)
30
31def _sockfam(ip):
32 """Returns the family argument of socket.socket"""
33 if ip.version == 4:
34 return socket.AF_INET
35 elif ip.version == 6:
36 return socket.AF_INET6
37 else:
38 raise ValueError('IPv' + ip.version + ' is not supported')
39
40def sender(group):
41 group_ip = ipaddr.IP(group)
42
43 s = socket.socket(_sockfam(group_ip), socket.SOCK_DGRAM)
44
45 # Set Time-to-live (optional)
46 ttl_bin = struct.pack('@i', MYTTL)
47 if group_ip.version == 4:
48 s.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, ttl_bin)
49 else:
50 s.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_MULTICAST_HOPS, ttl_bin)
51
52 while True:
Tim Peterse6ddc8b2004-07-18 05:56:09 +000053 data = repr(time.time())
Gregory P. Smith6493d782009-05-03 18:42:15 +000054 s.sendto(data + '\0', (group_ip.ip_ext_full, MYPORT))
Tim Peterse6ddc8b2004-07-18 05:56:09 +000055 time.sleep(1)
Guido van Rossum4fab6a51992-09-08 21:19:55 +000056
Guido van Rossuma1b51f31992-10-25 19:20:47 +000057
Gregory P. Smith6493d782009-05-03 18:42:15 +000058def receiver(group):
59 group_ip = ipaddr.IP(group)
Guido van Rossumbd07b311992-11-16 16:54:45 +000060
Tim Peterse6ddc8b2004-07-18 05:56:09 +000061 # Create a socket
Gregory P. Smith6493d782009-05-03 18:42:15 +000062 s = socket.socket(_sockfam(group_ip), socket.SOCK_DGRAM)
63
Tim Peterse6ddc8b2004-07-18 05:56:09 +000064 # Allow multiple copies of this program on one machine
65 # (not strictly needed)
Gregory P. Smith6493d782009-05-03 18:42:15 +000066 s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
67
Tim Peterse6ddc8b2004-07-18 05:56:09 +000068 # Bind it to the port
Gregory P. Smith6493d782009-05-03 18:42:15 +000069 s.bind(('', MYPORT))
70
71 # Join group
72 if group_ip.version == 4: # IPv4
73 mreq = group_ip.packed + struct.pack('=I', socket.INADDR_ANY)
74 s.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq)
75 else:
76 mreq = group_ip.packed + struct.pack('@I', 0)
77 s.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_JOIN_GROUP, mreq)
78
79 # Loop, printing any data we receive
80 while True:
81 data, sender = s.recvfrom(1500)
82 while data[-1:] == '\0': data = data[:-1] # Strip trailing \0's
83 print (str(sender) + ' ' + repr(data))
Guido van Rossumbd07b311992-11-16 16:54:45 +000084
85
Gregory P. Smith6493d782009-05-03 18:42:15 +000086if __name__ == '__main__':
87 main()