关于IP_ADD_MEMBERSHIP的文档说:
IP_ADD_MEMBERSHIP(自Linux 1.2起) 加入组播组。参数是一个ip_mreqn结构。
var InsuranceVM = new Vue({ delimiters: ['[[', ']]'], el: '#insurance-form', data: { insurance_types: [], insurance_type: '', insurance_types_get_error: '', }, watch: { // whenever question changes, this function will run insurance_type: function (newQuestion, oldQuestion) { //this.answer = 'Waiting for you to stop typing...' this.getAnswer(newQuestion) } }, methods: { getAnswer: _.debounce( function () { var vm = this; axios.post('http://35.196.91.194/insurance-list', {}) .then(function (response) { vm.insurance_types_get_error = ''; vm.insurance_types = response.data.results; }) .catch(function (error) { vm.insurance_types_get_error = 'Error! Could not reach the API. ' + error; }) }, 500 ) } });
所以我有一个界面" eth0"用ip 192.168.1.5。我想将此接口加入多播组225.1.1.1。我对如何正确设置ip_mreqn结构有点困惑?我发现了两种可能的方式:
1
struct ip_mreqn {
struct in_addr imr_multiaddr; /* IP multicast group
address */
struct in_addr imr_address; /* IP address of local
interface */
int imr_ifindex; /* interface index */
};
imr_multiaddr contains the address of the multicast group the appli‐
cation wants to join or leave. It must be a valid multicast address
(or setsockopt(2) fails with the error EINVAL). imr_address is the
address of the local interface with which the system should join the
multicast group; if it is equal to INADDR_ANY, an appropriate inter‐
face is chosen by the system. imr_ifindex is the interface index of
the interface that should join/leave the imr_multiaddr group, or 0 to
indicate any interface.
2
ip_mreqn group;
group.imr_multiaddr.s_addr = inet_addr("225.1.1.1");
group.imr_address.s_addr = inet_addr("192.168.1.5");
group.imr_ifindex = 0;
第三种方法是使用SO_BINDTODEVICE套接字选项。
我的问题是。
1)将特定接口加入组播组的正确方法是什么?
2)imr_address和imr_ifindex之间的功能区别是什么?
3)SO_BINDTODEVICE选项如何有用?
编辑:我做了一些研究。
假设我有两个网络接口:eth0与ip 192.168.1.5和eth1与ip 192.168.1.255我在eth0上接收多播,ip 192.168.1.5。
这些方法正常工作(我在eth0上收到多播消息):
ip_mreqn group;
group.imr_multiaddr.s_addr = inet_addr("225.1.1.1");
group.imr_address.s_addr = htonl(INADDR_ANY);
group.imr_ifindex = if_nametoindex("eth0");
或
group.imr_address.s_addr = inet_addr("192.168.1.5");
group.imr_ifindex = 0;
或显然
group.imr_address.s_addr = htonl(INADDR_ANY);
group.imr_ifindex = if_nametoindex("eth0");
甚至
group.imr_address.s_addr = inet_addr("192.168.1.5");
group.imr_ifindex = if_nametoindex("eth0");
这些方式不(我不会在eth0上收到多播消息):
group.imr_address.s_addr = inet_addr("192.168.1.255");
group.imr_ifindex = if_nametoindex("eth0");
和
group.imr_address.s_addr = inet_addr("192.168.1.5");
group.imr_ifindex = if_nametoindex("eth1");
答案 0 :(得分:1)
我一直使用较早的struct ip_mreq
代替struct ip_mreqn
,因为两者都受支持。这个结构没有索引字段,因此它对于你需要设置的内容不那么模糊。
struct ip_mreq
{
/* IP multicast address of group. */
struct in_addr imr_multiaddr;
/* Local IP address of interface. */
struct in_addr imr_interface;
};
然后你会这样设置:
struct ip_mreq group;
group.imr_multiaddr.s_addr = inet_addr("225.1.1.1");
group.imr_interface.s_addr = inet_addr("192.168.1.5");
答案 1 :(得分:0)
ip_mreqn
用于在 linux/net/ipv4/igmp.c
(linux 5.13) 的内核源代码中查找网络接口设备,如下所示。
static struct in_device *ip_mc_find_dev(struct net *net, struct ip_mreqn *imr)
{
struct net_device *dev = NULL;
struct in_device *idev = NULL;
if (imr->imr_ifindex) {
idev = inetdev_by_index(net, imr->imr_ifindex);
return idev;
}
if (imr->imr_address.s_addr) {
dev = __ip_dev_find(net, imr->imr_address.s_addr, false);
if (!dev)
return NULL;
}
if (!dev) {
struct rtable *rt = ip_route_output(net,
imr->imr_multiaddr.s_addr,
0, 0, 0);
if (!IS_ERR(rt)) {
dev = rt->dst.dev;
ip_rt_put(rt);
}
}
if (dev) {
imr->imr_ifindex = dev->ifindex;
idev = __in_dev_get_rtnl(dev);
}
return idev;
}
imr->imr_ifindex
首先用于搜索设备。如果未找到,则使用 imr->imr_address
。