1 #!/usr/bin/env python3 2 3 """ 4 Send/receive UDP multicast packets. 5 Requires that your OS kernel supports IP multicast. 6 7 Usage: 8 mcast -s (sender, IPv4) 9 mcast -s -6 (sender, IPv6) 10 mcast (receivers, IPv4) 11 mcast -6 (receivers, IPv6) 12 """ 13 14 MYPORT = 8123 15 MYGROUP_4 = '225.0.0.250' 16 MYGROUP_6 = 'ff15:7079:7468:6f6e:6465:6d6f:6d63:6173' 17 MYTTL = 1 # Increase to reach other networks 18 19 import time 20 import struct 21 import socket 22 import sys 23 24 def main(): 25 group = MYGROUP_6 if "-6" in sys.argv[1:] else MYGROUP_4 26 27 if "-s" in sys.argv[1:]: 28 sender(group) 29 else: 30 receiver(group) 31 32 33 def sender(group): 34 addrinfo = socket.getaddrinfo(group, None)[0] 35 36 s = socket.socket(addrinfo[0], socket.SOCK_DGRAM) 37 38 # Set Time-to-live (optional) 39 ttl_bin = struct.pack('@i', MYTTL) 40 if addrinfo[0] == socket.AF_INET: # IPv4 41 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' 47 s.sendto(data, (addrinfo[4][0], MYPORT)) 48 time.sleep(1) 49 50 51 def receiver(group): 52 # Look up multicast group address in name server and find out IP version 53 addrinfo = socket.getaddrinfo(group, None)[0] 54 55 # Create a socket 56 s = socket.socket(addrinfo[0], socket.SOCK_DGRAM) 57 58 # Allow multiple copies of this program on one machine 59 # (not strictly needed) 60 s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 61 62 # Bind it to the port 63 s.bind(('', MYPORT)) 64 65 group_bin = socket.inet_pton(addrinfo[0], addrinfo[4][0]) 66 # Join group 67 if addrinfo[0] == socket.AF_INET: # IPv4 68 mreq = group_bin + struct.pack('=I', socket.INADDR_ANY) 69 s.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq) 70 else: 71 mreq = group_bin + struct.pack('@I', 0) 72 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)) 79 80 81 if __name__ == '__main__': 82 main() 83