LINUX多播編程

一.單播,廣播和多播

1.單播用于兩個主機之間的端對端通信,廣播用于一個主機對整個局域網上所有主機上的數據通信。單播和廣播是兩個極端,要么對一個主機進行通信,要么對整個局域網上的主機進行通信。實際情況下,經常需要對一組特定的主機進行通信,而不是整個局域網上的所有主機,這就是多播的用途。

2.多播的概念:

?
1>多播,也稱為“組播”,將局域網中同一業務類型主機進行了邏輯上的分組,進行數據收發的時候其數據僅僅在同一分組中進行,其他的主機沒有加入此分組不能收發對應的數據。

2>在廣域網上廣播的時候,其中的交換機和路由器指向需要獲取數據的主機復制并轉發數據。主機可以向路由器請求加入或退出某個組,網絡中的路由器和交換機有選擇地復制并傳輸數據,將數據僅僅傳輸給組內的主機。

3.多播的優點和缺點

1>優點:

?? 具有同種業務的主機加入同一數據流,共享同一通道,節省了帶寬和服務器的優點,具有廣播的優點而又沒有廣播所需要的帶寬。

?? 服務器的總帶寬不受客戶端帶寬的限制。由于組播協議由接收者的需求來確定是否進行數據流的轉發,所以服務器端的帶寬是常量,與客戶端的數量無關。

?? 與單播一樣,多播是允許在廣域網即Internet上進行傳輸的,而廣播僅僅在同一局域網上才能進行。

2>組播的缺點:

?? 多播與單播相比沒有糾錯機制,當發生錯誤的時候難以彌補,但是可以在應用層來實現此種功能

?? 多播的網絡支持存在缺陷,需要路由器及網絡協議棧的支持。

4.目前多播的應用主要有網上視頻,網上會議等

5.多播地址:

1>多播的地址是特定的,D類地址用于多播。D類IP地址就是多播IP地址,即224.0.0.0到239.255.255.255之間的IP地址,并被劃分為局部連續多播地址,預留多播地址和管理權限多播地址3類:

?? 局部多播地址:在224.0.0.0~224.0.0.251之間,這是路由協議和其他用途保留的地址,路由器并不轉發屬于此范圍的IP包。(即此類范圍的多播IP地址只能在局域網內使用)

?? 預留多播地址:在224.0.1.0~238.255.255.255之間,可用于全球范圍或網絡協議

?? 管理權限多播地址:在239.0.0.0~239.255.255.255之間,可供組織內部使用,類似于私有IP地址,不能用于Internet,可限制多播范圍。

6.IPv4多播地址到以太網地址的映射方法:

1>IPv4的D類地址(從224.0.0.0到239.255.255.255)是IPv4多播地址;D類地址的低序28位構成多播組ID(group? ID),整個32位地址則稱為組地址(group address)。

2>IPv4地址的映射,以太網地址的高24位總是01:00:5e下一位總是0,底序23位拷貝自多播組ID的底序23位。這樣就組成了多播地址的以太網地址。


本篇文章來源于 Linux公社網站(www.linuxidc.com)? 原文鏈接:http://www.linuxidc.com/Linux/2011-09/43602.htm

1>建立一個socket;

2>設置多播的參數,例如超時時間TTL,本地回環許可LOOP等

3>加入多播組

4>發送和接收數據
?

5>從多播組離開

2.多播程序設計使用setsockopt()函數和getsockopt()函數來實現,組播的選項是IP層的。

3.setsockopt()的選項

1>IP_MULTICAST_TTL:設置多播組數據的TTL值(路由跳數),每跨過一個路由器,TTL值減一.范圍為0~255之間的任何值。


int? ttl;

setsockopt(sock_fd,IPPROTO_IP,IP_MULTICAST_TTL,&ttl,sizeof(ttl));

2>IP_MULTICAST_LOOP:默認情況下,當本機發送組播數據到某個網絡接口時,在IP層,數據會回送公道本地的回環接口,選項IP_MULTICAST_LOOP用于控制數據是否回送到本地的回環接口。


int? loop;

setsockopt(sock_fd,IPPROTO_IP,IP_MULTICAST_LOOP,&loop,sizeof(loop));

參數loop設置為0表示禁止回送,設置為1允許回送。

