For IPv4, the index of the network interface is the IP address; for IPv6 the index of the network interface is returned by the method socket.getaddrinfo
.
The code below shows how to listen to multicast on all network interfaces:
from socket import AF_INET6, AF_INET
import socket
import struct
# Bugfix for Python 3.6 for Windows ... missing IPPROTO_IPV6 constant
if not hasattr(socket, 'IPPROTO_IPV6'):
socket.IPPROTO_IPV6 = 41
multicast_address = {
AF_INET: ["224.0.1.187"],
AF_INET6: ["FF00::FD"]
}
multicast_port = 5683
addr_info = socket.getaddrinfo('', None) # get all ip
for addr in addr_info:
family = addr[0]
local_address = addr[4][0]
sock = socket.socket(family, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind((local_address, multicast_port))
if family == AF_INET:
for multicast_group in multicast_address[family]:
sock.setsockopt(
socket.IPPROTO_IP,
socket.IP_ADD_MEMBERSHIP,
socket.inet_aton(multicast_group) + socket.inet_aton(local_address)
)
elif family == AF_INET6:
for multicast_group in multicast_address[family]:
ipv6mr_interface = struct.pack('i', addr[4][3])
ipv6_mreq = socket.inet_pton(socket.AF_INET6, multicast_group) + ipv6mr_interface
sock.setsockopt(
socket.IPPROTO_IPV6,
socket.IPV6_JOIN_GROUP,
ipv6_mreq
)
# _transport, _protocol = await loop.create_datagram_endpoint(
# lambda: protocol_factory(), sock=sock)