Linux網(wǎng)絡(luò)編程——多播

轉(zhuǎn)載 http://blog.csdn.net/tennysonsky/article/details/44493407#

概述
單播用于兩個(gè)主機(jī)之間的端對(duì)端通信,廣播用于一個(gè)主機(jī)對(duì)整個(gè)局域網(wǎng)上所有主機(jī)上的數(shù)據(jù)通信湘捎。單播和廣播是兩個(gè)極端垦江,要么對(duì)一個(gè)主機(jī)進(jìn)行通信,要么對(duì)整個(gè)局域網(wǎng)上的主機(jī)進(jìn)行通信。實(shí)際情況下钩述,經(jīng)常需要對(duì)一組特定的主機(jī)進(jìn)行通信,而不是整個(gè)局域網(wǎng)上的所有主機(jī)穆碎,這就是多播的用途牙勘。

IP 多播(也稱多址廣播或組播)技術(shù),是一種允許一臺(tái)或多臺(tái)主機(jī)(多播源)發(fā)送單一數(shù)據(jù)包到多臺(tái)主機(jī)(一次的所禀,同時(shí)的)的 TCP/IP 網(wǎng)絡(luò)技術(shù)方面。多播是 IPv6 數(shù)據(jù)包的 3 種基本目的地址類型之一,多播是一點(diǎn)對(duì)多點(diǎn)的通信, IPv6 沒有采用 IPv4 中的組播術(shù)語色徘,而是將廣播看成是多播的一個(gè)特殊例子恭金。

多播作為一點(diǎn)對(duì)多點(diǎn)的通信,數(shù)據(jù)的收發(fā)僅僅在同一分組中進(jìn)行褂策,是節(jié)省網(wǎng)絡(luò)帶寬的有效方法之一横腿。在網(wǎng)絡(luò)應(yīng)用中,當(dāng)需要將一個(gè)節(jié)點(diǎn)的信號(hào)傳送到多個(gè)節(jié)點(diǎn)時(shí)斤寂,無論是采用重復(fù)點(diǎn)對(duì)點(diǎn)通信方式耿焊,還是采用廣播方式,都會(huì)嚴(yán)重浪費(fèi)網(wǎng)絡(luò)帶寬遍搞,只有多播才是最好的選擇罗侯。多播能使一個(gè)或多個(gè)多播源只把數(shù)據(jù)包發(fā)送給特定的多播組,而只有加入該多播組的主機(jī)才能接收到數(shù)據(jù)包溪猿。

IP 多播應(yīng)用大致可以分為三類:點(diǎn)對(duì)多點(diǎn)應(yīng)用钩杰,多點(diǎn)對(duì)點(diǎn)應(yīng)用和多點(diǎn)對(duì)多點(diǎn)應(yīng)用。
1)點(diǎn)對(duì)多點(diǎn)應(yīng)用是指一個(gè)發(fā)送者诊县,多個(gè)接收者的應(yīng)用形式讲弄,這是最常見的多播應(yīng)用形式。典型的應(yīng)用包括:媒體廣播依痊、媒體推送避除、信息緩存、事件通知和狀態(tài)監(jiān)視等抗悍。

2)多點(diǎn)對(duì)點(diǎn)應(yīng)用是指多個(gè)發(fā)送者,一個(gè)接收者的應(yīng)用形式钳枕。通常是雙向請(qǐng)求響應(yīng)應(yīng)用缴渊,任何一端(多點(diǎn)或點(diǎn))都有可能發(fā)起請(qǐng)求。典型應(yīng)用包括:資源查找鱼炒、數(shù)據(jù)收集衔沼、網(wǎng)絡(luò)競拍、信息詢問等。

