簡體   English   中英

如何通過接口過濾組播接收套接字?

[英]How to filter a multicast receiving socket by interface?

我需要創建兩個偵聽同一IP:端口但在不同接口上的套接字:

  1. socket0接收發送到接口eth0上的224.2.2.2:5000的UDP流量
  2. socket1接收發送到接口eth1上的224.2.2.2:5000的UDP流量

直到我意識到Linux將所有這些合並到相同的流量中之前,它似乎非常直接。 例如,假設eth1上只有流量,而且eth0沒有活動。 當我第一次創建socket0時,它不會接收任何數據,但是一旦我創建socket1(並加入多播組),socket0也將開始接收相同的數據。 我找到了解釋這一點的鏈接

現在這對我來說實際上是有道理的,因為我指定網絡接口的唯一時刻是使用ip_mreq.imr_interface.s_addr加入多播組setsockopt(socket,IPPROTO_IP,IP_ADD_MEMBERSHIP,...) 我相信這指定哪個接口加入組但與套接字將從哪個接口接收無關。

到目前為止我嘗試將套接字綁定到多播地址和端口,其行為如上所述。 我已經嘗試綁定到接口地址,但這在Linux上不起作用(雖然它似乎在Windows上這樣做),你在套接字上沒有收到任何流量。 最后,我嘗試綁定到INADDR_ANY但這不是我想要的,因為我將收到發送到端口的任何其他數據而不管目標IP,例如單播,並且它仍然不會停止來自其他的組播數據接口。

我不能使用SO_BINDTODEVICE因為它需要root權限。

所以我想知道的是,這是否可行。 如果不能做到那就沒關系,我會把它作為一個答案並繼續前進,我只是無法找到任何方法。 哦,我把這個問題標記為C因為這就是我們正在使用的東西,但我認為它真的可能不是特定於語言。

我沒有包含此代碼,因為我認為它更多的是理論問題,而不是源代碼的問題。 我們一直在使用套接字(多播或其他)一段時間沒有任何問題,這只是我們第一次必須處理多個接口。 但如果你認為它可能有所幫助,我可以寫一些最小的工作示例。


編輯 可能的重復

我認為我在這里嘗試實現的用例是不同的。 套接字應該從同一個組播組和端口(上例中的224.2.2.2:5000)接收數據,但只能從一個特定接口接收數據。 換句話說,兩個接口都從同一個組播組接收數據(但不同的網絡,因此數據不同),我需要每個套接字只能在一個接口上監聽。

我認為這個問題是關於同一端口上的多個組,而不是來自不同接口的相同組。 除非有一些我沒有看到的東西,實際上可能對我有所幫助。

是的,您可以在沒有root權限的情況下在Linux上執行您想要的操作:

綁定到INADDR_ANY並設置IP_PKTINFO套接字選項。 然后,您必須使用recvmsg()接收多播UDP數據包並掃描IP_PKTINFO控制消息。 這為您提供了收到的UDP數據包的一些邊帶信息:

struct in_pktinfo {
    unsigned int   ipi_ifindex;  /* Interface index */
    struct in_addr ipi_spec_dst; /* Local address */
    struct in_addr ipi_addr;     /* Header Destination address */
};

ipi_ifindex是接收數據包的接口索引。 (您可以使用變成一個接口名稱此if_indextoname()或其他方式輪if_nametoindex()

正如您在Windows上所說的那樣,相同的網絡功能具有不同的語義,特別是對於UDP,甚至更多用於多播。

UDP套接字的IP地址的Linux bind()語義大多沒用。 它本質上只是一個目標地址過濾器。 您幾乎總是希望綁定到INADDR_ANY以獲取UDP套接字,因為您不關心數據包的發送地址,也不想接收多個地址的數據包(例如,接收單播和多播)。

暫無
暫無

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

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