网络编程学习——多播

1 概述

  单播地址标识单个IP接口,广播地址标识某个子网单所有IP接口,多播地址标识一组IP接口。单播和广播是寻址方案的两个极端(要么单个要么全部),多播则意在两者之间提供一种折中方案。多播数据报只应该由对它感兴趣的接口接收。另外,广播一般局域网中使用,而多播则既可用于局域网,也可跨广域网使用。事实上,基于MBone单应用系统每天都在跨整个因特网多播。

  套接字API为支持多播而增添的内容比较简单:9个套接字选项,其中3个影响目的地址为多播地址的UDP数据报的发送,另外6个影响主机对于多播数据的接收。

 

2 多播地址

  IPv4的D类地址(从224.0.0.0到239.255.255.255)是IPv4多播地址。D类地址的低序28位构成多播组ID(group ID),整个32位地址则称为组地址(group address)。

  图1-1展示了从IPv4多播地址到以太网地址的映射方法。图中还展示了IPv6多播地址到以太网地址的映射,以便比较二者映射成的结果以太网地址。

150857_0jqV_2537915.jpg

图1-1 IPv4和IPv6多播地址到以太网地址的映射

 

3 局域网上多播和广播的比较

  图1-2展示了IPv4情形作为例子。

152934_X8nv_2537915.jpg

图1-2 UDP数据报多播示例

  让一个进程接收某个多播数据报的先决条件是该进程加入相应多播组并绑定相应端口。

 

4 广域网上的多播

  单个局域网上的多播是简单的。一个主机发送一个多播分组,对它感兴趣的主机增加额外负担。

  广域网也可以从多播中受益。考虑如图1-3所示的广域网,其中5个局域网通过5个多播路由器互联。

155335_wFcO_2537915.jpg

图1-3 用5个多播路由器互连的5个局域网

  假设在其中的5个主机上启动了某个程序(比如说监听某个多播音频会话的一个程序),而且这5个程序(实为进程)加入了一个给定多播组(我们也说这5个主机加入了那个多播组)。另外假设每个多播路由器与其邻居多播路由器的通信使用某个多播路由协议(multicast routing protocol),我们就用MRP指称。图1-4展示了整个情形。

155918_bUxW_2537915.jpg

图1-4 广域网上5个主机加入一个多播组

  当某个主机上的一个进程加入一个多播组时,该主机向所有直接连接的多播路由器发送一个IGMP消息,告诉它们本主机已加入那个多播组。多播路由器随后使用MRP交换这些消息,这样每隔多播路由器就知道收到目的地为所加入多播地址的分组时该如何处理。

  接着假设左上方主机上的一个进程开始发送目的地为那个给定多播地址的分组。比如说这个进程发送的是那些多播接收进程正等着接收的音频分组。图1-5给出了这些分组。

160634_5se6_2537915.jpg

图1-5 广域网上发送多播分组

 

5 源特定多播

  广域网上的多播因为多个原因而难以部署。最大的问题是运行MRP要求每隔多播路由器接收来自所有本地接收主机的多播组加入以及其他请求,并在所有多播路由器之间交换这些信息;多播路由器的转发功能要求把来自网络中任何发送主机的数据复制并发送到网络中任何接收主机。另一个大问题是多播地址的分配:IPv4没有足够数量的多播地址可以静态地分配给想用的任何多播应用系统使用。

  源特定多播(source-specific multicast,SSM)给出了这些问题的一个务实的解决办法。SSM把应用系统单源地址结合到组地址上,从而在有限程度上解决了问题:

  • 接收进程向多播路由器提供发送进程的源地址作为多播组加入操作的一部分。

  • 把多播组的标识从单纯多播组地址细化为单播源地址和多播目的地址之间(SSM称之为通道)。

 

6 多播套接字选项

  图1-6给出了与组成员无关的3个套接字选项的IPv4和IPv6版本以及它们在getsocketopt或setsockopt调用中期望第四个参数指向的数据类型。

162511_ZCeX_2537915.jpg

图1-6 组成员无关多播套接字选项

  图1-7给出了与组成员相关的6个套接字选项的IPv4、IPv6和与IP版本无关的API。

