2016-04-11 27 views
0

我試圖寫多點傳送服務器。我有兩個問題:與INADDR_ANY的套接字綁定和具有多接口的多播的特定接口

  1. 如何在多個接口(如ethernet/wifi接口)上發送多播通知。我是否需要爲每個接口創建多個套接字並綁定?

  2. 當使用INADDR_ANY地址綁定套接字時,描述符已準備好執行I/O操作(使用select調用),但是當我使用特定接口地址(例如ethernet/wifi)綁定時,描述符尚未準備好執行任何被卡住的操作只在選擇API。 那麼綁定一個套接字與默認地址(INADDR_ANY)或特定的接口地址有什麼區別?

    int sd = socket(AF_INET, SOCK_DGRAM, 0); 
    if (sd < 0) { 
         printf("scoket() failed"); 
         return sd; 
    } 
    
    int r = -1; 
    
    int on = 1; 
    if ((r = setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, (char *) &on, sizeof(on))) < 0) { 
         printf("recv setsockopt(SO_REUSEADDR) failed"); 
         return r; 
    } 
    // add membership to receiving socket 
    struct ip_mreq mreq; 
    memset(&mreq, 0, sizeof(struct ip_mreq)); 
    mreq.imr_interface.s_addr = htonl(INADDR_ANY); 
    mreq.imr_multiaddr.s_addr = inet_addr(MDNS_ADDR); 
    if ((r = setsockopt(sd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *) &mreq, sizeof(mreq))) < 0) { 
         printf("recv setsockopt(IP_ADD_MEM) failed"); 
         return r; 
    } 
    // enable loopback in case someone else needs the data 
    if ((r = setsockopt(sd, IPPROTO_IP, IP_MULTICAST_LOOP, (char *) &on, sizeof(on))) < 0) { 
         printf("recv setsockopt(IP_MULTICAST_LOOP) failed"); 
         return r; 
    } 
    
    
    #ifdef IP_PKTINFO 
    if ((r = setsockopt(sd, SOL_IP, IP_PKTINFO, (char *) &on, sizeof(on))) < 0) { 
         printf("recv setsockopt(IP_PKTINFO) failed"); 
         return r; 
    } 
    #endif 
    /* bind to an address */ 
    struct sockaddr_in serveraddr; 
    memset(&serveraddr, 0, sizeof(serveraddr)); 
    serveraddr.sin_family = AF_INET; 
    serveraddr.sin_port = htons(MDNS_PORT); 
    //serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);  /* receive multicast */ 
    serveraddr.sin_addr.s_addr = inet_addr("192.168.10.23");  /* receive multicast */ 
    if ((r = bind(sd, (struct sockaddr *)&serveraddr, sizeof(serveraddr))) < 0) { 
         printf("recv bind()"); 
    } 
    

在線程等待描述符準備好I/O(基本上所有的讀取文件描述符)

  FD_ZERO(&sockfd_set); 
      FD_SET(svr->sockfd, &sockfd_set); 
      FD_SET(svr->notify_pipe[0], &sockfd_set); 
      printf("before select\n"); 
      select(max_fd + 1, &sockfd_set, NULL, NULL, NULL); 
      printf("after select\n"); 

當INADD_ANY地址插座ID綁定選擇將收益和我能夠使用文件描述符進行讀取,但是當使用特定接口進行綁定時,則選擇永不返回,因爲沒有可供讀取的文件描述符。

+0

當你綁定到'INADDR_ANY'然後調用'select'時,你會*檢查'select'返回什麼?並檢查'sockfd_set'中設置了哪些描述符?並談論錯誤,是任何系統調用失敗,你應該真的打印[錯誤](http://man7.org/linux/man-pages/man3/errno.3.html)(也許在[ strerror'](http://man7.org/linux/man-pages/man3/strerror.3.html))。 –

+1

我已經將套接字描述符添加到sockfd_set,並且選擇將在與INADDR_ANY綁定後返回1,之後我使用FD_ISSET檢查套接字描述符並對特定描述符執行讀取操作。在其他情況下,select沒有返回,因爲我沒有提到超時。 – Narrator

+0

當接收多播時,總是綁定到'INADDR_ANY'。在Linux中,如果綁定到特定的接口,您將無法接收多播。 – dbush

回答

0

綁定具有特定地址的套接字是將其鎖定到設備的通用方法。這種方法有點舊,因爲程序啓動後地址可以在設備上更改。一般來說,我會建議綁定到INADDR_ANY。

您可以隨時更改套接字上的輸出多播設備。

選項來考慮:

人7 IP:
IP_MULTICAST_ALL - 提供的所有設備(默認爲1)
IP_MULTICAST_IF - 我敢肯定,這只是將輸出設備設置

人7座:
SO_BINDTODEVICE

只是用一下選項,看看結果是什麼

+1

IP_MULTICAST_IF設置通過其爲套接字發送相關IGMP消息的接口。沒有其他的。 – EJP

0
  1. 如何在多個接口(如ethernet/wifi接口)上發送多播通告。我是否需要爲每個接口創建多個套接字並綁定?

號遍歷網絡接口並調用setsockopt()與適當的加入對依次在每個接口的參數。你只需要一個插座。

  • 當綁定套接字與INADDR_ANY地址,描述符是準備做I/O操作(使用select調用)
  • 這不是正確的。您的代碼只會檢查可讀性。

    但是當我與特定的接口地址e.g以太網/ WIFI綁定則描述符不準備進行任何操作

    同樣,這不是正確的。你只是在檢查可讀性,而不是「任何操作」。所有這一切意味着沒有多播是通過你綁定的地址進入的。

    它被卡在選擇api只。那麼綁定套接字與默認地址(INADDR_ANY)或特定的接口地址有什麼區別?

    它決定您通過發送和接收的IP地址。

    相關問題