摘要: 本文試圖成為學習TCP/IP網絡組播技術的入門材料。文中介紹了組播通信的概念及原理,以及用於組播應用編程的Linux API的詳細資料。為了使讀者更加完整的了解Linux 組播的整體概念,文中對實現該技術的核心函數也做了介紹。在文章的最後給出了一個簡單的C語言套接字編程例子,說明如何創建組播應用程序。
一、導言
在網絡中,主機間可以用三種不同的地址進行通信:
單播地址(unicast):即在子網中主機的唯一地址(接口)。如IP地址:192.168.100.9或MAC地址:80:C0:F6:A0:4A:B1。
廣播地址:這種類型的地址用來向子網內的所有主機(接口)發送數據。如廣播IP地址是192.168.100.255,MAC廣播地址:FF:FF:FF:FF:FF。
組播地址:通過該地址向子網內的多個主機即主機群(接口)發送數據。
如果只是向子網內的部分主機發送報文,組播地址就很有用處了;在需要向多個主機發送多媒體信息(如實時音頻、視頻)的情況下,考慮到其所需的帶寬,分別向每一客戶端主機發送數據並不是個好辦法,如果發送主機與某些接收端的客戶主機不在子網之內,采用廣播方式也不是一個好的解決方案。
二、組播地址
大家知道,IP地址空間被劃分為A、B、C三類。第四類即D類地址被保留用做組播地址。在第四版的IP協議(IPv4)中,從224.0.0.0到239.255.255.255間的所有IP地址都屬於D類地址。
組播地址中最重要的是第24位到27位間的這四位,對應到十進制是224到239,其它28位保留用做組播的組標識,如下圖所示:
圖1 組播地址示意圖
IPv4的組播地址在網絡層要轉換成網絡物理地址。對一個單播的網絡地址,通過ARP協議可以獲取與IP地址對應的物理地址。但在組播方式下ARP協議無法完成類似功能,必須得用其它的方法獲取物理地址。在下面列出的RFC文檔中提出了完成這個轉換過程的方法:
RFC1112:Multicast IPv4 to Ethernet physical address correspondence
RFC1390:Correspondence to FDDI
RFC1469:Correspondence to Token-Ring networks
在最大的以太網地址范圍內,轉換過程是這樣的:將以太網地址的前24位最固定為01:00:5E,這幾位是重要的標志位。緊接著的一位固定為0,其它23位用IPv4組播地址中的低23位來填充。該轉換過程如下圖所示:
圖2 地址轉換示意圖
例如,組播地址為224.0.0.5其以太網物理地址為01:00:5E:00:00:05。
還有一些特殊的IPv4組播地址:
224.0.0.1:標識子網中的所有主機。同一個子網中具有組播功能的主機都是這個組的成員。
224.0.0.2:該地址用來標識網絡中每個具有組播功有的路由器。
224.0.0.0----224.0.0.255范圍內的地址被分配給了低層次的協議。向這些范圍內的地址發送數據包,有組播功能的路由器將不會為其提供路由。
239.0.0.0----239.255.255.255間的地址分配用做管理用途。這些地址被分配給局部的每一個組織,但不可以分配到組織外部,組織內的路由器不向在組織外的地址提供路由。
除了上面列出的部分組播地址外,還有許多的組播地址。在最新版本的RFC文檔“Assinged Numbers”中有完整的介紹。
下面的表中列出了全部的組播地址空間,同時還列出了相應的地址段的常用名稱及其TTL(IP包的存活時間)。在IPv4組播方式下,TTL有雙重意義:正如大家所知的,TTL原本用來控制數據包在網絡中的存活時間,防止由於路由器配置錯誤導致出現數據包傳播的死循環;在組播方式下,它還代表了數據包的活動范圍,如:數據包在網絡中能夠傳送多遠?這樣就可以基於數據包的分類來定義其傳送范圍。
范圍 TTL 地址區間 描述
節點(Node) 0 只能向本機發送的數據包,不能向網絡中的其它接口傳送
鏈路(Link) 1 224.0.0.0-224.0.0.255 只能在發送主機所在的一個子網內的傳送,不會通過路由器轉發。
部門 32 239.255.0.0-239.255.255.255 只在整個組織下的一個部門內(Department) 傳送
組織 64 239.192.0.0--239.195.255.255 在整個組織內傳送(Organization)
全局(Global)255 224.0.1.0--238.255.255.255 沒有限制,可全局范圍內傳送
三、組播的工作過程
在局域網內,主機的網絡接口將到目的主機的數據包發送到高層,這些數據包中的目的地址是物理接口地址或廣播地址。
如果主機已經加入到一個組播組中,主機的網絡接口就會識別出發送到該組成員的數據包。
因此,如果主機接口的物理地址為80:C0:F6:A0:4A:B1,其加入的組播組為224.0.1.10,則發送給主機的數據包中的目的地址必是下面三種類型之一:
接口地址:80:C0:F6:A0:4A:B1
廣播地址:FF:FF:FF:FF:FF:FF:FF:FF
組播地址:01:00:5E:00:01:0A
廣域網中,路由器必須支持組播路由。當主機中運行的進程加入到某個組播組中時,主機向子網中的所有組播路由器發送IGMP(Internet分組管理協議)報文,告訴路由器凡是發送到這個組播組的組播報文都必須發送到本地的子網中,這樣主機的進程就可以接收到報文了。子網中的路由器再通知其它的路由器,這些路由器就知道該將組播報文轉發到哪些子網中去。
子網中的路由器也向224.0.0.1發送一個IGMP報文(224.0.0.1代表組中的全部主機),要求組中的主機提供組的相關信息。組中的主機收到這個報文後,都各將計數器的值設為隨機值,當計數器遞減為0時再向路由器發送應答。這樣就防止了組中所有的主機同時向路由器發送應答,造成網絡擁塞。主機向組播地址發送一個報文做為對路由器的應答,組中的其它主機一旦看到這個應答報文,就不再發送應答報文了,因為組中的主機向路由器提供的都是相同的信息,所以子網路由器只需得到組中一個主機提供的信息就可以了。
如果組中的主機都退出了,路由器就收不到應答,因此路由器認為該組目前沒有主機加入,遂停止到該子網報文的路由。IGMPv2的解決方案是:組中的主機在退出時向224.0.0.2 發送報文通知組播路由器。
四、應用編程接口(API)
如果你有套接字編程的經驗,就會發現,對組播選項所進行的操作只需五個新的套接字操作。函數setsockopt()及getsockopt()用來建立和讀取這五個選項的值。下表中列出了組播的可選項,並列出其數據類型和描述:
IPv4 選項 數據類型 描 述
IP_ADD_MEMBERSHIP strUCt ip_mreq 加入到組播組中
IP_ROP_MEMBERSHIP struct ip_mreq 從組播組中退出
IP_MULTICAST_IF struct ip_mreq 指定提交組播報文的接口
IP_MULTICAST_TTL u_char 指定提交組播報文的TTL
IP_MULTICAST_LOOP u_char 使組播報文環路有效或無效
在頭文件中定義了ip_mreq結構:
struct ip_mreq {
struct in_addr imr_multiaddr; /* IP multicast address of group */
struct in_addr imr_interface; /* local IP address of interface */
};
在頭文件中組播選項的值為:
#define IP_MULTICAST_IF 32
#define IP_MULTICAST_TTL 33
#define IP_MULTICAST_LOOP 34
#define IP_ADD_MEMBERSHIP 35
#define IP_DROP_MEMBERSHIP 36
IP_ADD_MEMBERSHIP
若進程要加入到一個組播組中,用soket的setsockopt()函數發送該選項。該選項類型是ip_mreq結構,它的第一個字段imr_multiaddr指定了組播組的地址,第二個字段imr_interface指定了接口的IPv4地址。
IP_DROP_MEMBERSHIP
該選項用來從某個組播組中退出。數據結構ip_mreq的使用方法與上面相同。
IP_MULTICAST_IF
該選項可以修改網絡接口,在結構ip_mreq中定義新的接口。
IP_MULTICAST_TTL
設置組播報文的數據包的TTL(生存時間)。默認值是1,表示數據包只能在本地的子網中傳送。
IP_MULTICAST_LOOP
組播組中的成員自己也會收到它向本組發送的報文。這個選項用於選擇是否激活這種狀態。
五、一個組播通信的例子
下面給出一個簡單的例子實現文中闡述的思想:由一個進程向一個組播組發送報文,組播組中的相關進程接收報文,並將報文顯示到屏幕上。
下面的代碼實現了一個服務進程,它將標准輸入接口輸入的信息全部發送到組播組224.0.1.1。你會發現,將信息發送到組播組不需要特別的操作,只要設置好組播組的目的地址就足夠了。若在開發過程中,Loopback和TTL這兩個選項的默認值不適合應用程序,可以加以調整。
服務程序
將標准輸入端口的輸入發送到組播組224.0.1.1。
#include
#include
#include
#include
#include
#include
#define MAXBUF 256
#define PUERTO 5000
#defin