Skip to content

Instantly share code, notes, and snippets.

@kontza
Last active February 10, 2022 07:35
Show Gist options
  • Save kontza/f78cde37fbf29d9d91f02f48facaa6e8 to your computer and use it in GitHub Desktop.
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.
#!/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