多播适用于 WSL1,但不适用于 WSL2

问题描述 投票:0回答:1

我有一个运行两个线程的小应用程序。

一个线程发送 UDP 多播数据包(到组 239.0.0.1),另一个线程读取相同的多播数据包。

当我使用 Visual Studio 在 Windows 上的应用程序上运行此程序时,它可以正常工作 - 数据包已成功发送和接收。我在 Wireshark 上看到了。我还有一个嵌入式目标,该应用程序最终在其中运行,运行 VxWorks RTOS,并且它也可以在 VxWorks 上运行。

我在 Linux 上使用 WSL2 进行了尝试。 sendto() 成功,但recvfrom() 失败。不过我确实在 Wireshark 上看到了数据包,并且 Wireshark 上没有报告任何错误。

我降级到 WSL1,它可以工作。

是否有 WSL2 特有的东西可能会导致多播失败,但可以在 WSL1、Windows 和 VxWorks 上工作?如果我切换到单播,它可以在 WSL2 上运行。

以下是一些代码片段:

接收线程:

uint32_t  ip_addr_mgrp;
uint32_t  ip_addr_mifc;
inet_pton(AF_INET, (char*)"172.18.19.53", &ip_addr_mifc);
inet_pton(AF_INET, (char*)"239.0.0.1", &ip_addr_mgrp);

int fd = socket(AF_INET, SOCK_DGRAM, SOCKET_PROTOCOL);

struct sockaddr_in server_addr;

server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = ip_addr_mifc;
server_addr.sin_port = htons(45007);

bind(fd, (struct sockaddr*)&server_addr, sizeof(server_addr));

struct ip_mreq mreq;
mreq.imr_multiaddr.s_addr = ip_addr_mgrp;
mreq.imr_interface.s_addr = ip_addr_mifc;

setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char*)&mreq, sizeof(mreq));

// code to set to non-blocking

// Loop for reading

// Call select()
// Call FD_ISSET()
// Call recvfrom()

TX 线程:

uint32_t  ip_addr_mgrp;
uint32_t  ip_addr_mifc;
inet_pton(AF_INET, (char*)"172.18.19.53", &ip_addr_mifc);
inet_pton(AF_INET, (char*)"239.0.0.1", &ip_addr_mgrp);

int fd = socket(AF_INET, SOCK_DGRAM, SOCKET_PROTOCOL);

struct ip_mreq mreq;
mreq.imr_multiaddr.s_addr = ip_addr_mgrp;
mreq.imr_interface.s_addr = ip_addr_mifc;

setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char*)&mreq, sizeof(mreq));

setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, (const char*)&mreq.imr_interface.s_addr, sizeof(struct in_addr));

char loop = 1;
setsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP, (char*)&loop, sizeof(loop));

// code to set to non-blocking

// Loop for sending

// Call sendto() to 237.0.0.1:45007
c sockets windows-subsystem-for-linux multicast
1个回答
0
投票

在 Linux 上,如果套接字绑定到本地 IP 地址,即使加入多播组,它也无法接收多播流量。

正如评论中提到的,WSL1 是 Windows 系统调用之上的 API 层,而 WSL2 是一个完整的 Linux 虚拟机。 这就是为什么绑定到本地接口在 WSL1 上有效但在 WSL2 上无效。

您可以通过将套接字绑定到

INADDR_ANY
或相关的多播地址(本例中为 239.0.0.1)来解决此问题。

© www.soinside.com 2019 - 2024. All rights reserved.