This repository was archived by the owner on Nov 23, 2017. It is now read-only.
Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 185
This repository was archived by the owner on Nov 23, 2017. It is now read-only.
Can't receive replies to multicast UDP packets#480
Copy link
Copy link
Open
Description
It doesn't appear to be possible to receive replies to multicast UDP messages. Server-side multicast does work, but only with a bit of extra config.
Given the following (working) server code, adapted from the UDP Echo example:
import asyncio import logging import socket import struct BROADCAST_PORT = 1910 BROADCAST_ADDR = "239.255.255.250" class MulticastServerProtocol: def connection_made(self, transport): self.transport = transport def datagram_received(self, data, addr): print('Received{!r} from{!r}'.format(data, addr)) data = "I received{!r}".format(data).encode("ascii") print('Send{!r} to{!r}'.format(data, addr)) self.transport.sendto(data, addr) loop = asyncio.get_event_loop() loop.set_debug(True) logging.basicConfig(level=logging.DEBUG) sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) sock.bind(('', BROADCAST_PORT)) group = socket.inet_aton(BROADCAST_ADDR) mreq = struct.pack('4sL', group, socket.INADDR_ANY) sock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq) sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1) listen = loop.create_datagram_endpoint( MulticastServerProtocol, sock=sock, ) transport, protocol = loop.run_until_complete(listen) loop.run_forever() loop.close() ...the following non-asyncio client code sends a broadcast packet and correctly receives the responses:
import socket import struct import sys BROADCAST_PORT = 1910 BROADCAST_ADDR = "239.255.255.250" sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) sock.settimeout(3) ttl = struct.pack('b', 1) sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, ttl) try: sent = sock.sendto( sys.argv[1].encode("ascii"), (BROADCAST_ADDR, BROADCAST_PORT) ) while True: try: data, server = sock.recvfrom(1024) except socket.timeout: break else: print("Reply from{}:{!r}".format(server, data)) finally: sock.close() However, the following code, which I'm pretty sure is the asyncio equivalent, sends out the mutlicast packet correctly but never receives a response:
import asyncio import socket import struct import sys BROADCAST_PORT = 1910 BROADCAST_ADDR = "239.255.255.250" class DiscoveryClientProtocol: def __init__(self, loop): self.loop = loop self.transport = None def connection_made(self, transport): self.transport = transport sock = self.transport.get_extra_info('socket') sock.settimeout(3) ttl = struct.pack('b', 1) sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, ttl) self.transport.sendto(sys.argv[1].encode("ascii")) def datagram_received(self, data, addr): print("Reply from{}:{!r}".format(addr, data)) # Don't close the socket as we might get multiple responses. def error_received(self, exc): print('Error received:', exc) def connection_lost(self, exc): print("Socket closed, stop the event loop") self.loop.stop() loop = asyncio.get_event_loop() connect = loop.create_datagram_endpoint( lambda: DiscoveryClientProtocol(loop), remote_addr=(BROADCAST_ADDR, BROADCAST_PORT), ) transport, protocol = loop.run_until_complete(connect) loop.run_forever() transport.close() loop.close() Metadata
Metadata
Assignees
Labels
No labels