#!/usr/bin/env python3 # # @RDE_HEADER@ # $Id$ # $HeadURL$ # $Author$ # Created by Christian Fröbel, NLE, 2019-08-08 # import socket import struct from contextlib import contextmanager from argparse import ArgumentParser, RawDescriptionHelpFormatter import sys # struct in_addr # { # uint32_t s_addr; /* address in network byte order */ # }; # struct ip_mreqn # { # struct in_addr imr_multiaddr; /* IP multicast group address */ # struct in_addr imr_address; /* IP address of local interface */ # int imr_ifindex; /* interface index */ # }; def _createBoundSocket(multicastGroup, multicastPort, interface): s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) s.bind((multicastGroup, multicastPort)) mreqn = struct.pack('4s4si', socket.inet_aton(multicastGroup), socket.inet_aton(interface), 0) s.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreqn) return s def _receive(s): while True: buf, address = s.recvfrom(4096) print('received {} bytes from {}'.format(len(buf), address)) def _main(): args = _parseCmdLine() with autoClose(_createBoundSocket(args.group, args.port, args.interface)) as s: _receive(s) @contextmanager def autoClose(resource): try: yield resource finally: resource.close() def _parseCmdLine(): parser = ArgumentParser(description='Tool to receive multicast traffic', formatter_class=RawDescriptionHelpFormatter) parser.add_argument('--group', '-g', required=True, help='multicast group') parser.add_argument('--port', '-p', type=int, required=True, help='port') parser.add_argument('--interface', '-i', default='0.0.0.0', help='address of interface to listen on; default 0.0.0.0') return parser.parse_args() if __name__ == '__main__': _main()