Last active
February 10, 2022 07:35
-
-
Save kontza/f78cde37fbf29d9d91f02f48facaa6e8 to your computer and use it in GitHub Desktop.
A simple multicast sender/listener. Adapted from https://pymotw.com/3/socket/multicast.html to contain both the sender and the listener in the same script.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
import argparse | |
import datetime | |
import socket | |
import struct | |
import time | |
def listener(args): | |
multicast_group = args.address | |
server_address = ("", args.port) | |
# Create the socket | |
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) | |
# Bind to the server address | |
sock.bind(server_address) | |
# Tell the operating system to add the socket to | |
# the multicast group on all interfaces. | |
group = socket.inet_aton(multicast_group) | |
mreq = struct.pack("4sL", group, socket.INADDR_ANY) | |
sock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq) | |
# Receive/respond loop | |
while True: | |
print("\nwaiting to receive message") | |
data, address = sock.recvfrom(1024) | |
print(f"received {len(data)} bytes from {address}") | |
print(data) | |
print(f"sending acknowledgement to {address}") | |
sock.sendto(b"ack", address) | |
def sender(args): | |
message = datetime.datetime.today().isoformat() | |
multicast_group = (args.address, args.port) | |
# Create the datagram socket | |
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) | |
# Set a timeout so the socket does not block | |
# indefinitely when trying to receive data. | |
sock.settimeout(0.2) | |
# Set the time-to-live for messages to 1 so they do not | |
# go past the local network segment. | |
ttl = struct.pack("b", 1) | |
sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, ttl) | |
try: | |
# Send data to the multicast group | |
print(f"sending {message}") | |
sock.sendto(bytes(message, "utf-8"), multicast_group) | |
# Look for responses from all recipients | |
while True: | |
print("waiting to receive") | |
try: | |
data, server = sock.recvfrom(16) | |
except socket.timeout: | |
print("timed out, no more responses") | |
break | |
else: | |
print(f"received {data} from {server}") | |
finally: | |
print("closing socket") | |
sock.close() | |
if __name__ == "__main__": | |
default_address = "224.3.29.71" | |
default_port = 10000 | |
parser = argparse.ArgumentParser( | |
description="""A multicast sender/listener. | |
Adapted from https://pymotw.com/3/socket/multicast.html | |
to include both the listener and the sender in a single script.""" | |
) | |
parser.add_argument( | |
"-a", | |
"--address", | |
metavar="address", | |
type=str, | |
help="multicast address to connect to (default = {})".format(default_address), | |
default=default_address, | |
) | |
parser.add_argument( | |
"-p", | |
"--port", | |
metavar="port", | |
type=int, | |
help="multicast port (default = {})".format(default_port), | |
default=default_port, | |
) | |
parser.add_argument( | |
"-l", "--listen", help="listen to multicast traffic", action="store_true" | |
) | |
parser.add_argument( | |
"-s", "--send", help="send multicast traffic", action="store_true" | |
) | |
args = parser.parse_args() | |
if args.listen: | |
listener(args) | |
elif args.send: | |
while True: | |
sender(args) | |
time.sleep(3.14) | |
else: | |
parser.print_help() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment