我正在尝试在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 );发布于 2010-10-04 09:38:52
绑定过滤传入地址,因此如果您绑定到适配器地址,则只能获得具有匹配目标地址的数据包:即单播数据包,如果您绑定到多播地址,则只能获得多播数据包;要获得多播和单播数据包,您必须绑定到INADDR_ANY或IN6ADDR_ANY。
https://stackoverflow.com/questions/3851061
复制相似问题