3>IP_ADD_MEMBERSHIP: 該選項通過對一個結構struct ip_mreq類型的變量進行控制而加入一個多播組。

?? struct ip_mreq

struct ip_mreq

{

?????? struct in_addr imr_multiaddr;/*加入的多播組IP地址*/

?????? struct? in_addr imr_interface;/*加入的網絡接口IP地址*/

};

?? 選項IP_ADD_MEMBESHIP選項用于加入某個多播組,之后就可以向這個多播組發送數據或者從多播組接收數據。此選項的值為mreq結構,成員imr_multiaddr是需要加入的多播組IP地址,成員imr_interface是本機需要加入多播組的網絡接口IP地址。

struct ip_mreq? mreq;

setsockopt(sock_fd,IPPROTO_IP,IP_ADD,MEMBERSHIP,&mreq,sizeof(mreq));

?? 使用IP_ADD_MEMBERSHIP選項每次只能加入一個網絡接口的IP地址到多播組,但并不是一個多播組僅允許一個主機IP地址加入,可以多次調用IP_ADD_MEMBERSHIP選項來實現多個IP地址加入同一個多播組,或者同一個IP地址加入多個多播組。當imr_interface為INADDR_ANY時,選擇的本地默認網口。

4>IP_DROP_MEMBERSHIP:該選項用于從一個多播組中退出。

struct ip_mreq? mreq;

setsockopt(sock_fd,IPPROTP_IP,IP_DROP_MEMBERSHIP,&merq,sizeof(sreq));

三實例:

情景:

?? 服務器端每隔2秒向目的端口號為5000和目的多播地址為224.0.0.255發送數據welcome you to multicast socket programme。

?? 客戶端從多播地址為224.0.0.255和端口號5000處接收5次多播數據。

?


LINUX
?1.服務器端程序

?1? #include<stdio.h>
? 2 #include<string.h>
? 3 #include<stdlib.h>
? 4 #include<unistd.h>
? 5 #include<sys/socket.h>
? 6 #include<sys/types.h>
? 7 #include<arpa/inet.h>
? 8 #include<netinet/in.h>
? 9
?10 #define? SERV_PORT 5350
?11 #define? MCAST_PORT 5350
?12 #define? MCAST_ADDR "224.0.0.251"
?13 #define? MCAST_INTERVAL?? 2
?14
?15 int main(int argc,char **argv)
?16 {
?17???????? int sock_fd;
?18???????? struct sockaddr_in mcast_addr,addr_serv,addr_client;
?19???????? char send_buf[]="tigerjibo";
?20???????? char recv_buf[1024];
?21???????? int serv_len,mcast_len;
?22???????? int send_num;
?23???????? int recv_num;
?24???????? int err;
?25???????? struct ip_mreq mreq;
?26???????? sock_fd = socket(AF_INET,SOCK_DGRAM,0);/*建立套接子*/
?27???????? if(sock_fd < 0){
?28???????????????? perror("socket()");
?29???????????????? exit(1);
?30???????? } else {
?31???????????????? printf("socket sucefull!\n");
?32???????? }
?33???????? /*服務器端地址*/
?34???????? memset(&addr_serv,0,sizeof(struct sockaddr_in));
?35???????? addr_serv.sin_family = AF_INET;
?36???????? addr_serv.sin_addr.s_addr = inet_addr("192.168.1.11");
?37???????? addr_serv.sin_port = htons(SERV_PORT);
?38???????? serv_len = sizeof(struct sockaddr_in);
?39??????? //初始化多播地址
?40???????? memset(&mcast_addr,0,sizeof(mcast_addr));
?41???????? mcast_addr.sin_family = AF_INET;
?42???????? mcast_addr.sin_addr.s_addr = inet_addr(MCAST_ADDR);
?43???????? mcast_addr.sin_port = htons(MCAST_PORT);
?44
?45???????? if(bind(sock_fd,(struct sockaddr*)&addr_serv,serv_len)<0){

?46???????????????? perror("bind");
?47???????????????? exit(1);
?48???????? } else {
?49???????????????? printf("bind sucess\n");
?50???????? }
?51???????? while(1){
?52???????????????? printf("begin send:\n");
?53???????????????? send_num = sendto(sock_fd,send_buf,sizeof(send_buf),0,(struct sockaddr *)&mcast_addr,sizeof(mcast_addr));
?54???????????????? if( send_num? < 0){
?55???????????????????????? perror("sendto()");
?56???????????????????????? exit(1);
?57???????????????? } else{
?58???????????????????????? printf("send sucessful\n");
?59???????????????? }
?60???????????????? sleep(MCAST_INTERVAL);
?61???????? }
?62???????? close(sock_fd);
?63???????? return 0;
?64 }
?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? 64,1???????? 底端

