multicast - multiple network interface @ 071's blog :: 隨意窩 Xuite日誌
    1. 沒有新回應!
  • 201310081455multicast - multiple network interface

    最近因為一個案子, 機子本身有 lan0/wlan0 二張網卡, 都要能由 Onvif test tool 來 discovery 到.

    原本只能由 lan0 收送 multicast 封包, 要改成同時能對 lan0/wlan0 收送 multicast 封包

    主要改動的地方如下:

    1. add multicast group 的地方要能 針對 lan0/wlan0 來 join group ,程式代碼如下

             //sudp 為主要接收 multicast 的 socket

             sudp = socket (AF_INET, SOCK_DGRAM, 0);

             memset (&sockudp_r, 0, sizeof (struct sockaddr_in));
             sockudp_r.sin_family = AF_INET;
             sockudp_r.sin_port = htons (3702);
             sockudp_r.sin_addr.s_addr = htonl (INADDR_ANY);   
       
             if (bind (sudp, (struct sockaddr *) &sockudp_r, sizeof (struct sockaddr_in)) < 0)
             {
                 perror ("bind");
                 exit (1);
             }
             setsockopt(sudp, SOL_SOCKET, SO_REUSEADDR, (const char*)&reuseFlag, sizeof(reuseFlag));
             setsockopt (sudp, SOL_SOCKET, SO_BROADCAST,(char*)&reuseFlag,sizeof(reuseFlag));
     
             imr.imr_multiaddr.s_addr = inet_addr (UPNP_MCAST_ADDR);
             imr.imr_interface.s_addr = inet_addr (gcIpAddress);//gcIpAddress為lan0的IPaddress
             //imr.imr_interface.s_addr = htonl(INADDR_ANY);
         
         
             setsockopt(sudp,IPPROTO_IP,IP_MULTICAST_LOOP,(const char*)&reuseFlag,sizeof(reuseFlag));
             setsockopt(sudp,IPPROTO_IP,IP_MULTICAST_TTL,(const char*)&ttl,sizeof(ttl));
             setsockopt(sudp,IPPROTO_IP,IP_MULTICAST_IF,(const char*)&imr.imr_interface.s_addr,sizeof(struct sockaddr_in));
             setsockopt(sudp,IPPROTO_IP,IP_ADD_MEMBERSHIP,(const char*)&imr,sizeof(imr));      
             
             //此處針對 wlan0 再使用 IP_MULTICAST_IF 來加入multicast 的 group

             imr.imr_interface.s_addr = inet_addr (gcIpAddress_w);//gcIpAddress_w為wlan0的IPaddress

             setsockopt(sudp,IPPROTO_IP,IP_MULTICAST_IF,(const char*)&imr.imr_interface.s_addr,sizeof(struct sockaddr_in));
             setsockopt(sudp,IPPROTO_IP,IP_ADD_MEMBERSHIP,(const char*)&imr,sizeof(imr));     

        while (1) {

          //後來找到為何無法 receive 到 multicast封包的原因, 是因為SO_BINDTODEVICE, 會導致socket只能針對某一網卡接收, 所以在執行 send 封包之後要在 receive 之前再 SO_BINDTODEVICE 到 空字串 來解除socket只針對某一網卡接收的情形

           char *IfName;

           IfName  = ""; //"eth0\0"
           if ( setsockopt(sudp,SOL_SOCKET,SO_BINDTODEVICE,IfName,strlen(IfName)) == -1 )
           {
             printf("mctest: setsockopt eth1 SO_BINDTODEVICE: %m\n");
           }

           // do recevfrom to received multicast packet from packet

        }

    2. 要發送 multicast 封包時, 可以指定要針對  lan0/wlan0 來做發送, 範例程式碼如下:

    //sNIC : eth0 / wlan0 , add by antony 20131008
    void send_hello(char* sNIC)
    {    
        int n=0;
        char SSDPannounce[2048]="\0";  //為要發送的內容  


        //之所以要再建立一個socket來發送multicast封包, 是因為使用原本recv用的socket( 在其針對二個network interface 加入multicast group 之後) , 會有問題, 導致其無法收到multicast 封包

    //後來找到為何無法 receive 到 multicast封包的原因, 是因為SO_BINDTODEVICE, 會導致socket只能針對某一網卡接收, 所以在執行 send 封包之後要在 receive 之前再 SO_BINDTODEVICE 到 空字串 來解除socket只針對某一網卡接收的情形

    //SO_BINDTODEVICE

    //       Bind this socket to a particular device like "eth0", as specified in the passed interface name. If the name is an empty string or the option length is zero, the socket   device   binding is   removed.   The passed option is a variable-length null terminated interface name string with the maximum size   of   IFNAMSIZ. If a socket is bound to an interface, only packets received from that particular interface are processed by the socket. Note that this   only   works   for   some   socket types, particularly AF_INET sockets. It is not supported   for   packet   sockets   (use   normal bind(8) there).


          
       //modify by antony begin , 20131004       
       struct ifreq ifr;
       char *IfName;
       
       memset(&ifr, 0, sizeof(ifr));
       strcpy(ifr.ifr_ifrn.ifrn_name, sNIC);
       ifr.ifr_addr.sa_family = AF_INET;
       //此處針對要發送的network interface :sNIC(lan0或wlan0)去發送
       if ((ioctl(sudp, SIOCGIFFLAGS, &ifr)>= 0)&&(ifr.ifr_flags&IFF_UP)) 
       {
           IfName  = sNIC; //"eth0\0"
        if ( setsockopt(sudp,SOL_SOCKET,SO_BINDTODEVICE,IfName,strlen(IfName)) == -1 )
           {
             printf("mctest: setsockopt eth1 SO_BINDTODEVICE: %m\n");
           }
            n = sendto (sudp, SSDPannounce, strlen (SSDPannounce), 0,
                      (struct sockaddr *) &sockudp_r, sizeof (struct sockaddr_in));
        
       }   
          //modify by antony end , 20131004 
                           
    }

     

    RTSP Client use...|日誌首頁|SYN Flood ( att...上一篇RTSP Client use OpenRTSP (live555) with H264/MJpeg...下一篇SYN Flood ( attact and Defense)...
    回應