接收组播需要设置local_ip 目的是为了让内核知道是哪个网卡接收组播数据,否则内核会随机选择一个网卡接收组播数据。
一、绑定网卡的设置
多网卡指定一个网卡接收组播的三个关键设置:
接收udp组播的网卡ip,必须设置为跟组播发送ip一个网段的ip,否则接收不到组播数据。
代码里本地监听bind地址必须是0.0.0.0,端口为组播端口。
代码加入组播addmembership指定imr_interface的ip地址为接收组播的网卡ip。 代码demo参考:multicast_receiver.c
指定源组播,linux和windows编程稍微有差别:
linux: bind 的是组播地址和组播端口
windows:bind 的是接收网卡的地址ip和组播端口
二、组播相关设置和错误现象描述
1.防火墙状态查询
systemctl status firewalld #查询防火墙状态 Active: inactive (dead) 则为关闭状态
systemctl stop firewalld.service #关闭防火墙
2. 网卡过滤组播包设置
1 看接受组播的网卡是否过滤了:
cat /proc/sys/net/ipv4/conf/en4/rp_filter
如果是0, good。
2 看all网卡是否过滤了:
cat /proc/sys/net/ipv4/conf/all/rp_filter
如果是0, good。
这两个值都必须是0,才行!如果不是0,这样修改:
3 临时修改取消过滤:
sudo sysctl -w net.ipv4.conf.en4.rp_filter=0
sudo sysctl -w net.ipv4.conf.all.rp_filter=0
4 永久修改取消过滤(重启亦有效):
sudo vi /etc/sysctl.conf
改为:
net.ipv4.conf.default.rp_filter=0
net.ipv4.conf.all.rp_filter=0
rp_filter参数介绍 rp_filter参数用于控制系统是否开启对数据包源地址的校验。 首先看一下Linux内核文档documentation/networking/ip-sysctl.txt中的描述: 即rp_filter参数有三个值,0、1、2,具体含义: 0:不开启源地址校验。 1:开启严格的反向路径校验。对每个进来的数据包,校验其反向路径是否是最佳路径。如果反向路径不是最佳路径,则直接丢弃该数据包。 2:开启松散的反向路径校验。对每个进来的数据包,校验其源地址是否可达,即反向路径是否能通(通过任意网口),如果反向路径不同,则直接丢弃该数据包。 什么是反向路由校验 所谓反向路由校验,就是在一个网卡收到数据包后,把源地址和目标地址对调后查找路由出口,从而得到反身后路由出口。然后根据反向路由出口进行过滤。
当rp_filter的值为1时,要求反向路由的出口必须与数据包的入口网卡是同一块,否则就会丢弃数据包。 当rp_filter的值为2时,要求反向路由必须是可达的,如果反路由不可达,则会丢弃数据包
3. 可以接收到组播,但是接收一段时间就收不到了。时间一般是路由器配置查询器的时间的两倍。
原因:网卡未添加组播路由,所以没有持续发IGMP包,路由器查询后发现没有端口收流,就不继续往端口发流。 解决办法:讲网卡添加到路由地址
route add -net 0.0.0.0 netmask 0.0.0.0 dev en4
4. 对于要多网卡收流
现象描述: 网卡1(192.168.100.71) :可以收到组播地址的流(source 192.168.100.150);网卡2(192.168.1.171):收不到组播地址的流(source 192.168.100.150)
原因: 网卡2发送不了IGMP的包,原因1.171不知道里没有100.150的路由,所以不知道往哪里发送,解决方法:route add -net 192.168.100.150 netmask 255.255.255.255 dev enp1s0f2,这样网卡2可以收到组播包,但是网卡1收不到组播包了。
因此要想多网卡都接收组播流,配置路由就不行了。
我还尝试了 sysctl -w net.ipv4.conf.all.rp_filter=2,当把所有网卡的的内核参数都设置2后,网卡enp1s0f2可以收到流了,但是收一段时间后,流就停了,用tcpdump -i enp1s0f2 igmp -l -n -vv 观察,enp1s0f2仅仅收到交换机发送的igmp查询包,却没有enp1s0f2发送的IGMP的包(只有刚开始加入组的时候有两个IGMP的包,正常情况应该是加入的时候发送两个IGMP包,然后每隔一段时间,再发送一个IGMP包)。
后来运行下面的命令,就可以多网卡收流:
sysctl -w net.ipv4.conf.all.rp_filter=0
cat /proc/sys/net/ipv4/conf/all/rp_filter
切记:有几个网卡,就要执行几次sysctl -w net.ipv4.conf.网卡名.rp_filter=0,每个网卡执行一下次 原文链接
三、抓包
tcpdump -i en4 host 230.13.0.2 and port 3456 and udp -w ./udp.cap 用wireshark打开udp.cap,可以看到组播数据。或者直接在控制台观看: tcpdump -vv -i en4 host 230.13.0.2
修改网卡的ip(改为抓包看到的src的ip同网段):
(ubuntu16.04)修改sudo vi /etc/network/interfaces auto en4 iface en4 inet static address 180.0.0.109 netmask 255.255.255.0
重启这个网卡: sudo ifdown en4 sudo ifup en4
如果ip没改过来,再: sudo ifconfig en4 180.0.0.109