3)多點(diǎn)對(duì)多點(diǎn)應(yīng)用是指多個(gè)發(fā)送者和多個(gè)接收者的應(yīng)用形式指蚁。通常菩佑,每個(gè)接收者可以接收多個(gè)發(fā)送者發(fā)送的數(shù)據(jù),同時(shí)凝化,每個(gè)發(fā)送者可以把數(shù)據(jù)發(fā)送給多個(gè)接收者稍坯。典型應(yīng)用包括:多點(diǎn)會(huì)議、資源同步搓劫、并行處理瞧哟、協(xié)同處理、遠(yuǎn)程學(xué)習(xí)枪向、討論組勤揩、分布式交互模擬(DIS)、多人游戲等秘蛔。

多播地址
IP 多播通信必須依賴于 IP 多播地址陨亡,在 IPv4 中它是一個(gè) D 類 IP 地址,范圍從 224.0.0.0 到 239.255.255.255深员,并被劃分為局部鏈接多播地址负蠕、預(yù)留多播地址和管理權(quán)限多播地址三類:
1)局部鏈接多播地址范圍在 224.0.0.0~224.0.0.255,這是為路由協(xié)議和其它用途保留的地址辨液,路由器并不轉(zhuǎn)發(fā)屬于此范圍的IP包虐急;

2)預(yù)留多播地址為 224.0.1.0~238.255.255.255,可用于全球范圍(如Internet)或網(wǎng)絡(luò)協(xié)議滔迈;

3)管理權(quán)限多播地址為 239.0.0.0~239.255.255.255止吁,可供組織內(nèi)部使用,類似于私有 IP 地址燎悍,不能用于 Internet敬惦,可限制多播范圍。

一些多播組地址被 IANA 確定為知名地址谈山,它們也被當(dāng)作永久主機(jī)組俄删,這和 TCP 及 UDP 中的知名端口相似。同樣奏路,這些知名多播地址在 RFC 最新分配數(shù)字中列出畴椰,注意這些多播地址所代表的組是永久組,而它們的組成員卻不是永久的鸽粉。這些地址如下:
224.0.0.1 所有組播主機(jī)
224.0.0.2 所有組播路由器
224.0.0.4 DRMRP 路由器
224.0.0.5 所有 OSPF 的路由器
224.0.0.6 OSPF 指派路由器
224.0.0.9 RPIv2 路由器
224.0.0.10 EIGRP 路由器
224.0.0.13 PIM 路由器
224.0.0.22 IGMPv3
224.0.0.25 RGMP
224.0.1.1 NTP 網(wǎng)絡(luò)時(shí)間協(xié)議

多播地址與 MAC 地址的映射
使用同一個(gè) IP 多播地址接收多播數(shù)據(jù)包的所有主機(jī)構(gòu)成了一個(gè)主機(jī)組斜脂,也稱為多播組。一個(gè)多播組的成員是隨時(shí)變動(dòng)的触机,一臺(tái)主機(jī)可以隨時(shí)加入或離開多播組帚戳,多播組成員的數(shù)目和所在的地理位置也不受限制玷或,一臺(tái)主機(jī)也可以屬于幾個(gè)多播組。

這個(gè)我們可以這樣理解片任,多播地址就類似于 QQ 群號(hào)偏友,多播組相當(dāng)于 QQ 群,一個(gè)個(gè)的主機(jī)就相當(dāng)于群里面的成員对供。

** IPv4 的 D 類地址是多播地址**位他。IEEE 把一塊以太網(wǎng)多播組地址分給 IANA 以支持IP多播。塊的地址都以 01:00:5e 開頭犁钟,第 25 位為 0棱诱,低 23 位為 IPv4 多播地址( D類地址 )的低 23 位。IPv4 多播地址與 MAC 地址的映射關(guān)系如圖所示:


由于多播地址( D類地址 )中的最高 5bit 在映射過程中被忽略涝动,因此每個(gè)以太網(wǎng)多播地址對(duì)應(yīng)的多播組是不唯一的迈勋。32 個(gè)不同的多播組號(hào)被映射為一個(gè)以太網(wǎng)地址。例如醋粟,多播地址 224.128.64.32(十六進(jìn)制 e0.80.40.20)和 224.0.64.32(十六進(jìn)制 e0.00.40.20)都映射為同一以太網(wǎng)地址 01:00:5e:00:40:20靡菇。

