簡體   English   中英

在一個套接字上訂閱多個多播組 (Linux, C)

[英]Subscribing to multiple multicast groups on one socket (Linux, C)

是否可以從單個套接字上的多個多播組接收數據?

例如:

void AddGroup(int sock,
              const char* mc_addr_str,
              int mc_port,
              const char* interface) {
  struct sockaddr_in mc_addr;
  memset(&mc_addr, 0, sizeof(mc_addr));
  mc_addr.sin_family      = AF_INET;
  mc_addr.sin_addr.s_addr = inet_addr(mc_addr_str);
  mc_addr.sin_port        = htons(mc_port);

  if ((bind(sock, (struct sockaddr *) &mc_addr,
            sizeof(mc_addr))) < 0) {
    perror("bind() failed");
    exit(1);
  }

  // construct an IGMP join request structure
  struct ip_mreq mc_req;
  mc_req.imr_multiaddr.s_addr = inet_addr(mc_addr_str);
  mc_req.imr_interface.s_addr = inet_addr(interface);

  if ((setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP,
                  (void*) &mc_req, sizeof(mc_req))) < 0) {
    perror("setsockopt() failed");
    exit(1);
  }
}

當我添加一個多播組時,此代碼有效。 但是當我嘗試添加另一個時,“綁定”失敗。 我不太明白為什么首先需要綁定? (但沒有它代碼就無法工作)。

理想情況下,我想在同一個套接字上多次調用 AddGroup。 這可能嗎? 或者我是否需要每組一個套接字然后只使用輪詢?

您可以使用帶有 IP_ADD_MEMBERSHIP 選項的適當的setsockopt()調用,而不是 bind(),加入任意數量的多播組。

您可以在單個套接字上加入任意數量的多播組。 請參閱 setsockopt(), IP_PKTINFO 以獲取識別您正在讀取數據的多播組的方法。

您只綁定一次套接字。 第二次跳過綁定,看看會發生什么。

bind到被動地址,即 IPv4 的 0.0.0.0 並使用 ASM 或 SSM 拉入其他組,例如列出的IP_ADD_MEMBERSHIP

您只能bind一次。

是的,這是可能的:查看鏈接中的示例 ( http://www.tenouk.com/Module41c.html ) 要通過幾個步驟來縮短它:

  1. 你用 SO_REUSEADDR 設置了
  2. 您綁定 INADDR_ANY
  3. 您可以在要從中接收數據報的每個組上使用 IP_ADD_MEMBERSHIP 設置ockopt。
  4. 在我看來,使用 IP_PKTINFO 提供了一個選項來區分接收到的數據包,但發送方必須注意准備它們( 為 UDP 套接字設置源 IP

在基於 Unix 的操作系統中:

如果需要綁定到多播地址,則不能多次調用bind() 當您期望使用相同目標端口的多個多播流和在同一設備中運行的多個進程接收這些多播時,您將需要綁定到多播地址。

例如,當您有多播流:239.0.0.1:1234、239.0.0.2:1234、239.0.0.3:1234 和 239.0.0.4:1234,並且您想接收 239.0.0.1、239.0.0 和 239.0-A 時。想要在進程 B 中接收 239.0.0.3、239.0.0.4,當進程 A 和 B 在同一設備上運行時,您無法完成此操作。

我不相信在給定套接字上加入多個多播組是不可能的。 套接字由源IP /端口和目標IP /端口的配對定義。 操作系統不知道如何處理來自第二個ip / port的數據,因為它沒有一個套接字來發送它。

綁定是注冊與操作系統的連接所必需的。 它基本上就像注冊文件句柄一樣。

執行此操作的最佳方法是為每個多播組創建一個套接字,然后調用select()。 如果任何套接字有數據可供讀取,select()將通知您。

有關socket(),bind()和select()的更多信息,請查看您的手冊頁。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM