linux网络编程之一-----多播(组播)编程

什么是多播

        组播(Multicast)是网络一种点对多(one to many)的通信方式,通过报文复制完成网络中一台server对应多台接收者的高效数据传 送。对其形象的比喻就是类似于广播电台和电视台节目的发送。电台或电视台向特定频道发送他们的节目,而接收者可以根据自己的喜好选择频道来收听或收看节 目。

       传统网络的通信方式单 播(Unicast) 在许多场合下并不合适,如果强行采于单播方式只是会增加网络上传送的报文,还会影响server端的运行效率,如网络游戏,网络视频会议等。这些场合下由于接收者需要的是同样的数据,如果有N个 接收者,那么server就需要把这份数据做成N个报文分别发送给接收者,这样当接收者增多的情况下,server端发送的报文也同样需要增多,server端承受这样的通信量肯定有一个 极值,当接收者到一定程度的时候,不单单是网络流量增大的问题了,server面临的只有宕机。

  组播在这种场合下就有了用武之地了。Server端需要做的就是向特写的Group发送一个报文,当网络的多个接收者对这个报文感兴趣的时候,他们可以自由复制得到这个报文。这样的 情况下,无论接收者增加多少人,Server需要做的只是发送一个报文,而网络上传送的是只是一份报文。

        单播用于两个主机之间的端对端通信,广播用于一个主机对整个局域网上所有主机上的数据通信。单播和广播是两个极端,要么对一个主机进行通信,要么对整个局域网上的主机进行通信。实际情况下,经常需要对一组特定的主机进行通信,而不是整个局域网上的所有主机,这就是多播的用途。

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


单播图例:

                                 linux网络编程之一-----多播(组播)编程_第1张图片

多播图例:

                      linux网络编程之一-----多播(组播)编程_第2张图片

组播地址

        32位的IP地址被分成了A、B、C、D、E五种类型,前三种是我们日常生活常见的,由一个权威部分统一分配。而D类地址我们需要的多播地址, 前三种地址我们可以形象的认为是一个点,而一个D类多播地址可以认为是一个频道。这样对多播的理解可以形象一点。

       D类IP地址就是多播IP地址,即

       常见多播保留地址224.0.0.0239.255.255.255之间的IP地址,并被划分为局部连接多播地址、预留多播地址和管理权限多播地址3类:

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

                    linux网络编程之一-----多播(组播)编程_第3张图片
实验:可在主机上执行ping 224.0.0.1,看看有多少主 机有回应。

IP组播地址到链路层地址的转换

         因为以太网支持多种协议,所以要采取措施分配多播地址,避免冲突。IEEE管理以太网多播地址分配。IEEE把一块以太网多播地址分给IANA以支持IP多播。块的地址都以01:00:5e开头。 第25位为0,低23位为IPv4组播地址的低23位。IPv4组播地址与MAC地址的映射关系如图所示:
                                                 linux网络编程之一-----多播(组播)编程_第4张图片
        由于多播组号中的最高5bit在映射过程中被忽略,因此每个以太网多播地址对应的多播组是不唯一的。32个不同的多播组号被映射为一个以太网地址。例如,多播地址224.128.64.32(十六进制e0.80.40.20)和224.0.64.32(十六进制e0.00.40.20)都映射为同一以太网地址01:00:5e:00:40:20。

组播需要的网络环境

        如果主机想获得多播报 文,相邻的路由器也必须支持IGMP,如果想获得Internet上的多播报文,主机到Server的这个路径中所遇到的路由器必须全部支持IGMP,路由器还必须支持源发现协议,如MSDP,PIM_DM,PIM_SM等。


组播的等级