既然地址映射是不唯一的,那么設(shè)備驅(qū)動(dòng)程序或 IP 層就必須對(duì)數(shù)據(jù)報(bào)進(jìn)行過濾米愿。因?yàn)榫W(wǎng)卡可能接收到主機(jī)不想接收的多播數(shù)據(jù)幀厦凤,如下圖,假如主機(jī) 1 加入的多播為 224.128.64.32育苟, 主機(jī) 2 加入的多播為 224.0.64.32较鼓,我們想給 224.0.64.32 所在的多播組 ( 主機(jī) 2 ) 發(fā)送信息,數(shù)據(jù)經(jīng)過網(wǎng)卡時(shí)违柏,224.128.64.32 (主機(jī) 1 ) 和 224.0.64.32 (主機(jī) 2 ) 所在多播組的網(wǎng)卡都會(huì)收到數(shù)據(jù)博烂,因?yàn)樗鼈兊?MAC 地址都是 01:00:5e:00:40:20。這時(shí)候漱竖,如果網(wǎng)卡不提供足夠的多播數(shù)據(jù)幀過濾功能禽篱,設(shè)備驅(qū)動(dòng)程序就必須接收所有多播數(shù)據(jù)幀,然后對(duì)它們進(jìn)行過濾馍惹,這個(gè)過濾過程是網(wǎng)絡(luò)驅(qū)動(dòng)或IP層自動(dòng)完成躺率。

Linux多播編程

套接口選項(xiàng)

**int setsockopt( int sockfd, int level,int optname,   **
**const void *optval, socklen_t optlen );**

成功執(zhí)行返回0,否則返回-1

選項(xiàng) IP_ADD_MEMBERSHIP 和 IP_DROP_MEMBERSHIP
加入或者退出一個(gè)多播組万矾,通過選項(xiàng) IP_ADD_MEMBERSHIP 和 IP_DROP_MEMBERSHIP悼吱,對(duì)一個(gè)結(jié)構(gòu) struct ip_mreq 類型的變量進(jìn)行控制,struct ip_mreq 原型如下:

struct in_addr{
in_addr_t s_addr;
}
struct ip_mreq          
{ 
struct in_addr imn_multiaddr; // 多播組 IP良狈,類似于 QQ 群號(hào)
struct in_addr imr_interface;   // 將要添加到多播組的 IP后添,類似于QQ 成員號(hào)

};

多播只能用 UDP 或原始 IP 實(shí)現(xiàn),不能用 TCP们颜。

加入多播實(shí)例:


#include <stdio.h>  
#include <stdlib.h>  
#include <unistd.h>  
#include <fcntl.h>  
#include <sys/socket.h>  
#include <netinet/in.h>  
#include <arpa/inet.h>  
#include <string.h>  
#include <errno.h>  
#include <sys/types.h>  
  
