Pratheesh
Pratheesh

Reputation: 635

UDP multicast message is not able to send and receive between Docker conatiners

I am trying to send a UDP multicast message from my container-1 and trying to receive it on container2.I have linked container-2 with container-1 using --link option .I am using these sample codes for testing

multicastsend.py

import socket
MCAST_GRP = '224.1.1.1'
MCAST_PORT = 5007
regarding socket.IP_MULTICAST_TTL
# ---------------------------------
# for all packets sent, after two hops on the network the packet will not
# be re-sent/broadcast (see https://www.tldp.org/HOWTO/Multicast-HOWTO-6.html)
MULTICAST_TTL = 2
    
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, MULTICAST_TTL)
    
# For Python 3, change next line to 'sock.sendto(b"robot", ...' to avoid the
# "bytes-like object is required" msg (https://stackoverflow.com/a/42612820)
sock.sendto(b"robot", (MCAST_GRP, MCAST_PORT))

multicastrec.py

import socket
import struct

MCAST_GRP = '224.1.1.1'
MCAST_PORT = 5007
IS_ALL_GROUPS = True

sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
if IS_ALL_GROUPS:
    # on this port, receives ALL multicast groups
    sock.bind(('', MCAST_PORT))
else:
    # on this port, listen ONLY to MCAST_GRP
    sock.bind((MCAST_GRP, MCAST_PORT))
mreq = struct.pack("4sl", socket.inet_aton(MCAST_GRP), socket.INADDR_ANY)

sock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq)

while True:
  # For Python 3, change next line to "print(sock.recv(10240))"
  print (sock.recv(10240))

The port 5007 on container-2(receiver) is published using -p 5007:5007/udp option with docker run

When i run sender and receiver on the same container messages are getting published and received properly .But when running in two different containers messages are not getting received

UPDATE

when running these containers with --network=host option we are able to establish the connection . But is there any way to make this happen with default Bridge network of docker

Upvotes: 1

Views: 933

Answers (1)

Stephen
Stephen

Reputation: 2863

These lines don't do what you think they do:

mreq = struct.pack("4sl", socket.inet_aton(MCAST_GRP), socket.INADDR_ANY)
sock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq)

INADDR_ANY is the wildcard address, but when used with IP_ADD_MEMBERSHIP that just means that it will pick the 'default' interface--not all interfaces. If you want to add all interfaces, you will need to loop over all of your interfaces and add membership explicitly for each of them. In your case, you probably just want to add membership with docker bridge ip for that container.

Something like this worked for me:

bridge_ip = "172.19.0.1"  # change this to match the bridge IP for your container
sock.setsockopt(
     socket.SOL_IP,
     socket.IP_ADD_MEMBERSHIP,
     socket.inet_aton(MCAST_GRP) + socket.inet_aton(bridge_ip),
)

I the exact same question you had and found the following answers which helped me:

for the insight that INADDR_ANY does not mean all: https://stackoverflow.com/a/46075375/2069572

for the syntax to IP_ADD_MEMBERSHIP a specific address https://stackoverflow.com/a/6102513/2069572

If you really do want to add all of your interfaces, you will need to do that in a loop. This answer will get you on the right track for figuring out how to get all the addresses associated with your interfaces: https://stackoverflow.com/a/24196955/2069572

Upvotes: 2

Related Questions