?1.客戶端程序??????????????????????????????????????????????

?1 #include<stdio.h>
? 2 #include<string.h>
? 3 #include<stdlib.h>
? 4 #include<errno.h>
? 5
? 6 #include<sys/socket.h>
? 7 #include<sys/types.h>
? 8 #include<arpa/inet.h>
? 9 #include<netinet/in.h>
?10 #include<unistd.h>
?11 #define? LOCAL_PORT????? 5350
?12 #define? MCAST_ADDR????? "224.0.0.251"
?13 #define? MCAST_INTERVAL??? 5
?14 #define? LOCAL_ADDR?? "192.168.1.11"
?15 /*
?16 static void mdns_mcast_group(struct sockaddr_in *mcast_addr){
?17???????? mcast_addr->sin_family = AF_INET;
?18???????? mcast_addr->sin_port = htons(MCAST_PORT);
?19???????? mcast_addr->sin_addr.s_addr = inet_addr(MCAST_ADDR);
?20
?21 }
?22 int mdns_open_socket(void){
?23???????? struct ip_mreq mreq;
?24???????? struct sockaddr_in sa;
?25???????? int fd =-1,ttl,yes;//yes地址重用
?26????????
?27???????? mdns_mcast_group(&sa);
?28
?29???????? if((fd = socket(AF_INET,SOCK_DGRAG,0)) < 0){
?30???????????????? printf("socket() failed: %s\n",strerror(errno));
?31???????? }
?32 }*/
?33 int main()
?34 {
?35???????? int sock_fd;
?36???????? struct sockaddr_in local_addr;
?37???????? int err = -1;
?38???????? int loop = 1;
?39???????? sock_fd = socket(AF_INET,SOCK_DGRAM,0);/*建立套接字*/
?40???????? if(sock_fd < 0){
?41???????????????? perror("socket()");
?42???????????????? exit(1);
?43???????? } else {
?44???????????????? printf("socket() sucessful\n");

?45???????? }

?46???????? memset(&local_addr,0,sizeof(local_addr));
?47???????? local_addr.sin_family = AF_INET;
?48???????? local_addr.sin_addr.s_addr = htonl(INADDR_ANY);//inet_addr(LOCAL_ADDR);htonl(INADDR_ANY);固定為local_addr則接受不到
?49???????? local_addr.sin_port = htons(LOCAL_PORT);
?50???????? err = bind(sock_fd,(struct sockaddr *)&local_addr,sizeof(local_addr));
?51???????? if(err < 0){
?52???????????????? perror("bind");
?53???????????????? exit(1);
?54???????? } else {
?55???????????????? printf("bind sucessful\n");
?56???????? }
?57???????? loop = 1;
?58???????? err = setsockopt(sock_fd,IPPROTO_IP,IP_MULTICAST_LOOP,&loop,sizeof(loop));
?59???????? if(err < 0){
?60???????????????? perror("setsocket():IP MULTICAST_LOOP");
?61???????????????? exit(1);
?62???????? } else {
?63???????????????? printf("IP_MULTICAST_LOOP SUCESSFUL\n");
?64???????? }
?65
?66???????? struct ip_mreq mreq;
?67???????? mreq.imr_multiaddr.s_addr = inet_addr(MCAST_ADDR);
?68???????? mreq.imr_interface.s_addr = inet_addr(LOCAL_ADDR);
?69???????? err = setsockopt(sock_fd,IPPROTO_IP,IP_ADD_MEMBERSHIP,&mreq,sizeof(mreq));//
?70???????? if(err < 0){
?71???????????????? printf("%s setsockopt():IP ADD MEMBURSHIP\n",strerror(errno));
?72???????????????? exit(1);
?73???????? } else {
?74???????????????? printf("setsockopt() IP ADD MEMBURSHIP sucessful\n");
?75???????? }
?76???????? int? times = 0;
?77???????? int? addr_len = 0;
?78???????? char buff[1000];
?79???????? int? recv_num? =0;
?80???????? for(times = 0;times < 5;times++){
?81???????????????? addr_len = sizeof(local_addr);
?82???????????????? memset(buff,0,sizeof(buff));
?83???????????????? recv_num = recvfrom(sock_fd,buff,sizeof(buff),0,(struct sockaddr*)&local_addr,&addr_len);
?84???????????????? if(recv_num < 0){

?85???????????????????????? perror("recvfrom()");
?86???????????????????????? exit(1);
?87???????????????? } else {
?88???????????????????????? printf("Recv %dst message from server :%s\n",times,buff);
?89???????????????????????? sleep(MCAST_INTERVAL);
?90???????????????? }
?91???????? }
?92???????? err = setsockopt(sock_fd,IPPROTO_IP,IP_DROP_MEMBERSHIP,&mreq,sizeof(mreq));
?93???????? close(sock_fd);
?94???????? return 0;
?95 }

