加入乙個多播組 最簡單的情況

2021-05-28 17:59:51 字數 3188 閱讀 8829

應用程式通過命令字ip_add_membership把乙個socket加入到乙個多播組,ip_add_membership是乙個ip層的命令字,其呼叫使用的引數是結構體struct ip_mreq,其定義如下:

struct ip_mreq

;該結構體的兩個成員分別用於指定所加入的多播組的組ip位址,和所要加入組的那個本地介面的ip位址。該命令字沒有源過濾的功能,它相當於實現igmpv1的多播加入服務介面。

ip_setsockopt實現了該命令字,它通過呼叫ip_mc_join_group把socket加入到多播組。

表示socket的結構體struct inet_sock有乙個成員mc_list,它是乙個結構體struct ip_mc_socklist的指標,實際上乙個該結構體的鍊錶,該結構體的定義如下:

struct ip_mc_socklist

;next指向鍊錶的下乙個節點;multi表示組資訊,即在哪乙個本地介面上,加入到哪乙個多播組;sfmode是過濾模式,取值為mcast_include或mcast_exclude,分別表示只接收sflist所列出的那些源的多播資料報,和不接收sflist所列出的那些源的多播資料報;sflist是源列表,結構體struct ip_sf_socklist的定義如下:

struct ip_sf_socklist

;sl_addr是源位址列表,sl_count應該是源位址列表中源位址的數量,sl_max應該是當前sl_addr陣列的最大可容納量(不確定)。對於通過呼叫ip_add_membership加入的多播組,它會在struct inet_sock的mc_list的煉表頭新增如下乙個節點:

struct ip_mc_socklist

另外,乙個socket所允許加入的多播組的最大數量也是有限制的,mc_list中節點的數量不允許超過sysctl_igmp_max_memberships(預設為20)。

ip_mc_join_group還需要通過ip_mreq.imr_inte***ce的指定值找到要加入多播組的那個介面,並為介面設定狀態(即該介面要加入哪個多播組,過濾哪些源,也就是為該介面增加乙個組,如果要增加的組已存在,則增加該組的引用計數)。代表網路裝置介面的結構體struct in_device有乙個成員mc_list,這是乙個結構體struct ip_mc_list的鍊錶,該結構體的定義如下:

struct ip_mc_list

;inte***ce指向網路裝置介面,multicast即為加入的組的多播位址,users記錄當前有幾個socket在該介面上加入了該多播組。sfcount是乙個有兩個元素的陣列,分別記錄在該介面上加入多播組的socket的過濾模式為exclude和include的數量,sfmode為該介面本身的過濾模式。sources為源位址列表,該結構體具體內容稍後再分析。timer為主動報告定時器,當乙個介面(注意:不是socket)新加入到乙個多播組,需要向多播路由器傳送乙個igmp報告,以通知多播路由器需要向本地網路**該組的資料報。tm_running是乙個標誌,如果timer當前正在執行,則置1,否則置0。reporter也是乙個標誌,如果當前正要開始傳送igmp報告,則置該標誌為1,否則為0。unsolicit_count是當乙個介面新加入到乙個多播組時,傳送主動報告的次數,值賦為igmp_unsolicited_report_count(預設值為2)。loaded也是乙個標誌,當該介面上的該多播組被加入時,需要通知硬體過濾器,通知完成即置該標誌為1,否則為0。

該結構體比較複雜,先看通過ip_add_membership命令字把乙個socket加入到乙個新的多播組,會使struct in_device的mc_list中增加乙個什麼樣的節點。下面是生成的節點的情況:

struct ip_mc_list

新生成的節點加入到mc_list鍊錶中後,要通知網路裝置介面的硬體,以使它的過濾機制可以接收進該多播組的資料報,同時也要通知多播路由器。

首先要把多播位址對映成乙太網位址,對映規則是把多播ip位址的低23位放到乙太網多播位址01-00-5e-00-00-00(16進製制)的低23位。因為乙個ip組位址有28位有效位(除去高位的1110),所以有可能出現多個組位址被對映成同乙個乙太網多播位址,具體實現見ip_eth_mc_map。然後把這個mac位址加到硬體的過濾機制中。

具體的實現在函式dev_mc_add中。代表網路裝置介面的結構體struct net_device也有乙個成員mc_list,它是乙個結構體struct dev_mc_list的鍊錶,該結構體的定義如下:

struct dev_mc_list

;next指向鍊錶下乙個節點,dmi_addr是多播mac位址,dmi_addrlen為多播mac位址的長度,dmi_users是在節點被重複到加入到裝置上的次數,struct net_device還有乙個成員mc_count,用於記錄鍊錶中節點的數量。dev_mc_add建立乙個新的struct dev_mc_list節點,加入到鍊錶中,並通過呼叫網路裝置介面的成員函式set_multicast_list來啟用裝置的過濾機制。

最後一步傳送主動成員報告,這裡,首先忽略igmpv1和igmpv2存在的情況。如果要加入的多播組是igmp_all_hosts(224.0.0.1),則不需要傳送成員報告。否則啟用定時器struct in_device->mr_ifc_timer(介面狀態改變定時器),該定時器在裝置初始化的時候被建立,其超時處理函式是igmp_ifc_timer_expire,它傳送乙個igmpv3的報告,然後再次啟用定時器。也就是說,第乙個主動成員報告立即發出,然後在乙個0到igmp_unsolicited_report_interval(預設為10秒)之間的乙個時間後,發出第二個主動成員報告,連續發出igmp_unsolicited_report_count(預設值為2)個。

測試環境中要加入的多播組是224.0.1.1,發出的igmpv3報告如下:

資料                含義

22                  第3版成員關係報告

00                  8bit保留,必須為0

f8 fc               校驗和

00 00               16bit保留,必須為0

00 01               組記錄的數量,為1

下面為一條組記錄:

04                  型別為change_to_exclude_mode,改變到exclude過濾模式

00                  輔助資料長度

00 00               源位址的數量

e0 00 01 01         組位址224.0.1.1

加入乙個組播組

網路中的一台主機如果希望能夠接收到來自網路中其它主機發往某乙個組播組的資料報,那麼這麼主機必須先加入該組播組,然後就可以從組位址接收資料報。在廣域網中,還涉及到路由器支援組播路由等,但本文希望以乙個最為簡單的例子解釋清楚協議棧關於組播的乙個最為簡單明瞭的工作過程,甚至,我們不希望涉及到igmp包。我...

乙個簡單的C 多播委託的小例子

多播委託是指乙個由委託串成的鍊錶,當鍊表上的乙個委託被 時,所有鍊錶上該委託的後續委託將會被順序執行。需要注意,多播委託必須是同型別的,返回型別必須為void,並且不能帶輸入引數 但可以帶引用引數 system.muliticastdelegate定義了對多播委託的支援。class program ...

乙個簡單的Linux下組播通訊的例子

傳送端 include include include include include include define portnum 5000 define groupip 224.0.1.1 int main build address memset void addr,0,sizeof addr...