int main(int argc, char*argv[])    
{       
    int sockfd; // 套接字文件描述符    
    struct sockaddr_in local_addr; // 本地地址   
    int err = -1;   
    char group[16] = "224.0.0.88"; // 多播組 IP  
        
    sockfd = socket(AF_INET, SOCK_DGRAM, 0);  //建立套接字  
    if (sockfd == -1)    
    {    
        perror("socket()");    
        return -1;    
    }       
        
    // 初始化地址   
    memset(&local_addr, 0, sizeof(local_addr));    
    local_addr.sin_family = AF_INET;    
    local_addr.sin_addr.s_addr = htonl(INADDR_ANY);    
    local_addr.sin_port = htons(8000);  
        
    // 綁定socket    
    err = bind(sockfd,(struct sockaddr*)&local_addr, sizeof(local_addr));    
    if(err < 0)    
    {    
        perror("bind()");    
        return -2;    
    }      
  
    struct ip_mreq mreq; // 多播地址結(jié)構(gòu)體                                   
  
    // 加入多播組吕朵,相當(dāng)于創(chuàng)建一個(gè)QQ群,某人加入此群  
    mreq.imr_multiaddr.s_addr = inet_addr(group); // 多播地址窥突,類似于 QQ 群號(hào)   
    mreq.imr_interface.s_addr = htonl(INADDR_ANY);// 將本機(jī)加入多播組努溃,類似于某人加入此群  
    // 加入多播組  
    err = setsockopt(sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP,&mreq, sizeof(mreq));    
    if (err < 0)    
    {    
        perror("setsockopt():IP_ADD_MEMBERSHIP");    
        return -4;    
    }    
  
    int times = 0;    
    int addr_len = 0;    
    char buff[256] = {0};    
    int n = 0;   
  
    // 循環(huán)接收廣播組的消息,5次后退出  
    for(times = 0; times<5; times++)    
    {    
        addr_len = sizeof(local_addr);    
        memset(buff, 0, sizeof(buff));       
          
        // 接收數(shù)據(jù)   
        n = recvfrom(sockfd, buff, sizeof(buff), 0,(struct sockaddr*)&local_addr, &addr_len);    
        if( n== -1)     
        {    
            perror("recvfrom()");    
        }    
  
        printf("Recv %dst message from server:%s\n", times, buff);    
        sleep(2);     
    }    
        
    // 退出廣播組   
    err = setsockopt(sockfd, IPPROTO_IP, IP_DROP_MEMBERSHIP,&mreq, sizeof(mreq));    
            
    close(sockfd);   
  
    return 0;    
}   

以上代碼編譯運(yùn)行時(shí)阻问,可以會(huì)出現(xiàn)這樣的錯(cuò)誤:No such device梧税。這主要和網(wǎng)絡(luò)配置有關(guān),解決方法請(qǐng)點(diǎn)此鏈接:http://blog.csdn.net/tennysonsky/article/details/49050579称近。

向多播組發(fā)送信息的測試示例:


#include <stdio.h>  
#include <stdlib.h>  
#include <unistd.h>  
#include <fcntl.h>  
#include <sys/socket.h>  
#include <netinet/in.h>  
#include <arpa/inet.h>  
#include <string.h>  
#include <errno.h>  
#include <sys/types.h>  
  