?


?

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/254099.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/254099.shtml
英文地址,請注明出處:http://en.pswp.cn/news/254099.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

cas單點登錄搭建

Cas Server下載&#xff1a;http://developer.jasig.org/cas/ Cas Client下載&#xff1a;http://developer.jasig.org/cas-clients/ 測試環境&#xff1a; jdk&#xff1a;java version "1.8.0_60" tomcat&#xff1a;apache-tomcat-7.0.65 mysql&#xff1a;mysql5…

新CIO:Mark Schwartz認為的領先IT

美國公民及移民服務局前任CIO&#xff0c;現任AWS企業戰略師Mark Schwartz在倫敦舉行的DevOps企業峰會上介紹了什么是領先的IT。\\Schwartz介紹說&#xff0c;老舊、傳統的模型將業務和IT完全分開&#xff0c;他又提出了一種新的模型&#xff0c;在這種模型中&#xff0c;CIO擔…

689D Magic Odd Square 奇數幻方

1 奇數階幻方構造法 (1) 將1放在第一行中間一列; (2) 從2開始直到nn止各數依次按下列規則存放&#xff1a;按 45方向行走&#xff0c;向右上&#xff0c;即每一個數存放的行比前一個數的行數減1&#xff0c;列數加1 (3) 如果行列范圍超出矩陣范圍&#xff0c;則回繞。例如1在第…

Java單例的常見形式

2019獨角獸企業重金招聘Python工程師標準>>> Java單例的常見形式 本文目的&#xff1a;總結Java中的單例模式 本文定位&#xff1a;學習筆記 學習過程記錄&#xff0c;加深理解&#xff0c;便于回顧。也希望能給學習的同學一些靈感 一、非延遲加載單例類 public cla…

運動控制卡的基類函數與實現例子

