Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1334685
  • 博文数量: 284
  • 博客积分: 3251
  • 博客等级: 中校
  • 技术积分: 3046
  • 用 户 组: 普通用户
  • 注册时间: 2012-04-26 17:23
文章分类

全部博文(284)

文章存档

2019年(2)

2018年(5)

2015年(19)

2014年(13)

2013年(10)

2012年(235)

分类: LINUX

2012-12-21 16:42:34

前面我们讲到如何加入到一个组播组中,当一个客户端完成了加入一个组播组的操作后,就可以从该组接收数据了。下面我们看看组播数据报接收的详细流程。
    通过加入组播组的操作后,网络设备接口已经知道要接收该组的数据报,所以组播数据会从网卡接收进来,一直到达myip_rcv函数,我们就从myip_rcv函数开始,跟踪整个组播数据报的接收流程。
    同样,myip_rcv还是先检查数据报的类型(是否为本机需要接收的包),ip首部是否正确,然后调用myip_rcv_finish。 myip_rcv_finish对任何数据报都要先查找输入路由,输入路由查找函数是myip_route_input,当该函数在路由缓存 myrt_hash_table中找不到相应的路由项时,判断数据报的输入地址,如果发现是组播地址,就不能简单地查找FIB,而是要作特殊处理。
    首先,调用myip_check_mc对这个组播数据报作检查,从网络设备接口的struct in_device中去匹配组播地址,如果匹配不到,表示这个不是我们希望接收的组播包,丢弃。匹配到了,则作下一步检查,如果这本身就是一个IGMP 包,则接收,否则,查看这个组播组在我们的struct in_device中设置的过滤机制,如果该数据报的源地址在我们的过滤名单中,则丢弃,否则接收。
    如果检查通过,准备接收这个组播包,则调用myip_route_input_mc查找组播输入路由,这是一个专门为组播设置的函数,它第一步要检查数据 报源地址的有效性,即源地址不能是组播地址,不能是广播地址,也不能是回环地址,同时,该数据报必须是一个因特网协议包(ETH_P_IP)。如果源地址 为0,那么只有当目的地址是224.0.0.0-224.0.0.255之间的值(只能在发送主机所在的一个子网内的传送,不会通过路由器转发。)时,系 统可以自己选定一个scope为RT_SCOPE_LINK的源地址,否则出错。
    当验证了源地址的有效性之后,我们建立路由项,即结构体struct rtable。该路由项的rt_type值是RTN_MULTICAST,表示这一条组播路由。对于本地接收的组播包,我们设置接收函数为myip_local_deliver。
    有了这个路由项,我们可以通过调用myip_local_deliver,继续接收流程,这部分流程前面已有多次介绍,所以讲得简单一点,只注意组播特有 的。同样,到myip_local_deliver_finish后,首先要检查是否有raw socket要接收这个组播包。然后根据IP首部里协议字段,调用相应协议的接收函数,我们这儿是一个UDP组播包,所以调用myudp_rcv。
    myudp_rcv首先会对路由项的成员rt_flags作一个检查,如果发现它有RTCF_BROADCAST或者RTCF_MULTICAST,就不 会走常规的从myudp_hash中匹配源和目的地址,找到socket,把数据报放入接收队列这么一个流程。而是调用函数 myudp_v4_mcast_deliver,这是一个专用于接收UDP组播数据报的函数,它首先根据目的端口确定在哈希表mydup_hash中的位 置,然后遍历找到的这个链表。与普通的UDP数据报接收相比,它多一个过滤检查,即在套接字结构体的成员mc_list中找到与该数据报所属组对应的 ip_mc_socklist项,查看它的过滤配置,确认该数据报的源地址是否在过滤列表中。如果不在,则把数据放到该socket的接收队列中,完成组 播数据报的接收。
阅读(3972) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~