【问题标题】:Listening for IPv6 multicasts on Linux在 Linux 上侦听 IPv6 多播
【发布时间】:2011-04-20 13:06:59
【问题描述】:

我正在尝试让一个简单的多播示例在 Linux 上工作(我已经 尝试了 RHEL 4 2.6.9 和 Ubuntu 8.04 2.6.24)。总体思路是 我希望服务器绑定到单播地址,然后添加 自己到组 ff02::1。然后我希望它收到 多播发送到 ff02::1。下面的代码适用于 Mac OS X 10.5(在 事实上,在 OS X 上运行的服务器会收到从 Linux 发送的多播 客户端),但我无法让 Linux 服务器端工作。它没有 获取任何多播。如果我将代码更改为绑定到 :: (INADDR6_ANY) 而不是单播地址(我已经尝试过链接本地和全局 地址),它确实获得了多播。我想知道是否有人 可以指出我做错了什么。

服务器:

memset( &hint, 0, sizeof( hint ) );

hint.ai_family = AF_INET6;
hint.ai_socktype = SOCK_DGRAM;

// argv[1] is either a link-local or a global address
err = getaddrinfo( argv[1], NULL, &hint, &info );

if( err != 0 ) {
    perror( "getaddrinfo" );
    exit( 1 );
}

struct sockaddr_in6 * addr = (struct sockaddr_in6*)info->ai_addr;
//addr->sin6_addr = in6addr_any; // if this is uncommented, multicasts are received
addr->sin6_port = htons( 7890 );
s = socket( AF_INET6, SOCK_DGRAM, 0 );

if( bind( s, (struct sockaddr*) addr, info->ai_addrlen ) != 0 ) {
    close( s );
    perror( "bind" );
    exit( 1 );
}

if( getaddrinfo( "ff02::1", NULL, &hint, &multi ) != 0 ) {
    close( s );
    perror( "getaddrinfo" );
    exit( 1 );
}

struct ipv6_mreq mreq;
memset( &mreq, 0, sizeof(mreq) );
memcpy( &mreq.ipv6mr_multiaddr, &((struct sockaddr_in6 *) multi->ai_addr)->sin6_addr, sizeof(mreq.ipv6mr_multiaddr) );
mreq.ipv6mr_interface = 2; // 2 happens to be the interface ID; I've tried other values here
freeaddrinfo( multi );

if( setsockopt( s, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq) ) != 0 ) {
    close( s );
    perror( "IPV6_JOIN_GROUP" );
    exit( 1 );
}

for( ; ; ) {
    char data[6];
    size_t len;

    len = recvfrom( s, data, 5, 0, NULL, NULL );
    data[5] = '\0';

    printf( "Received %s\n", data );

    if( strcmp( data, "exitt" ) == 0 ) {
        break;
    }
}

客户端代码如下:

memset( &hint, 0, sizeof( hint ) );

hint.ai_family = AF_INET6;
hint.ai_socktype = SOCK_DGRAM;
hint.ai_protocol = 0;

err = getaddrinfo( "ff02::1", NULL, &hint, &info );

if( err != 0 ) {
    perror( "getaddrinfo" );
    return 0;
}

struct sockaddr_in6 * addr = (struct sockaddr_in6*)info->ai_addr;
addr->sin6_port = htons( 7890 );
addr->sin6_scope_id = 2; // 2 happens to be the interface ID
s = socket( AF_INET6, SOCK_DGRAM, 0 );

for( ; ; ) {
    char data[6];
    size_t len;

    scanf( "%5s", data );
    data[5] = '\0';
    printf( "Sending %s\n", data );
    if( sendto( s, data, 5, 0, info->ai_addr, info->ai_addrlen ) != 5 ) {
        printf( "Error sending\n" );
    }

    if( strcmp( data, "exitt" ) == 0 ) {
        break;
    }
}

close( s );

【问题讨论】:

    标签: c++ linux ipv6 multicast


    【解决方案1】:

    绑定过滤传入地址,因此如果您绑定到适配器地址,您只会收到与目标地址匹配的数据包:即单播数据包,如果您绑定到多播地址,您将只会获得多播数据包;要获取多播和单播数据包,您必须绑定到 INADDR_ANY 或 IN6ADDR_ANY。

    【讨论】:

    • 这是否记录在某处?如果是这种情况,在绑定到单播地址的套接字上调用 IPv6_JOIN_GROUP 会返回错误,不是吗?
    • setsockopt 仍然有效,因为它是一个有效选项,请咨询 Stevens 的 bind() -> books.google.com.hk/…
    猜你喜欢
    • 2017-05-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-06
    相关资源
    最近更新 更多