2017-01-26 37 views
2

我正在處理一箇舊的代碼庫,其中ipv6多播看起來不起作用。當我嘗試將套接字綁定到ff01 :: 1時,它失敗。套接字正在我的以太網接口中創建。使用普通套接字的ipv6多播有什麼要求?

將套接字綁定到in6addr_any(「::」)會導致綁定成功,但除了應用程序本身使用給定套接字發送的套接字外,沒有收到數據包(設置了IPV6_MULTICAST_LOOP) 。這些數據包似乎永遠不會離開應用程序。在嘗試捕獲以太網接口中的數據包時,它們在wireshark中不可見。只有傳入的外部多播數據包可見。他們都沒有達到我的申請。

系統是Ubuntu 16.04與Linux 4.4.0。

設置代碼的樣品:在IPv6多點地址

#define MCASTADDRC "ff01::1" 

    int mcast::bind_mcast(const char *interface) { 

    this->net = socket(AF_INET6, SOCK_DGRAM, 0);   
    inet_pton(AF_INET6,MCASTADDRC,&this->multicast.ipv6mr_multiaddr); 

    this->ifaceaddr.sin6_family = AF_INET6; 
    this->ifaceaddr.sin6_port = htons(SRVPORT); 
    this->ifaceaddr.sin6_addr = in6addr_any; 

    // interface for multicast 
    this->mcastaddr.sin6_family = AF_INET6; 
    this->mcastaddr.sin6_port = htons(SRVPORT); 
    this->mcastaddr.sin6_addr = this->multicast.ipv6mr_multiaddr; 


    int opcoes = fcntl(this->net, F_GETFL, 0); 

    if (fcntl(this->net, F_SETFL, opcoes | O_NONBLOCK) == -1) { 
     // fail 
     return(false); 
    } 

    if (bind(net, (struct sockaddr *) &this->ifaceaddr, sizeof(this->ifaceaddr)) == -1) { 
     // fail      
     return(false); 
    } 

    this->ifaceindex = if_nametoindex(interface); 
    this->multicast.ipv6mr_interface = this->ifaceindex; 
    this->ifaceaddr.sin6_scope_id = this->ifaceindex; 

    int mcast_loop = 1; 
    if (setsockopt(this->net, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &mcast_loop, sizeof(mcast_loop))) { 
     //fail 
     return(false); 
    } 

    if (setsockopt(this->net, IPPROTO_IPV6, IPV6_MULTICAST_IF, &this->ifaceindex, sizeof(this->ifaceindex))) { 
     //fail 
     return(false); 
    } 

    if (setsockopt(this->net, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &this->multicast, sizeof(this->multicast))) { 
     //fail 
     return(false); 
    } 
    int optval = 6000000; 
    int optlen = sizeof(optval); 
    if (setsockopt(this->net, SOL_SOCKET, SO_RCVBUF, &optval, sizeof(optval))) { 

     exit(0); 
    } 
    if (getsockopt(this->net, SOL_SOCKET, SO_RCVBUF, &optval, (socklen_t *)&optlen)) { 
     // fail 
     exit(0); 
    } 

    if(optval < 262142) { 
     // buffer is too small, we failed 
     exit(0); 
    } 

    return(true); // success 

} 
+0

這是C++,而不是c! – Olaf

+0

@Olaf你是對的,只是因爲我使用的函數有C鏈接,這並不意味着我的代碼是C.我已經編輯了相應的問題。 –

回答

4

位12-15(開始於0)指定多播範圍。

形式爲ff01::/16的多播地址範圍爲1,表示接口本地。這些數據包不能通過任何網絡鏈路發送。這就是爲什麼你不能從其他主機接收任何類似地址的數據包。

您需要使用具有不同範圍值的地址。 2的範圍可以通過本地網絡發送,但不通過路由器發送,而範圍e(15)可以全局路由。

此外,運行程序時運行netstat -ng以確保您已加入正確的多播組在適當的接口。

有關更多詳細信息,請參閱維基頁面multicast addresses

+0

這有助於確定代碼中的錯誤。但後來我有這種非常奇怪的情況,因爲從其他主機發送的數據包全部被髮送到「ff01 :: 1」。所以發送到我的網卡的數據包本身就是鏈路本地的。這看起來不太好。 –

相關問題