如何使多播套接字无法接收单播数据

时间:2015-10-20 18:22:31

标签: c++ qt sockets multicast

有没有办法阻止加入多播组的套接字接收指向同一端口的单播数据?

套接字选项还是ioctl?我看到https://msdn.microsoft.com/en-us/library/windows/desktop/ms738712%28v=vs.85%29.aspx但似乎只是为了过滤哪些主机可以向你发送多播,而不是谁可以发送单播。

我正在使用Qt应用程序,所以如果有一种方法可以在Qt的套接字框架内执行此操作,那么很好,如果没有,那么恢复到常规旧的berkley套接字不是问题。

到目前为止我找到的唯一方法是非常hacky - 在绑定多播套接字之前创建第二个UDP套接字并将其绑定到端口确实有效。我猜我必须有更好的东西,但我还没找到它。

2 个答案:

答案 0 :(得分:1)

更糟糕的是:您甚至无法确定只收到针对您加入的地址的多播流量。您可能还会收到来自同一台计算机上运行的其他进程的组的多播流量,尽管它们与您的程序无关。

最好的(因为大多数便携式)解决方案不是尝试使用套接字选项解决此问题,而是检查收到的数据包以找出它们的目标并丢弃您不想接收的数据包。

您可以使用setsockopt(IP_PKTINFO)和recvmsg()来接收有关收到的UDP数据包的各种有用的元信息,包括通常非常有趣的目标IP地址,在您的情况下是多播地址。

答案 1 :(得分:0)

将套接字绑定到多播地址,将其添加到多播组,从而设置正确的接口。 这种方法已经在linux和OSX上进行了测试。

auto fd = socket(AF_INET, SOCK_DGRAM,0);

struct sockaddr_in sa;
sa.sin_family = AF_INET;
sa.sin_port = htons(MULTICAST_PORT);
inet_pton(AF_INET, INTERFACE_ADDRESS, &sa.sin_addr);

struct sockaddr_in multicast;
multicast.sin_family = AF_INET;
multicast.sin_port = htons(MULTICAST_PORT);
inet_pton(AF_INET, MULTICAST_ADDRESS, &multicast.sin_addr);

struct ip_mreqn req = {};
req.imr_ifindex = INTERFACE_INDEX;
req.imr_multiaddr = multicast.sin_addr;
req.imr_address = sa.sin_addr;

setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &req, sizeof(req))
setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, &req, sizeof(req))

bind(fd,(struct sockaddr*)&multicast, sizeof(multicast))

您可以将ip_mreqn替换为ip_mreq,它更易于移植,并且不需要接口索引。但是请注意,对于ipv6,需要接口索引才能加入多播组。

使用Qt,快速浏览https://doc.qt.io/qt-5/qtnetwork-multicastreceiver-receiver-cpp.html,我认为您需要做的就是将绑定调用的QHostAddress设置为groupAddress4。无法保证流量来自哪个设备。

您使用其他套接字的解决方案将无法移植,因为AFAIK没有将一个端口上的单播流量分派到多个套接字的定义方法。 (即:可能是循环轮询,可能是第一个绑定需要全部...)