| #!/usr/bin/env python3 |
| # |
| # Send/receive UDP multicast packets. |
| # Requires that your OS kernel supports IP multicast. |
| # |
| # Usage: |
| # mcast -s (sender, IPv4) |
| # mcast -s -6 (sender, IPv6) |
| # mcast (receivers, IPv4) |
| # mcast -6 (receivers, IPv6) |
| |
| MYPORT = 8123 |
| MYGROUP_4 = '225.0.0.250' |
| MYGROUP_6 = 'ff15:7079:7468:6f6e:6465:6d6f:6d63:6173' |
| MYTTL = 1 # Increase to reach other networks |
| |
| import time |
| import struct |
| import socket |
| import sys |
| |
| def main(): |
| group = MYGROUP_6 if "-6" in sys.argv[1:] else MYGROUP_4 |
| |
| if "-s" in sys.argv[1:]: |
| sender(group) |
| else: |
| receiver(group) |
| |
| |
| def sender(group): |
| addrinfo = socket.getaddrinfo(group, None)[0] |
| |
| s = socket.socket(addrinfo[0], socket.SOCK_DGRAM) |
| |
| # Set Time-to-live (optional) |
| ttl_bin = struct.pack('@i', MYTTL) |
| if addrinfo[0] == socket.AF_INET: # IPv4 |
| s.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, ttl_bin) |
| else: |
| s.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_MULTICAST_HOPS, ttl_bin) |
| |
| while True: |
| data = repr(time.time()).encode('utf-8') + b'\0' |
| s.sendto(data, (addrinfo[4][0], MYPORT)) |
| time.sleep(1) |
| |
| |
| def receiver(group): |
| # Look up multicast group address in name server and find out IP version |
| addrinfo = socket.getaddrinfo(group, None)[0] |
| |
| # Create a socket |
| s = socket.socket(addrinfo[0], socket.SOCK_DGRAM) |
| |
| # Allow multiple copies of this program on one machine |
| # (not strictly needed) |
| s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) |
| |
| # Bind it to the port |
| s.bind(('', MYPORT)) |
| |
| group_bin = socket.inet_pton(addrinfo[0], addrinfo[4][0]) |
| # Join group |
| if addrinfo[0] == socket.AF_INET: # IPv4 |
| mreq = group_bin + struct.pack('=I', socket.INADDR_ANY) |
| s.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq) |
| else: |
| mreq = group_bin + struct.pack('@I', 0) |
| s.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_JOIN_GROUP, mreq) |
| |
| # Loop, printing any data we receive |
| while True: |
| data, sender = s.recvfrom(1500) |
| while data[-1:] == '\0': data = data[:-1] # Strip trailing \0's |
| print(str(sender) + ' ' + repr(data)) |
| |
| |
| if __name__ == '__main__': |
| main() |