Linux加入多播组
多播数据报只应该由对它感兴趣的应用接收。广播一般局限与局域网内使用,而多播既可以用于局域网,也可以用于广域网。多播地址多播地址需要对IPv4和IPv6分开讨论。IPv4的D类地址(从224.0.0.0到239.255.255.255)是IPv4多播地址。其中低28位为group ID,整个32位为group address。一些特殊的IPv4多播地址:224.0.0.1...
·
多播数据报只应该由对它感兴趣的应用接收。
广播一般局限与局域网内使用,而多播既可以用于局域网,也可以用于广域网。
多播地址
多播地址需要对IPv4和IPv6分开讨论。
IPv4的D类地址(从224.0.0.0到239.255.255.255)是IPv4多播地址。其中低28位为group ID,整个32位为group address。
一些特殊的IPv4多播地址:
224.0.0.1:所有主机(all-hosts)组,所有具备多播功能的设备。
224.0.0.2:所有路由器(all-routers)组。
224.0.0.0到224.0.0.255之间的地址被称为link local,路由器从不转发以这些地址为目的地址的数据报。
IPv6多播地址
IPv6多播地址高位为ff。特殊的IPv6多播地址
ff01::1到ff02::1位all-nodes组,与IPv4的all-hosts意思是一样的。
ff01::2、ff02::2和ff05::2是all-routers组。
示例代码
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <linux/in.h>
#include <linux/if_ether.h>
#include <net/if.h>
#include <errno.h>
/**
* Join multicast group, support both IPv4 and IPv6.
* @param sockfd socket descripter
* @param grp sockaddr
* @param grplen sockaddr length
* @return 0:on success; non-zero:on failed
*/
static int mcast_join(int sockfd, const struct sockaddr *grp, socklen_t grplen)
{
#if MCAST_JOIN_GROUP
struct group_req req;
req.gr_interface = 0;
if (grplen > sizeof(req.gr_group)) {
errno = EINVAL;
return -1;
}
memcpy(&req.gr_group, grp, grplen);
return (setsockopt(sockfd, IPPROTO_IP, MCAST_JOIN_GROUP, &req, sizeof(req)));
#else
switch (grp->sa_family) {
case AF_INET: {
struct ip_mreq mreq;
struct ifreq ifreq;
memcpy(&mreq.imr_multiaddr,
&((const struct sockaddr_in *) grp)->sin_addr,
sizeof(struct in_addr));
mreq.imr_interface.s_addr = htonl(INADDR_ANY);
return (setsockopt(sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP,
&mreq, sizeof(mreq)));
}
#ifdef IPV6
#ifndef IPV6_JOIN_GROUP /* APIv0 compatibility */
#define IPV6_JOIN_GROUP IPV6_ADD_MEMBERSHIP
#endif
case AF_INET6: {
struct ipv6_mreq mreq6;
memcpy(&mreq6.ipv6mr_multiaddr,
&((const struct sockaddr_in6 *) grp)->sin6_addr,
sizeof(struct in6_addr));
mreq6.ipv6mr_interface = 0;
return (setsockopt(sockfd, IPPROTO_IPV6, IPV6_JOIN_GROUP,
&mreq6, sizeof(mreq6)));
}
#endif
default:
errno = EAFNOSUPPORT;
return -1;
}
#endif
}
int main(int argc, char **argv)
{
int fd = socket(AF_INET, SOCK_DGRAM, 0);
struct sockaddr_in grp;
bzero(&grp, sizeof(grp));
grp.sin_family = AF_INET;
grp.sin_addr.s_addr = inet_addr("224.0.0.1");;
if (mcast_join(fd, (struct sockaddr*)(&grp), sizeof(grp)))
perror("Join multicast group failed");
}
更多推荐
已为社区贡献4条内容
所有评论(0)