多播主机分为三个级别:

  • 0级:主机不能发送或接收IP多播。这种主机应该自动丢弃它收到的具有D类目的地址的分组。
  • 1级:主机能发送但不能接收IP多播。在向某个IP多播组发送数据报之前,并不要求主机加入该组。多播数据报的发送方式与单播一样,除了多播数据报的目的地址是 IP多播组之外。网络驱动器必须能够识别出这个地址,把在本地网络上多播数据报。
  • 2级:主机能发送和接收IP多播。
        对这三个等级的理解应 该从socket上。 建立了一个socket以后可以对它进行设置,看它需求什么。一般现在存在的网络程序就就是0级了,因为它们不支持多播,如用于连接web服务器获取网页内容的那个socket就应该属于0级。
       一个演唱会现场网络直 播,由于采用了多播,服务器要向一个多播组发送报文,因为他不需要获取接收者的报文,所以可以建立一个socket只向特定的多播组发送数据就可以 了,这个socket应该就是1级。
       一个网络会议的例子, 由于会议是有多个人参加的,每个人都需要接收其它人的报文,所以建立了一个socket,首先把这个socket加入到一个多播组,使其能接收多播组的数据,然后它也可以用这个socket向自己加入的多播组发送自己的状 态。这个socket就应该是2级。

linux多播编程

linux多播编程步骤:

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

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

int setsockopt(SOCKET s, int level, int optname, const char FAR * optval, int optlen);
int getsockopt(SOCKET s, int level, int optname, char FAR * optval, int FAR * optlen);

level必须为IPPROTO_IP,optname就是在 组播起到最主要作用的一个字段,与组播相关的可取值:

可取值 setsockopt() getsockopt() 含    义
IP_MULTICAST_TTL 支持 支持 设置多播组数据的TTL值
IP_ADD_MEMBERSHIP 支持 不支持 在指定接口上加入组播组
IP_DROP_MEMBERSHIP 支持 不支持 退出组播组
IP_MULTICAST_IF 支持 支持 获取默认接口或设置接口
IP_MULTICAST_LOOP 支持 支持 禁止组播数据回送



1.选项IP_MULTICASE_TTL

选项IP_MULTICAST_TTL允许设置超时TTL,范围为0255之间的任何值。默认情况下,多播报文的TTL被设置成了1,也就是说到这个报文在网络传送的时候,它只能在自己所在的网络传送,当要向外发送的时候,路由器把TTL减1以后变成了0,这个报文就已经被Discard了。例如:

unsigned char ttl=255;
setsockopt(s,IPPROTO_IP,IP_MULTICAST_TTL,&ttl,sizeof(ttl));

2.选项IP_MULTICAST_IF

选项IP_MULTICAST_IF用于设置发送组播使用的本地接口,另一个网络接口会忽略此数据。默认情况下被设置成了本地接口的第一个地址。例如:

struct in_addr addr;
setsockopt(s,IPPROTO_IP,IP_MULTICAST_IF,&addr,sizeof(addr));

参数addr是希望多播输出接口的IP地址,使用INADDR_ANY地址回送到默认接口。

当接收者加入到一个多播组以后,再向这个多播组发送数据,默认情况下在IP层,数据会回送到本地的回环接口,选项IP_MULTICAST_LOOP用于控制数据是否回送到本地的回环接口。例如:

unsigned char loop;
setsockopt(s,IPPROTO_IP,IP_MULTICAST_LOOP,&loop,sizeof(loop));参数loop设置为0禁止回送,设置为1允许回送。

3.选项IP_ADD_MEMBERSHIPIP_DROP_MEMBERSHIP

加入或者退出一个多播组,通过选项IP_ADD_MEMBERSHIPIP_DROP_MEMBERSHIP,对一个结构struct ip_mreq类型的变量进行控制,struct ip_mreq原型如下:

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

struct ip_mreq ipmr;
ipmr.imr_interface.s_addr = htonl(INADDR_ANY);
ipmr.imr_multiaddr.s_addr = inet_addr("234.5.6.7");
setsockopt(s, IPPROTO_IP, IP_ADDR_MEMBERSHIP, (char*)&ipmr, sizeof(ipmr));


你可能感兴趣的:(linux网络编程之一-----多播(组播)编程)