int main(int argc, char*argv)  
{  
    int sockfd; // 套接字文件描述符  
    struct sockaddr_in dest_addr; // 目標(biāo)ip  
    char buf[] = "BROADCAST TEST DATA";  
  
    sockfd = socket(AF_INET, SOCK_DGRAM, 0); // 建立套接字  
    if (s == -1)  
    {  
        perror("socket()");  
        return -1;  
    }  
  
    // 初始化目標(biāo) ip 信息  
    memset(&dest_addr, 0, sizeof(dest_addr));  
    dest_addr.sin_family = AF_INET;                 
    dest_addr.sin_addr.s_addr = inet_addr("224.0.0.88"); // 目的地址第队,為多播地址  
    dest_addr.sin_port = htons(8000);   // 多播服務(wù)器的端口也是 8000  
  
    // 向多播地址發(fā)送數(shù)據(jù)  
    while(1){  
        int n = sendto(sockfd, buf, strlen(buf), 0,(struct sockaddr*)&dest_addr, sizeof(dest_addr));  
        if( n < 0)  
        {  
            perror("sendto()");  
            return -2;  
        }        
  
        sleep(1);  
    }  
  
    return 0;  
}  
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末刨秆,一起剝皮案震驚了整個(gè)濱河市凳谦,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌衡未,老刑警劉巖尸执,帶你破解...
    沈念sama閱讀 207,113評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異缓醋,居然都是意外死亡如失,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評(píng)論 2 381
  • 文/潘曉璐 我一進(jìn)店門送粱,熙熙樓的掌柜王于貴愁眉苦臉地迎上來褪贵,“玉大人,你說我怎么就攤上這事抗俄〈喽。” “怎么了?”我有些...
    開封第一講書人閱讀 153,340評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵橄镜,是天一觀的道長偎快。 經(jīng)常有香客問我,道長洽胶,這世上最難降的妖魔是什么晒夹? 我笑而不...
    開封第一講書人閱讀 55,449評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮姊氓,結(jié)果婚禮上丐怯,老公的妹妹穿的比我還像新娘。我一直安慰自己翔横,他們只是感情好读跷,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,445評(píng)論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著禾唁,像睡著了一般效览。 火紅的嫁衣襯著肌膚如雪无切。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,166評(píng)論 1 284
  • 那天丐枉,我揣著相機(jī)與錄音哆键,去河邊找鬼。 笑死瘦锹,一個(gè)胖子當(dāng)著我的面吹牛籍嘹,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播弯院,決...
    沈念sama閱讀 38,442評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼辱士,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼!你這毒婦竟也來了听绳?” 一聲冷哼從身側(cè)響起颂碘,我...
    開封第一講書人閱讀 37,105評(píng)論 0 261
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎椅挣,沒想到半個(gè)月后凭涂,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,601評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡贴妻,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,066評(píng)論 2 325
  • 正文 我和宋清朗相戀三年切油,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片名惩。...
    茶點(diǎn)故事閱讀 38,161評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡澎胡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出娩鹉,到底是詐尸還是另有隱情攻谁,我是刑警寧澤,帶...
    沈念sama閱讀 33,792評(píng)論 4 323
  • 正文 年R本政府宣布弯予,位于F島的核電站戚宦,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏锈嫩。R本人自食惡果不足惜受楼,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,351評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望呼寸。 院中可真熱鬧艳汽,春花似錦、人聲如沸对雪。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至馋艺,卻和暖如春栅干,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背捐祠。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評(píng)論 1 261
  • 我被黑心中介騙來泰國打工非驮, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人雏赦。 一個(gè)月前我還...
    沈念sama閱讀 45,618評(píng)論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像芙扎,于是被迫代替她去往敵國和親星岗。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,916評(píng)論 2 344

推薦閱讀更多精彩內(nèi)容

  • 12.1 引言 在第1章中我們提到有三種IP地址:單播地址戒洼、廣播地址和多播地址俏橘。本章將更詳細(xì)地介紹廣播和多播。 廣...
    張芳濤閱讀 781評(píng)論 0 4
  • 1.這篇文章不是本人原創(chuàng)的圈浇,只是個(gè)人為了對(duì)這部分知識(shí)做一個(gè)整理和系統(tǒng)的輸出而編輯成的寥掐,在此鄭重地向本文所引用文章的...
    SOMCENT閱讀 13,037評(píng)論 6 174
  • 個(gè)人認(rèn)為,Goodboy1881先生的TCP /IP 協(xié)議詳解學(xué)習(xí)博客系列博客是一部非常精彩的學(xué)習(xí)筆記磷蜀,這雖然只是...
    貳零壹柒_fc10閱讀 5,051評(píng)論 0 8
  • 名詞延伸 通俗的說,域名就相當(dāng)于一個(gè)家庭的門牌號(hào)碼庶弃,別人通過這個(gè)號(hào)碼可以很容易的找到你衫贬。如果把IP地址比作一間房子...
    楊大蝦閱讀 20,590評(píng)論 2 57
  • 許多年之后,我走了 或許歇攻,我的詩會(huì)化作一個(gè)又一個(gè)蝴蝶 從我泛黃的詩卷里固惯,飛出 飛滿世界 或許,人們還會(huì)欣賞 或許缴守,...
    吳生善閱讀 147評(píng)論 0 0