基類 namespace MotionCardDll {public abstract class IMotionCard{public Int32 m_Mode;public Int32 m_BoardId;//Card 號public Int32 m_Card_name;public Int32 m_StartAxisID

U-Boot啟動過程完全分析

1.1 U-Boot 工作過程 U-Boot啟動內核的過程可以分為兩個階段&#xff0c;兩個階段的功能如下&#xff1a; &#xff08;1&#xff09;第一階段的功能 硬件設備初始化 加載U-Boot第二階段代碼到RAM空間 設置好棧 跳轉到第二階段代碼入口 &#xff08;2&#x…

CJOJ 2171 火車站開飯店(樹型動態規劃)

CJOJ 2171 火車站開飯店&#xff08;樹型動態規劃&#xff09; Description 政府邀請了你在火車站開飯店&#xff0c;但不允許同時在兩個相連的火車站開。任意兩個火車站有且只有一條路徑&#xff0c;每個火車站最多有 50 個和它相連接的火車站。 告訴你每個火車站的利潤&#…

JavaWeb總結(十五)

AJAX&#xff08;Asynchronous JavaScript and XML&#xff08;異步的 JavaScript 和 XML&#xff09;&#xff09; AJAX的作用是什么&#xff1f; 在無需重新加載整個網頁的情況下&#xff0c;能夠更新部分網頁的技術 是一種用于創建快速動態網頁的技術 通過在后臺與服務器進行…

工業相機基類與實現

基類 namespace Cameron {//相機參數public struct CamPara{public int DeviceID; //設備描述public string Name;public int WorkMode; //工作類型,0為連續模式,1為觸發模式public float Expours

物聯網技術周報第 143 期: Unity 3D 和 Arduino 打造虛擬現實飛行器

新聞 \\\\t《西門子、阿里云簽約助力中國工業物聯網發展》德國工業集團西門子和中國阿里巴巴集團旗下的云計算公司阿里云&#xff19;日在柏林簽署備忘錄&#xff0c;共同推進中國工業物聯網發展。根據備忘錄內容&#xff0c;西門子和阿里云將發揮各自技術和行業優勢&#xff…

不同平臺下 sleep區別用法

應用程序&#xff1a; #include <syswait.h> usleep(n) //n微秒 Sleep&#xff08;n&#xff09;//n毫秒 sleep&#xff08;n&#xff09;//n秒 驅動程序&#xff1a; #include <linux/delay.h> mdelay(n) //微秒milliseconds 其實現 #ifdef notdef #define mdelay…

各視頻、各音頻之間格式任意玩弄(圖文詳解)

寫在前面說的話 在這里&#xff0c;記錄下來&#xff0c;是為了方便以后偶爾所制作所需和你們前來的瀏覽學習。 學會&#xff0c;玩弄一些視頻和音頻的軟件&#xff0c;只有好處沒有害處。同時&#xff0c;也不需很多時間&#xff0c;練練手罷了。也是方便自己所用吧&#xff0…

oracle 如何查看日志?

2019獨角獸企業重金招聘Python工程師標準>>> Oracle日志查看一&#xff0e;Oracle日志的路徑&#xff1a;登錄&#xff1a;sqlplus "/as sysdba"查看路徑&#xff1a;SQL> select * from v$logfile;SQL> select * from v$logfile;(#日志文件路徑)二…

回歸_英國酒精和香煙關系

sklearn實戰-乳腺癌細胞數據挖掘(博客主親自錄制視頻教程) https://study.163.com/course/introduction.htm?courseId1005269003&utm_campaigncommission&utm_sourcecp-400000000398149&utm_mediumshare 數據統計分析聯系:&#xff31;&#xff31;&#xff1a;&a…

C# ini文件讀寫函數

namespace Tools {class IniOperate{[DllImport("kernel32")]private static extern int GetPrivateProfileString(string section, string key,

Visual studio內存泄露檢查工具--BoundsChecker

BoundsChecker是一個Run-Time錯誤檢測工具&#xff0c;它主要定位程序在運行時期發生的各種錯誤。 BoundsChecker能檢測的錯誤包括&#xff1a; 1&#xff09;指針操作和內存、資源泄露錯誤&#xff0c;比如&#xff1a;內存泄露&#xff1b;資源泄露&#xff…

【轉】如何用Maven創建web項目(具體步驟)

使用eclipse插件創建一個web project 首先創建一個Maven的Project如下圖 我們勾選上Create a simple project &#xff08;不使用骨架&#xff09; 這里的Packing 選擇 war的形式 由于packing是war包&#xff0c;那么下面也就多出了webapp的目錄 由于我們的項目要使用eclipse發…

CST光源控制卡簡單操作C#程序

namespace Machine {class LightCST{private SerialPort serialPort ;public LightCST(){serialPort = new SerialPort();}

可能是目前最詳細的Redis內存模型及應用解讀

Redis是目前最火爆的內存數據庫之一&#xff0c;通過在內存中讀寫數據&#xff0c;大大提高了讀寫速度&#xff0c;可以說Redis是實現網站高并發不可或缺的一部分。 我們使用Redis時&#xff0c;會接觸Redis的5種對象類型&#xff1a;字符串、哈希、列表、集合、有序集合。豐富…

bootcmd 和bootargs

看到這個標題&#xff0c;可能覺得這個并沒有什么的&#xff0c;其實不然&#xff0c;編好了u-boot了&#xff0c;但是如何來使用確不是那么簡單的&#xff0c;想當初我將uboot制作出來后以為全部都搞定了&#xff0c;屁顛屁顛的燒到板子上后可系統就是起不來&#xff0c;為什么…