not seeing UDP multicast messages from another device
As covered in https://www.tldp.org/HOWTO/Multicast-HOWTO-6.html, the sockets API requires that you identify the interface as well as the multicast address/port you want to use.
By not specifying this in your sample code, you have left this down to the OS to pick and it has picked a VirtualBox Host-Only Network. Unfortunately this type of network is limited to VMs running on the Windows machines.
To fix it, you need to identify the interface that you want to use for the multicast and pass that in to your sending and receving code. For example:
sender.pysock.setsockopt(socket.SOL_IP, socket.IP_MULTICAST_IF, socket.inet_aton(MCAST_IF_IP))
receiver.pymreq = struct.pack('4s4s', group, socket.inet_aton(MCAST_IF_IP))
where MCAST_IF_IP
is the IP address of the interface that you want to use.
Send and receive IPv6 link-local multicast UDP datagrams in Python?
Here's a link to python mcast demo, does both IPv4 and IPv6.
How to use the options to socket() for IPv6 multicast UDP?
Eventually figured this out. Here's the correct way of doing this:
import socket
import struct
import select
import ipaddress
# .packet is a byte array
mcast_group = ipaddress.IPv6Address("ff22:5eea:675c:d1fc:17c::1")
address = ipaddress.IPv6Address("...ipv6 global scope address of interface...")
port_no = 5555
interface_idx = 3
sock = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
group = struct.pack("16s i",
mcast_group.packed,
3 #Interface ID
)
sock.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_JOIN_GROUP, group)
sock.bind((str(mcast_group), port_no, 0, interface_idx))
recv_socks, _, _ = select.select([sock], [], [], 10)
if recv_socks:
print("Received packet")
Important differences from the code in the question:
- UDP (
SOCK_DGRAM
) sockets need to be bound to a port number. AFAICT this is why I was getting ICMP traffic as well as UDP withSOCK_RAW
and no traffic at all withSOCK_DGRAM
. - Instead of binding the socket to a unicast address on the interface of interest, bind it to the multicast group but use the interface index as the
scope_id
(the fourth in the address tuple passed tosocket.bind()
).
How can I get my server to UDP multicast to clients across the internet? Do I need a special multicast IP address?
You can't multicast on the Internet. Full stop.
Basically, multicast is only designed to work when there's someone in charge of the whole network to set it up. As you noted, that person needs to assign the multicast IP addresses, for example.
Use UDP without specifc port for Multicast
This isn't possible using the BSD socket API (which is roughly the API Python exposes in its socket
module) - except by creating 2 ** 16 - 1 sockets and using them to bind to all ports.
It's possible using lower-level interfaces such as the TUN/TAP system offered by Linux.
Related Topics
How to Sandbox Python in Pure Python
Find_Element_By_* Commands Are Deprecated in Selenium
Using Pandas .Append Within for Loop
How to Run Python Code from Sublime Text 2
Why am I Getting Attributeerror: Object Has No Attribute
Creating a Pandas Dataframe from a Numpy Array: How to Specify the Index Column and Column Headers
Converting String with Utc Offset to a Datetime Object
What Does It Mean to "Call" a Function in Python
Zip Variable Empty After First Use
Insert a Row to Pandas Dataframe
How to Add an Image or Icon to a Button Rectangle in Pygame
How to Access the Child Classes of an Object in Django Without Knowing the Name of the Child Class
Purpose of "%Matplotlib Inline"