2010-10-03 62 views
3

我試圖得到一個簡單的例子多播在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) 而不是單播地址(我已經嘗試鏈接本地和全局 地址),它確實獲取多播。我想知道是否有人可以指出我做錯了什麼。IPv6的組播偵聽在Linux上

服務器:

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); 

回答

3

綁定過濾傳入地址,所以如果你綁定到一個適配器地址只匹配目的地址獲取數據包:即單播數據包,如果綁定到多播地址,則只會獲得多播數據包;要獲取多播和單播數據包,您必須綁定到INADDR_ANY或IN6ADDR_ANY。

+0

是否記錄在某處?如果是這種情況,在綁定到單播地址的套接字上調用IPv6_JOIN_GROUP會返回一個錯誤,不是嗎? – Ray 2010-10-04 13:17:07

+0

的setsockopt的仍然有效,因爲它是一個有效的選項,請史蒂文斯的綁定() - > http://books.google.com.hk/books?id=ptSC4LpwGA0C&lpg=PA101&dq=stevens%20bind&hl=en&pg=PA103#v = onepage&q =史蒂文斯%20bind&F =假 – 2010-10-05 01:28:32