【发布时间】:2014-06-26 19:43:37
【问题描述】:
我需要从 eth0 接口发送多播数据并在 Linux 机器上的 eth1 上接收它。
我在 C 中有 2 个程序,PROG-1 确实设置了 IP_MULTICAST_IF 以便它从 eth0 发送,PROG-2 确实加入了 eth1 上的 mcast 组(使用 netstat -ng 验证),但在 eth1 上看不到任何多播流量。我只能在 eth0 上看到多播数据。我增加了 TTL 但没有帮助。有什么方法可以在 eth1 上接收从 eth0 发送的多播?
IP_MULTICAST_LOOP 也无济于事,它仅在两个程序在同一接口上工作时才有效,这对我没有好处。
它是基于 ipv4 的自定义协议。
发件人代码:
sock_fd = socket( AF_INET, SOCK_RAW, 100 );
srcip = inet_addr("10.1.231.112"); /* src mcast from eth0 */
ret_val = setsockopt( sock_fd,
IPPROTO_IP,
IP_MULTICAST_IF,
&srcip,
sizeof( srcip ));
ttl = 0x2;
ret_val = setsockopt( sock_fd,
IPPROTO_IP,
IP_MULTICAST_TTL,
( char * ) &ttl,
sizeof( ttl ));
dest_addr.sin_addr.s_addr = inet_addr("224.100.1.102");
dest_addr.sin_family = AF_INET;
dest_addr.sin_port = 0;
ret_val = sendto(sock_fd, (char *) buf,
(size_t) 64, 0, /* no flags */
(struct sockaddr *) &dest_addr, addr_len);
收货人代码:
sock_fd = socket( AF_INET, SOCK_RAW, 100 );
mreq.imr_multiaddr.s_addr = inet_addr("224.100.1.102");
mreq.imr_interface.s_addr = inet_addr("10.0.3.15"); /* join on eth1 */
ret_val = setsockopt( sock_fd,
IPPROTO_IP,
IP_ADD_MEMBERSHIP,
( char * ) &mreq,
sizeof( mreq ));
msglen = recvfrom(sock_fd, buf, 4096, 0,
(struct sockaddr*)&addr_struct, &addr_len);
我用 netstat -ng 验证了接收者加入了 eth1 上的组,但发送者发送的消息仅在 eth0 上可见(eth1 上的wireshark 不会捕获任何内容)。
让我解释一下我面临的确切问题。我有一个通常在专有硬件上运行的生产代码。这是一个用于网络通信的软件。所有通信都是通过多播完成的。架构是有一个 TX 任务正在向网络中的其他设备发送多播数据,不幸的是,还有一个 RX 任务也加入了与 TX 任务发送数据相同的组,因为其他网络设备正在与我的设备通信在同一个 mcast 地址上。在生产代码中,我们禁用了多播循环,一切正常,RX 任务没有收到 TX 任务发送的内容。现在我们决定在一台 linux 机器上运行这个软件来进行测试,在同一台机器上我们想要运行一个模拟所有其他盒子的软件。我想要完成它以将生产代码上的所有 mcast 套接字“绑定”到 eth0 和 eth1 上的模拟器上。但是我不能让他们互相交流。我可以根据需要配置我的网络接口,添加 vlan、接口或任何东西,只是为了使其相互通信。我不能做的是改变这个软件的架构。
【问题讨论】:
-
这里使用什么协议(ipv4 或 v6)?指定了什么多播地址?你为什么不发布你的代码?
-
您的 2 个 NIC 是否位于不同的 IP 子网或 VLAN 上?如果是这样,您的路由器通常需要一些特殊的配置旋钮来传递它们之间的流量。
-
如何使用反射器,一个充当两个多播地址之间桥梁的辅助进程?您的反射器可能必须跟踪它已经转发的消息(以便每条消息仅通过反射器“桥”一次),但除此之外,它应该是一个非常简单的程序,特别是如果您在消息本身中有一些东西,在协议中,这使得唯一标识消息变得简单。