【问题标题】:UDP multicast message is not able to send and receive between Docker conatinersUDP 多播消息无法在 Docker 容器之间发送和接收
【发布时间】:2020-12-15 07:01:55
【问题描述】:

我正在尝试从容器 1 发送 UDP 多播消息并尝试在容器 2 上接收它。我已使用 --link 选项将容器 2 与容器 1 链接起来。我正在使用这些示例代码进行测试

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))

容器 2(接收器)上的端口 5007 使用 -p 5007:5007/udp 选项和 docker run 发布

当我在同一个容器上运行发送者和接收者时,消息被正确发布和接收。但是在两个不同的容器中运行时,消息没有被接收

更新

当使用--network=host 选项运行这些容器时,我们能够建立连接。但是有什么办法可以通过docker的默认桥接网络实现这一点

【问题讨论】:

  • 另外,顺便说一下,无需使用 -p 将端口公开给您的主机。由于您将绑定到主机上的该端口,因此这只会使事情不太可能起作用。

标签: python-3.x udp multicast udpclient


【解决方案1】:

这些行并不像你认为的那样:

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

INADDR_ANY 是通配符地址,但是当与IP_ADD_MEMBERSHIP 一起使用时,这意味着它将选择“默认”接口——不是所有接口。如果要添加所有接口,则需要遍历所有接口并为每个接口显式添加成员资格。在您的情况下,您可能只想为该容器添加具有 docker bridge ip 的成员资格。

这样的事情对我有用:

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),
)

我遇到了与您完全相同的问题,并找到了以下对我有帮助的答案:

对于 INADDR_ANY 并不意味着全部的见解: https://stackoverflow.com/a/46075375/2069572

对于 IP_ADD_MEMBERSHIP 特定地址的语法 https://stackoverflow.com/a/6102513/2069572

如果您确实想添加所有接口,则需要循环执行。此答案将使您走上正确的轨道,以弄清楚如何获取与您的接口关联的所有地址: https://stackoverflow.com/a/24196955/2069572

【讨论】:

    猜你喜欢
    • 2012-06-05
    • 2019-05-12
    • 2018-02-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-10
    • 2018-11-03
    • 2023-04-02
    相关资源
    最近更新 更多