【问题标题】:IP_ADD_MEMBERSHIP on a socket, will the socket listen to unicast also?套接字上的 IP_ADD_MEMBERSHIP,套接字也会监听单播吗?
【发布时间】:2013-10-31 08:59:47
【问题描述】:

考虑下面的代码,

我正在尝试为多播绑定 UDP 套接字。
我已经将它绑定到一个特定的端口,并设置IP_ADD_MEMBERSHIP作为监听地址。

我的问题:套接字会接收到该端口的单播 UDP 数据包吗?如果是这样,我该如何预防?我希望只接收多播。

int fd;
if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
{
    perror("socket");
    exit(1);
}

u_int yes = 1;
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0)
{
    perror("Reusing ADDR failed");
    exit(1);
}

struct sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = (source_iface.empty()
                          ? htonl(INADDR_ANY)
                          : inet_addr(source_iface.c_str()));

if (bind(fd,(struct sockaddr *)&addr, sizeof(addr)) < 0)
{
    perror("bind");
    exit(1);
}

struct ip_mreq mreq;
mreq.imr_multiaddr.s_addr = inet_addr(group.c_str());
mreq.imr_interface.s_addr = (source_iface.empty()
                               ? htonl(INADDR_ANY)
                               : inet_addr(source_iface.c_str()));

if (setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0)
{
    perror("setsockopt");
    exit(1);
}

【问题讨论】:

  • 也许您想查看传入数据包的目标 IP 地址(如 stackoverflow.com/questions/5281409/… 所述)并在该 IP 地址不是多播 IP 地址时忽略该数据包? (OTOH,您可能想查看为什么您不想接收单播数据包 - 大概是出于充分的理由将它们发送给您)

标签: c++ sockets udp multicast setsockopt


【解决方案1】:

我相信您还需要在您想要收听的特定多播地址上bind,而不仅仅是在 setsockopt 调用中 - 后者也需要确保网卡和 IGMP也做正确的事。

另见What does it mean to bind a multicast (UDP) socket?

【讨论】:

  • 在代码中,我看到了一个bind() 调用,尽管INADDR_ANY 在这种情况下可能是错误的......
  • @AlexisWilke INADDR_ANY 不是多播地址,如果提供的解决方案是正确的,那么在这种情况下当然是错误的。
【解决方案2】:

好的,我让我的实例工作,所以我知道问题出在哪里。 bind() 必须针对多播 IP 地址发生:

struct sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = (group.empty()
                          ? htonl(INADDR_ANY)   // <-- this will work here but not below
                          : inet_addr(group.c_str()));

if (bind(fd,(struct sockaddr *)&addr, sizeof(addr)) < 0)
{
    perror("bind");
    exit(1);
}

这里的区别是group 而不是source_iface。在我改变它之前,它根本不会接收广播数据包。

【讨论】:

    猜你喜欢
    • 2011-02-15
    • 2013-03-29
    • 1970-01-01
    • 1970-01-01
    • 2023-03-09
    • 2016-04-06
    • 2016-10-12
    • 2010-11-09
    • 2011-11-09
    相关资源
    最近更新 更多