162835_m55e_2537915.jpg

图1-7 组成员相关多播套接字选项

  下面详细讲解这9个套接字选项。

6.1 IP_ADD_MEMBERSHIP、IPV6_JOIN_GROUP和MCAST_JOIN_GROUP

  在一个指定的本地接口上加入一个不限源的多播组。对于IPv4版本,本地接口使用某个单播地址指定;对于IPv6和与协议无关的API。

 

164850_48FQ_2537915.jpg

6.2 IP_DROP_MEMBERSHIP、IPV6_LEAVE_GROUP和MCAST_LEAVE_GROUP

  离开指定的本地接口上不限源的多播组。

 

6.3 IP_BLCOK_SOURCE和MCAST_BLOCK_SOURCE

  对于一个所指定本地接口上已存在的一个不限源的多播组,在本地套接字上阻塞接收到来自某个源的多播分组。

 

6.4 IP_UNBLOCK_SOURCE和MCAST_UNBLOCK_SOURCE

  开通一个先前阻塞的源。

 

6.5 IP_ADD_SOURCE_MEMBERSHIP和MCAST_JOIN_SOURCE_GROUP

  在一个指定的本地接口上加入一个特定于源的多播组。

 

6.6 IP_DROP_SOURCE_MEMBERSHIP和MCAST_LEAVE_SOURCE_GROUP

  在一个指定的本地接口上离开一个特定于源的多播组。

 

6.7 IP_MULTICAST_IF和IPV6_MULTICAST_IF

  指定通过本套接字发送的多播数据报的外出接口。

 

6.8 IP_MULTICAST_TTL和IPV6_MULTICAST_HOPS

  给出外出的多播数据报设置IPv4的TTL或IPv6的跳限。如果不指定,这两个版本就都默认为1,从而把多播数据报限制在本地子网。

 

6.9 IP_MULTICAST_LOOP和IPV6_MUTICAST_LOOP

  开启或禁止某个多播数据报的本地自环(即回馈)。默认情况下回馈开启:如果一个主机在某个外出接口上属于某个多播组,那么该主机上由某个进度发送的目的地为该多播组的每个数据报都有一个副本回馈,被该主机作为一个收取的数据报处理。

 

7 mcast_join和相关函数

int mcast_join( int sockfd, const struct sockaddr *grp, socklen_t grplen, const char *ifname,
 u_int ifindex ); // 加入一个不限源的多播组
 
int mcast_leave(int sockfd, const struct sockaddr * sa, socklen_t salen); // 离开一个不限源的多播组

int mcast_block_source(int sockfd, const struct sockaddr * src, socklen_t srclen, 
                       const struct sockaddr * src, socklen_t srclen ); // 阻塞接收从定单播源到
                                                                           给定多播组的数据报
                                                                            
int mcast_unblock_source(int sockfd, const struct sockaddr * src, socklen_t srclen, 
                       const struct sockaddr * src, socklen_t srclen ); // 开通从给定单播源到给定
                                                                           多播组的数据接收
                                                                           
int mcast_join_source_group(int sockfd, const struct sockaddr * src, socklen_t srclen, 
                       const struct sockaddr * src, socklen_t srclen, const char *ifname,
                       u_int ifindex ); // 加入一个特定于源的多播组 
                       
int mcast_leave_source_group(int sockfd, const struct sockaddr * src, socklen_t srclen, 
                       const struct sockaddr * src, socklen_t srclen, const char *ifname,
                       u_int ifindex ); // 离开一个特定于源的多播组 
                                                                           
int mcast_set_if(int sockfd, const char * ifname, u_int ifindex); // 设置外出多播数据报的默认接口索引

int mcast_set_loop(int sockfd, int flag); // 把回馈套接字选项设置为1或0

int mcast_set_ttl(int sockfd, int ttl); // 设置IPv4或IPv6的TTL

int mcast_get_if(int sockfd); 

int mcast_get_loop(int sockfd);  

int mcast_get_ttl(int sockfd);

 

 

 

 

 

 

 

 

 

   

 

 

 

 

 

 

 

 

 

 

 

 

转载于:https://my.oschina.net/u/2537915/blog/665311

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值