blob: 924c7c3e80e7d28ea084cf393e3cc0d469d79593 [file] [log] [blame]
Benjamin Peterson90f5ba52010-03-11 22:53:45 +00001#!/usr/bin/env python3
Georg Brandl856898b2010-12-30 22:11:50 +00002
3"""
4Send/receive UDP multicast packets.
5Requires that your OS kernel supports IP multicast.
6
7Usage:
8 mcast -s (sender, IPv4)
9 mcast -s -6 (sender, IPv6)
10 mcast (receivers, IPv4)
11 mcast -6 (receivers, IPv6)
12"""
Guido van Rossum4fab6a51992-09-08 21:19:55 +000013
14MYPORT = 8123
Gregory P. Smith2b1a4672009-05-03 19:09:56 +000015MYGROUP_4 = '225.0.0.250'
16MYGROUP_6 = 'ff15:7079:7468:6f6e:6465:6d6f:6d63:6173'
17MYTTL = 1 # Increase to reach other networks
Guido van Rossum4fab6a51992-09-08 21:19:55 +000018
Guido van Rossum4fab6a51992-09-08 21:19:55 +000019import time
20import struct
Gregory P. Smith2b1a4672009-05-03 19:09:56 +000021import socket
22import sys
Guido van Rossum4fab6a51992-09-08 21:19:55 +000023
Guido van Rossumbd07b311992-11-16 16:54:45 +000024def main():
Gregory P. Smith2b1a4672009-05-03 19:09:56 +000025 group = MYGROUP_6 if "-6" in sys.argv[1:] else MYGROUP_4
Guido van Rossum4fab6a51992-09-08 21:19:55 +000026
Gregory P. Smith2b1a4672009-05-03 19:09:56 +000027 if "-s" in sys.argv[1:]:
28 sender(group)
Tim Peterse6ddc8b2004-07-18 05:56:09 +000029 else:
Gregory P. Smith2b1a4672009-05-03 19:09:56 +000030 receiver(group)
31
Gregory P. Smith2b1a4672009-05-03 19:09:56 +000032
33def sender(group):
Amaury Forgeot d'Arc37831432009-06-23 22:01:54 +000034 addrinfo = socket.getaddrinfo(group, None)[0]
Gregory P. Smith2b1a4672009-05-03 19:09:56 +000035
Amaury Forgeot d'Arc37831432009-06-23 22:01:54 +000036 s = socket.socket(addrinfo[0], socket.SOCK_DGRAM)
Gregory P. Smith2b1a4672009-05-03 19:09:56 +000037
38 # Set Time-to-live (optional)
39 ttl_bin = struct.pack('@i', MYTTL)
Amaury Forgeot d'Arc37831432009-06-23 22:01:54 +000040 if addrinfo[0] == socket.AF_INET: # IPv4
Gregory P. Smith2b1a4672009-05-03 19:09:56 +000041 s.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, ttl_bin)
42 else:
43 s.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_MULTICAST_HOPS, ttl_bin)
44
45 while True:
46 data = repr(time.time()).encode('utf-8') + b'\0'
Amaury Forgeot d'Arc37831432009-06-23 22:01:54 +000047 s.sendto(data, (addrinfo[4][0], MYPORT))
Tim Peterse6ddc8b2004-07-18 05:56:09 +000048 time.sleep(1)
Guido van Rossum4fab6a51992-09-08 21:19:55 +000049
Guido van Rossuma1b51f31992-10-25 19:20:47 +000050
Gregory P. Smith2b1a4672009-05-03 19:09:56 +000051def receiver(group):
Amaury Forgeot d'Arc37831432009-06-23 22:01:54 +000052 # Look up multicast group address in name server and find out IP version
53 addrinfo = socket.getaddrinfo(group, None)[0]
Guido van Rossumbd07b311992-11-16 16:54:45 +000054
Tim Peterse6ddc8b2004-07-18 05:56:09 +000055 # Create a socket
Amaury Forgeot d'Arc37831432009-06-23 22:01:54 +000056 s = socket.socket(addrinfo[0], socket.SOCK_DGRAM)
Gregory P. Smith2b1a4672009-05-03 19:09:56 +000057
Tim Peterse6ddc8b2004-07-18 05:56:09 +000058 # Allow multiple copies of this program on one machine
59 # (not strictly needed)
Gregory P. Smith2b1a4672009-05-03 19:09:56 +000060 s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
61
Tim Peterse6ddc8b2004-07-18 05:56:09 +000062 # Bind it to the port
Gregory P. Smith2b1a4672009-05-03 19:09:56 +000063 s.bind(('', MYPORT))
64
Amaury Forgeot d'Arc37831432009-06-23 22:01:54 +000065 group_bin = socket.inet_pton(addrinfo[0], addrinfo[4][0])
Gregory P. Smith2b1a4672009-05-03 19:09:56 +000066 # Join group
Amaury Forgeot d'Arc37831432009-06-23 22:01:54 +000067 if addrinfo[0] == socket.AF_INET: # IPv4
68 mreq = group_bin + struct.pack('=I', socket.INADDR_ANY)
Gregory P. Smith2b1a4672009-05-03 19:09:56 +000069 s.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq)
70 else:
Amaury Forgeot d'Arc37831432009-06-23 22:01:54 +000071 mreq = group_bin + struct.pack('@I', 0)
Gregory P. Smith2b1a4672009-05-03 19:09:56 +000072 s.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_JOIN_GROUP, mreq)
73
74 # Loop, printing any data we receive
75 while True:
76 data, sender = s.recvfrom(1500)
77 while data[-1:] == '\0': data = data[:-1] # Strip trailing \0's
78 print(str(sender) + ' ' + repr(data))
Guido van Rossumbd07b311992-11-16 16:54:45 +000079
80
Gregory P. Smith2b1a4672009-05-03 19:09:56 +000081if __name__ == '__main__':
82 main()