blob: b7f85567aaa55fab499d87ef2c98a85d683780ca [file] [log] [blame]
Gregory P. Smith2b1a4672009-05-03 19:09:56 +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. Smith2b1a4672009-05-03 19:09:56 +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. Smith2b1a4672009-05-03 19:09:56 +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
Guido van Rossum4fab6a51992-09-08 21:19:55 +000017import time
18import struct
Gregory P. Smith2b1a4672009-05-03 19:09:56 +000019import socket
20import sys
Guido van Rossum4fab6a51992-09-08 21:19:55 +000021
Guido van Rossumbd07b311992-11-16 16:54:45 +000022def main():
Gregory P. Smith2b1a4672009-05-03 19:09:56 +000023 group = MYGROUP_6 if "-6" in sys.argv[1:] else MYGROUP_4
Guido van Rossum4fab6a51992-09-08 21:19:55 +000024
Gregory P. Smith2b1a4672009-05-03 19:09:56 +000025 if "-s" in sys.argv[1:]:
26 sender(group)
Tim Peterse6ddc8b2004-07-18 05:56:09 +000027 else:
Gregory P. Smith2b1a4672009-05-03 19:09:56 +000028 receiver(group)
29
Gregory P. Smith2b1a4672009-05-03 19:09:56 +000030
31def sender(group):
Amaury Forgeot d'Arc37831432009-06-23 22:01:54 +000032 addrinfo = socket.getaddrinfo(group, None)[0]
Gregory P. Smith2b1a4672009-05-03 19:09:56 +000033
Amaury Forgeot d'Arc37831432009-06-23 22:01:54 +000034 s = socket.socket(addrinfo[0], socket.SOCK_DGRAM)
Gregory P. Smith2b1a4672009-05-03 19:09:56 +000035
36 # Set Time-to-live (optional)
37 ttl_bin = struct.pack('@i', MYTTL)
Amaury Forgeot d'Arc37831432009-06-23 22:01:54 +000038 if addrinfo[0] == socket.AF_INET: # IPv4
Gregory P. Smith2b1a4672009-05-03 19:09:56 +000039 s.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, ttl_bin)
40 else:
41 s.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_MULTICAST_HOPS, ttl_bin)
42
43 while True:
44 data = repr(time.time()).encode('utf-8') + b'\0'
Amaury Forgeot d'Arc37831432009-06-23 22:01:54 +000045 s.sendto(data, (addrinfo[4][0], MYPORT))
Tim Peterse6ddc8b2004-07-18 05:56:09 +000046 time.sleep(1)
Guido van Rossum4fab6a51992-09-08 21:19:55 +000047
Guido van Rossuma1b51f31992-10-25 19:20:47 +000048
Gregory P. Smith2b1a4672009-05-03 19:09:56 +000049def receiver(group):
Amaury Forgeot d'Arc37831432009-06-23 22:01:54 +000050 # Look up multicast group address in name server and find out IP version
51 addrinfo = socket.getaddrinfo(group, None)[0]
Guido van Rossumbd07b311992-11-16 16:54:45 +000052
Tim Peterse6ddc8b2004-07-18 05:56:09 +000053 # Create a socket
Amaury Forgeot d'Arc37831432009-06-23 22:01:54 +000054 s = socket.socket(addrinfo[0], socket.SOCK_DGRAM)
Gregory P. Smith2b1a4672009-05-03 19:09:56 +000055
Tim Peterse6ddc8b2004-07-18 05:56:09 +000056 # Allow multiple copies of this program on one machine
57 # (not strictly needed)
Gregory P. Smith2b1a4672009-05-03 19:09:56 +000058 s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
59
Tim Peterse6ddc8b2004-07-18 05:56:09 +000060 # Bind it to the port
Gregory P. Smith2b1a4672009-05-03 19:09:56 +000061 s.bind(('', MYPORT))
62
Amaury Forgeot d'Arc37831432009-06-23 22:01:54 +000063 group_bin = socket.inet_pton(addrinfo[0], addrinfo[4][0])
Gregory P. Smith2b1a4672009-05-03 19:09:56 +000064 # Join group
Amaury Forgeot d'Arc37831432009-06-23 22:01:54 +000065 if addrinfo[0] == socket.AF_INET: # IPv4
66 mreq = group_bin + struct.pack('=I', socket.INADDR_ANY)
Gregory P. Smith2b1a4672009-05-03 19:09:56 +000067 s.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq)
68 else:
Amaury Forgeot d'Arc37831432009-06-23 22:01:54 +000069 mreq = group_bin + struct.pack('@I', 0)
Gregory P. Smith2b1a4672009-05-03 19:09:56 +000070 s.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_JOIN_GROUP, mreq)
71
72 # Loop, printing any data we receive
73 while True:
74 data, sender = s.recvfrom(1500)
75 while data[-1:] == '\0': data = data[:-1] # Strip trailing \0's
76 print(str(sender) + ' ' + repr(data))
Guido van Rossumbd07b311992-11-16 16:54:45 +000077
78
Gregory P. Smith2b1a4672009-05-03 19:09:56 +000079if __name__ == '__main__':
80 main()