使用接口名称设置IP_MULTICAST_IF时,sendto中的参数无效

时间:2012-06-12 09:33:22

标签: sockets multicast sendto setsockopt

我正在编写一个发送和接收多播数据包的小程序。我需要设置输出接口的名称(例如eth0)而不是其地址。因此,我必须使用struct ip_mreqn(而不是struct in_addr),以便我可以使用其imr_ifindex字段来设置接口索引(我可以使用接口名称获得)。

但由于某种原因,它不起作用。对setsockopt()的调用工作正常,但是对sendto()的以下调用返回"无效的参数"错误。当然,如果我用in_addr替换ip_mreqn并使用interface' s地址,错误就会消失。

以下是我的代码:

sd = socket(AF_INET, SOCK_DGRAM, 0);

struct ip_mreqn addr;
addr.imr_ifindex = if_nametoindex("eth0");
setsockopt(sd, IPPROTO_IP, IP_MULTICAST_IF, &addr, sizeof(addr);

struct sockaddr_in sock_addr;
memset((char *) &sock_addr, 0, sizeof(sock_addr));
sock_addr.sin_family = AF_INET;
sock_addr.sin_port = destination_port;
sock_addr.sin_addr.s_addr = destination_address;

char msg[] = "abc";

while (sendto(sd, msg, sizeof(msg), 0, reinterpret_cast<const sockaddr*>(&sock_addr),
  sizeof(sock_addr)) < 0)
    throw std::runtime_error(strerror(errno));

设置IP_MULTICAST_IF时使用struct ip_mreqn有什么问题吗?有谁有任何想法?真的很感激帮助。感谢。

请注意,目标端口和地址已按网络字节顺序排列。

2 个答案:

答案 0 :(得分:4)

来自tldp's multicast howto

  

通常,系统管理员指定应从中发送默认接口多播数据报。程序员可以覆盖它并使用此选项为给定套接字选择具体的传出接口。

struct in_addr interface_addr;
setsockopt (socket, IPPROTO_IP, IP_MULTICAST_IF, &interface_addr, sizeof(interface_addr));

根据它们,只是接口的索引是不够的。

修改
您可能会将IP_MULTICAST_IFIPV6_MULTICAST_IF混淆,后者使用无符号整数来表示接口编号(请参阅man 7 ipv6)。

修改
事实证明,给出的例子按预期工作。这是我的完整测试用例:

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <net/if.h>
#include <arpa/inet.h>
#include <sys/socket.h>


int main()
{
    int sd = socket(AF_INET, SOCK_DGRAM, 0);
    struct sockaddr_in sa = {0};
    struct ip_mreqn addr = {{0}};
    char msg[] = "abc";

    addr.imr_ifindex = if_nametoindex("eth0");
    setsockopt(sd, IPPROTO_IP, IP_MULTICAST_IF, &addr, sizeof(addr));

    sa.sin_family = AF_INET;
    sa.sin_port = 8653;

    inet_pton(AF_INET, "224.255.255.5", &sa.sin_addr);
    if (sendto(sd, msg, sizeof(msg), 0, (void*)&sa, sizeof(sa)) < 0) {
        perror("bugger");
        return 1;
    }
    return 0;
}

答案 1 :(得分:0)

在答案的代码示例中,不要忘记hs().sin_port中的目标端口