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.mzph.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…

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…

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 个和它相连接的火车站。 告诉你每个火车站的利润&#…

各视频、各音频之间格式任意玩弄(图文详解)

写在前面说的话 在这里&#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…

【转】如何用Maven创建web项目(具体步骤)

使用eclipse插件创建一个web project 首先创建一个Maven的Project如下图 我们勾选上Create a simple project &#xff08;不使用骨架&#xff09; 这里的Packing 选择 war的形式 由于packing是war包&#xff0c;那么下面也就多出了webapp的目录 由于我们的项目要使用eclipse发…

可能是目前最详细的Redis内存模型及应用解读

Redis是目前最火爆的内存数据库之一&#xff0c;通过在内存中读写数据&#xff0c;大大提高了读写速度&#xff0c;可以说Redis是实现网站高并发不可或缺的一部分。 我们使用Redis时&#xff0c;会接触Redis的5种对象类型&#xff1a;字符串、哈希、列表、集合、有序集合。丰富…

POJ 1696 Space Ant 极角排序(叉积的应用)

题目大意&#xff1a;给出n个点的编号和坐标&#xff0c;按逆时针方向连接着n个点&#xff0c;按连接的先后顺序输出每个点的编号。 题目思路&#xff1a;Cross&#xff08;a,b&#xff09;表示a,b的叉积&#xff0c;若小于0&#xff1a;a在b的逆时针方向&#xff0c;若大于0a在…

SuperMap iDesktop之导入数据

SuperMap作为一个平台软件有自己的数据格式&#xff0c;现要将ESRI的SHP数据导入到SuperMap的udb数据库中&#xff0c;可以完成导入&#xff0c;但也不得不说几点问题。 下面是ArcGIS中批量导入SHP的操作界面。 比较分析 &#xff08;1&#xff09;界面简洁性 明显ArcGIS要简洁…

MyBatis 实践 -配置

MyBatis 实践标签&#xff1a; Java与存储 Configuration mybatis-configuration.xml是MyBatis的全局配置文件(文件名称随意),其配置内容和顺序例如以下: properties : 属性(文件)载入/配置settings : 全局配置參数typeAliases : 定义类型别名typeHandlers : 类型处理器objectF…

DM365视频处理流程/DM368 NAND Flash启动揭秘

DM365的视频处理涉及到三个相关处理器&#xff0c;分别是视频采集芯片、ARM处理器和视频图像协处理器&#xff08;VICP&#xff09;&#xff0c;整个处理流程由ARM核协调。视频处理主要涉及三个处理流程&#xff0c;分别是视频采集、视频编码和对编码后的视频的处理&#xff0c…

系统的Drawable(四)-LayerListDrawable

系统的Drawable(四)-LayerListDrawable 学习自 https://blog.csdn.net/u014695188/article/details/52815444 LayerListDrawable 漫谈 使用layer-list可以将多个drawable按照顺序层叠在一起显示&#xff0c;默认情况下&#xff0c;所有的item中的drawable都会自动根据它附上vie…

图像处理:镜头频率(衍射极限) 和 相机采样:显微镜的采样定理

采样定理大家都知道&#xff0c;相信不用多说。 我自己写下来给自己看。 下面&#xff0c;我总结 大家平时照相的镜头或者显微镜的物镜的情况下&#xff1a; 采样频率是指图像在数字化的时候的过程&#xff0c;实际上就是我们相机感光元件CCD或者CMOS的一个个小像元把模拟的连续…

像素越多越好?像元的面积越小越好?为何底大一级压死人?

像素越多越好&#xff1f;像素点的面积越小越好&#xff1f;为何底大一级压死人&#xff1f; 像素是&#xff1a;图像最小单元的数量&#xff0c;例如6000*4000&#xff0c;像素数量就是24*10^6。 像素太少当然图像就看不见了&#xff0c;看不清晰了。 但是现在几乎所有手机和相…

DM6446开发攻略:V4L2视频驱动和应用分析

针对DAVINCI DM6446平台&#xff0c;网络上也有很多网友写了V4L2的驱动&#xff0c;但只是解析Montavistalinux-2.6.10 V4L2的原理、结构和函数&#xff0c;深度不够。本文决定把Montavista 的Linux-2.6.18 V4L2好好分析一下&#xff0c;顺便讲解在产品中的应用&#xff0c;满足…

相机像素尺寸(像元大小)和成像系统分辨率之间的关系

相机像素尺寸&#xff08;像元大小&#xff09;和成像系统分辨率之间的关系 在显微成像系统中&#xff0c;常常会用分辨率来评价其成像能力的好坏。这里的分辨率通常是指光学系统的极限分辨率以及成像探测器的图像分辨率。最终图像所呈现出的实际分辨率&#xff0c;取决于二者的…

工业相机之全局曝光与卷帘曝光

曝光方式包括两种&#xff1a; 全局曝光&#xff08;global shutter&#xff09;卷帘曝光&#xff08;rolling shutter&#xff09; CCD相机都是全局曝光&#xff0c;CMOS相机既有全局曝光也有卷帘曝光 全局曝光 全局曝光的方式比较简单。也就是说光圈打开后&#xff0c;整个图…