我尝试在Linux中处理多播数据包流。在266s-278s(并非总是完全相同的时间段)内,接收工作正常,但此后,不再接收任何数据包。
这是我初始化多播的方式:
int arg = 1;
int fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if(fd == -1) {
fprintf(stderr, "Error creating socket, %s\n", strerror(errno));
return;
}
if(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &arg, sizeof(arg)) < 0) {
fprintf(stderr, "Failed to set `SO_REUSEADDR`, %s\n", strerror(errno));
return;
}
fcntl(fd, F_SETFL, O_NONBLOCK);
static struct ifreq intf;
strncpy(intf.ifr_name, cfg->ifname_buf, IF_NAMESIZE);
if(setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, (char*)&intf, sizeof(intf)) < 0) {
fprintf(stderr, "Failed to set `SO_BINDTODEVICE`, %s\n", strerror(errno));
return;
}
struct sockaddr_in sin;
memset(&sin, 0, sizeof(struct sockaddr_in));
sin.sin_family = AF_INET;
sin.sin_port = htons(xxxxx);
sin.sin_addr.s_addr = inet_addr("xxx.xxx.xxx.xxx");
if(bind(fd, (struct sockaddr*)&sin, sizeof(struct sockaddr)) < 0) {
fprintf(stderr, "Error on binding socket, %s\n", strerror(errno));
return;
}
ioctl(fd, SIOCGIFADDR, &intf);
struct ip_mreqn igmpv2_req;
memset(&igmpv2_req, 0, sizeof(struct ip_mreqn));
if(inet_pton(AF_INET, "xxx.xxx.xxx.xxx", &igmpv2_req.imr_multiaddr.s_addr)) {
memcpy(&igmpv2_req.imr_address, &cfg->ifaddr.sin_addr, sizeof(struct in_addr));
igmpv2_req.imr_ifindex = cfg->ifindex;
printf("Multiaddr: %s\n", inet_ntoa(igmpv2_req.imr_multiaddr));
printf("Interfaceaddr: %s\n", inet_ntoa(igmpv2_req.imr_address));
printf("Ifindex: %d\n", igmpv2_req.imr_ifindex);
if(setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &igmpv2_req, sizeof(struct ip_mreqn)) < 0) {
fprintf(stderr, "Failed to set `IP_ADD_MEMBERSHIP`: %s\n", strerror(errno));
return;
} else {
printf("Saved FD for igmp socket!\n");
cfg->socket_fd_igmp = fd;
}
} else {
fprintf(stderr, "Failed `inet_pton` igmp-multiaddr, %s\n", strerror(errno));
return;
}
正如我说的,它可以在266-280秒内正常工作。在那之后,没有数据包被接收。我不知道这是因为我向多播组添加接口的方式还是因为某些内核队列已满(我每秒接收多达200k数据包)。
多播不是一件小事。根据您的描述,会发生以下情况:
表演时
setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &igmpv2_req, sizeof(struct ip_mreqn))
然后,客户端为此组发送igmp加入消息。您的交换机已启用igmp snooping,现在知道将该组的多播数据包转发到主机的端口。
现在,在您观察到的时间之后(4-5分钟,对于许多交换机来说,默认时间是260秒),交换机中的此信息将超时,因为主机不会定期/主动发送这些消息。 >
您需要网络上的多播路由器
,该路由器定期查询主机,主机以igmp报告响应它们正在侦听的多播组,以保持交换硬件上的igmp侦听表到目前为止。或者,您也可以尝试在多播发送方和接收方之间的所有设备上禁用igmp侦听,以使all
多播消息泛洪到all端口(使它们从第2层广播)视图)。这可能会在第2层网段上施加很高的负载,因此首选第一种方法。一个丑陋的解决方法(我尚未测试)可能是每2-3分钟删除并重新添加setsockopt()
的成员资格。这应该强制igmp数据包,从而维持多播连接,但这不是应该的工作方式。