zoukankan      html  css  js  c++  java
  • 多播

    广播和多播(组播)仅用于UDP

    多播,也称为“组播”,将局域网中同一业务类型主机进行了逻辑上的分组,进行数据收发的时候其数据仅仅在同一分组中进行,其他的主机没有加入此分组不能收发对应的数据。

    多播IP地址

    多播的地址是特定的,D类地址用于多播。D类IP地址就是多播IP地址,即224.0.0.0至239.255.255.255之间的IP地址,并被划分为局部连接多播地址、预留多播地址和管理权限多播地址3类:

    • 局部多播地址:在224.0.0.0~224.0.0.255之间,这是为路由协议和其他用途保留的地址,路由器并不转发属于此范围的IP包
    • 预留多播地址:在224.0.1.0~238.255.255.255之间,可用于全球范围(如Internet)或网络协议
    • 管理权限多播地址:在239.0.0.0~239.255.255.255之间,可供组织内部使用,类似于私有IP地址,不能用于Internet,可限制多播范围

    其他特殊地址

    224.0.0.1 所有组播主机
    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网络时间协议

    多播地址到以太网地址的转换

    以太网多播地址范围地址:01:00:5e:00:00:00 -- 01:00:5e:7f:ff:ff

    地址都以01:00:5e开头。第25位为0,低23位为IPv4组播地址的低23位。IPv4组播地址与MAC地址的映射关系如图所示:

    由于多播组号中的最高5bit在映射过程中被忽略,因此每个以太网多播地址对应的多播组是不唯一的。32个不同的多播组号被映射为一个以太网地址。例如,多播地址224.128.64.32(十六进制e0.80.40.20)和224.0.64.32(十六进制e0.00.40.20)都映射为同一以太网地址01:00:5e:00:40:20。

    多播编程步骤

    1>建立一个socket;
    2>设置多播的参数,例如超时时间TTL,本地回环许可LOOP等
    3>加入多播组
    4>发送和接收数据
    5>从多播组离开

    多播程序设计使用setsockopt()函数和getsockopt()函数来实现,组播的选项是IP层的。

    1 int setsockopt(
    2 SOCKET s,
    3 int level,
    4 int optname,
    5 const char* optval,
    6 int optlen
    7 );

    s(套接字): 指向一个打开的套接口描述字
    level:(级别): 指定选项代码的类型。
    SOL_SOCKET: 基本套接口
      IPPROTO_IP: IPv4套接口
      IPPROTO_IPV6: IPv6套接口
      IPPROTO_TCP: TCP套接口
    optname(选项名): 选项名称

    getsockopt()/setsockopt()的选项

        义

    IP_MULTICAST_TTL

    设置多播组数据的TTL值

    IP_ADD_MEMBERSHIP

    在指定接口上加入组播组

    IP_DROP_MEMBERSHIP

    退出组播组

    IP_MULTICAST_IF

    获取默认接口或设置接口

    IP_MULTICAST_LOOP

    禁止组播数据回送


    optval(选项值): 是一个指向变量的指针 类型:整形,套接口结构, 其他结构类型:linger{}, timeval{ }
    optlen(选项长度) :optval 的大小

    广播组结构体:

    1 struct ip_mreq          
    2 { 
    3     struct in_addr imn_multiaddr;      /*加入或者退出的广播组IP地址*/ 
    4    struct in_addr imr_interface;      /*加入或者退出的网络接口IP地址*/
    5 };

    加入或者退出一个多播组,通过选项IP_ADD_MEMBERSHIP和IP_DROP_MEMBERSHIP,对一个结构struct ip_mreq类型的变量进行控制

    选项IP_ADD_MEMBERSHIP用于加入某个多播组,之后就可以向这个多播组发送数据或者从多播组接收数据。此选项的值为mreq结构,成员imn_multiaddr是需要加入的多播组IP地址,成员imr_interface是本机需要加入广播组的网络接口IP地址。例如:

    1 struct ip_mreq mreq;
    2 setsockopt(s,IPPROTO_IP,IP_ADD_MEMBERSHIP,&mreq,sizeof(mreq));

    实例

    服务端:

     1 #include<iostream>
     2 #include<stdio.h>
     3 #include<sys/socket.h>
     4 #include<netdb.h>
     5 #include<sys/types.h>
     6 #include<arpa/inet.h>
     7 #include<netinet/in.h>
     8 #include<unistd.h>
     9 #include<stdlib.h>
    10 #include<string.h>
    11 #define MCAST_PORT 8888
    12 #define MCAST_ADDR "224.0.0.88"  // 多播地址
    13 #define MCAST_DATA "BROADCAST TEST DATA"  // 多播内容
    14 #define MCAST_INTERVAL 5  //多播时间间隔
    15 using namespace std;
    16 
    17 int main()
    18 {
    19     int sock;
    20     struct sockaddr_in mcast_addr;
    21     sock=socket(AF_INET,SOCK_DGRAM,0);
    22     if(sock==-1)
    23     {
    24         cout<<"socket error"<<endl;
    25         return -1;
    26     }
    27     memset(&mcast_addr,0,sizeof(mcast_addr));
    28     mcast_addr.sin_family=AF_INET;
    29     mcast_addr.sin_addr.s_addr=inet_addr(MCAST_ADDR);
    30     mcast_addr.sin_port=htons(MCAST_PORT);
    31     while(1)
    32     {       //向局部多播地址发送多播内容
    33         int n=sendto(sock,MCAST_DATA,sizeof(MCAST_DATA),0,(struct sockaddr*)&mcast_addr,sizeof(mcast_addr));
    34         if(n<0)
    35         {
    36             cout<<"send error"<<endl;
    37             return -2;
    38         }
    39         else
    40         {
    41             cout<<"send message is going ...."<<endl;
    42         }
    43         sleep(MCAST_INTERVAL);
    44 
    45     }
    46     return 0;
    47 }

    客户端:

     1 #include<iostream>
     2 #include<stdio.h>
     3 #include<stdlib.h>
     4 #include<string.h>
     5 #include<sys/types.h>
     6 #include<unistd.h>
     7 #include<sys/socket.h>
     8 #include<netdb.h>
     9 #include<arpa/inet.h>
    10 #include<netinet/in.h>
    11 #define MCAST_PORT 8888
    12 #define MCAST_ADDR "224.0.0.88" /*一个局部连接多播地址,路由器不进行转发*/
    13 #define MCAST_INTERVAL 5  //发送时间间隔
    14 #define BUFF_SIZE 256   //接收缓冲区大小
    15 using namespace std;
    16 int main()
    17 {
    18     int sock;
    19     struct sockaddr_in local_addr;
    20     int err=-1;
    21     sock=socket(AF_INET,SOCK_DGRAM,0);
    22     if(sock==-1)
    23     {
    24         cout<<"sock error"<<endl;
    25         return -1;
    26     }
    27     /*初始化地址*/
    28     local_addr.sin_family=AF_INET;
    29     local_addr.sin_addr.s_addr=htonl(INADDR_ANY);
    30     local_addr.sin_port=htons(MCAST_PORT);
    31     /*绑定socket*/
    32     err=bind(sock,(struct sockaddr*)&local_addr,sizeof(local_addr));
    33     if(err<0)
    34     {
    35         cout<<"bind error"<<endl;
    36         return -2;
    37     }
    38     /*设置回环许可*/
    39     int loop=1;
    40     err=setsockopt(sock,IPPROTO_IP,IP_MULTICAST_LOOP,&loop,sizeof(loop));
    41     if(err<0)
    42     {
    43         cout<<"set sock error"<<endl;
    44         return -3;
    45     }
    46     struct ip_mreq mreq;/*加入广播组*/
    47     mreq.imr_multiaddr.s_addr=inet_addr(MCAST_ADDR);//广播地址
    48     mreq.imr_interface.s_addr=htonl(INADDR_ANY); //网络接口为默认
    49     /*将本机加入广播组*/
    50     err=setsockopt(sock,IPPROTO_IP,IP_ADD_MEMBERSHIP,&mreq,sizeof(mreq));
    51     if(err<0)
    52     {
    53         cout<<"set sock error"<<endl;
    54         return -4;
    55     }
    56     int times=0;
    57     socklen_t addr_len=0;
    58     char buff[BUFF_SIZE];
    59     int n=0;
    60     /*循环接受广播组的消息,5次后退出*/
    61     for(times=0;;times++)
    62     {
    63         addr_len=sizeof(local_addr);
    64         memset(buff,0,BUFF_SIZE);
    65         n=recvfrom(sock,buff,BUFF_SIZE,0,(struct sockaddr*)&local_addr,&addr_len);
    66         if(n==-1)
    67         {
    68             cout<<"recv error"<<endl;
    69             return -5;
    70         }
    71         /*打印信息*/
    72         printf("RECV %dst message from server : %s
    ",times,buff);
    73         sleep(MCAST_INTERVAL);
    74     }
    75     /*退出广播组*/
    76     err=setsockopt(sock,IPPROTO_IP,IP_DROP_MEMBERSHIP,&mreq,sizeof(mreq));
    77     close(sock);
    78     return 0;
    79 }
  • 相关阅读:
    angular 输入属性
    angular 管道
    angular 双向绑定
    Python3与OpenCV3.3 图像处理(补)--第三节补充
    Python3与OpenCV3.3 图像处理(三)--Numpy数组操作
    Python3与OpenCV3.3 图像处理(二)--图像基本操作
    Python3与OpenCV3.3 图像处理(一)--环境搭建与简单DEMO
    安阳三篇之猝死的城
    安阳三篇之小城青年
    安阳三篇之全民赌局
  • 原文地址:https://www.cnblogs.com/raichen/p/5026578.html
Copyright © 2011-2022 走看看