1#!/usr/bin/env python3 2 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""" 13 14MYPORT = 8123 15MYGROUP_4 = '225.0.0.250' 16MYGROUP_6 = 'ff15:7079:7468:6f6e:6465:6d6f:6d63:6173' 17MYTTL = 1 # Increase to reach other networks 18 19import time 20import struct 21import socket 22import sys 23 24def 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 33def 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 51def 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 81if __name__ == '__main__': 82 main() 83