Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/62.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C Linux多播数据包在4分钟后耗尽_C_Linux_Networking_Multicast - Fatal编程技术网

C Linux多播数据包在4分钟后耗尽

C Linux多播数据包在4分钟后耗尽,c,linux,networking,multicast,C,Linux,Networking,Multicast,我尝试在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(sets

我尝试在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;
}
int arg=1;
int fd=插座(AF INET、SOCK DGRAM、IPPROTO_UDP);
如果(fd==-1){
fprintf(stderr,“创建套接字时出错,%s\n”,strerror(errno));
返回;
}
if(setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,&arg,sizeof(arg))<0){
fprintf(stderr,“未能设置'SO_REUSEADDR',%s\n”,strerror(errno));
返回;
}
fcntl(fd、F_设置FL、O_非块);
静态结构ifreq intf;
strncpy(intf.ifr\u name,cfg->ifname\u buf,IF\u namize);
if(setsockopt(fd,SOL_SOCKET,SO_BINDTODEVICE,(char*)&intf,sizeof(intf))<0){
fprintf(stderr,“未能设置'SO_BINDTODEVICE',%s\n”,strerror(errno));
返回;
}
sin中的结构sockaddr_;
memset(&sin,0,sizeof(struct sockaddru 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,“绑定套接字上的错误,%s\n”,strerror(errno));
返回;
}
ioctl(fd、SIOCGIFADDR和intf);
结构ip_mreqn igmpv2_请求;
memset(&igmpv2_-req,0,sizeof(struct-ip_-mreqn));
if(inet\u pton(AF\u inet,“xxx.xxx.xxx.xxx”、&igmpv2\u request.imr\u multiaddr.s\u addr)){
memcpy(&igmpv2_req.imr_address,&cfg->ifaddr.sin_addr,sizeof(struct in_addr));
igmpv2_req.imr_iIndex=cfg->iIndex;
printf(“多地址:%s\n”,inet_ntoa(igmpv2_req.imr_Multiaddr));
printf(“Interfaceaddr:%s\n”,inet_ntoa(igmpv2_请求imr_地址));
printf(“iIndex:%d\n”,igmpv2\u请求imr\u iIndex);
if(setsockopt(fd、IPPROTO_IP、IP_ADD_MEMBERSHIP和igmpv2_req、sizeof(struct IP_mreqn))小于0){
fprintf(stderr,“未能设置'IP\u添加\u成员资格”:%s\n”,strerror(errno));
返回;
}否则{
printf(“为igmp套接字保存的FD!\n”);
cfg->socket\u fd\u igmp=fd;
}
}否则{
fprintf(stderr,“Failed`inet\u pton`igmp multiaddr,%s\n”,strerror(errno));
返回;
}

正如我所说的,它在266-280秒时运行良好。在此之后,不会收到任何数据包。我不知道这是因为我向多播组添加接口的方式,还是因为某个内核队列已满(我每秒接收多达200k个数据包)。

多播不是一件小事。根据您的描述,发生了以下情况:

当你表演的时候

setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &igmpv2_req, sizeof(struct ip_mreqn))
然后,客户端为该组发送一条igmp连接消息。您的交换机已启用igmp侦听功能,现在知道将此组的多播数据包转发到主机端口

现在,在您观察到(4-5分钟,260秒确实是许多交换机的默认时间)交换机中的此信息超时,因为主机不会定期/主动发送这些消息

您的网络上需要一个多播路由器,该路由器定期查询主机,主机通过igmp报告响应它们正在侦听的多播组,以使交换硬件上的igmp侦听表保持最新

或者,您也可以尝试在多播发送方和接收方之间的所有设备上禁用igmp窥探,以便所有多播消息都被淹没到所有端口(使它们从第2层的角度进行广播)。这会给第2层管段带来相当大的负荷,因此首选第一种方法


一个丑陋的解决方法(我还没有测试过)可能是每隔2-3分钟使用
setsockopt()
删除并重新添加成员资格。这应该强制igmp数据包,从而保持多播连接,但这不是它应该如何工作的。

请回答您的问题并添加更多详细信息:您如何检测“未收到数据包”?您的程序是否阻止等待数据包?它是否显示错误消息?数据包嗅探器(如Wireshark)是否显示数据包?也许您应该显示接收数据包的代码。您知道Linux是否负责对交换机的响应吗?据我所知,我工作的网络已经有了所有这些多播路由器/交换机。@binaryBigInt“你知道Linux是否负责对交换机的响应吗?”交换机不查询(某些交换机型号可以配置为查询器,但这不是保证),这将是一个mcast路由器。您只需修复网络配置。禁用交换机上的IGMP侦听通常是个坏主意。如果主机上正确配置了IGMP,那么它应该响应这些问题。@RonMaupin
Ctx
刚刚写道,我需要一个多播路由器,用于查询订阅多播流的主机。如果他们没有回复,他们将从交换机/路由器中移除。如果我理解正确,这与您的陈述相反:
开关不查询
。因为我不负责网络配置,所以我必须假设网络中的所有东西都在正常工作,并且我的应用程序不会以某种方式响应用户的查询rooter@binaryBigInt,通常,开关不进行查询。IGMP sooping是被动侦听主机和路由器之间IGMP对话的交换机。IGMP是一种协议,用于主机和路由器相互通信,以确定局域网上应该存在哪些多播组流量。有些型号的交换机可以配置为查询器,但它不是通用的。路由器将查询路由器接口上配置的IGMP组。@RonMaupin很抱歉,这并不能解决我的问题。老实说,我不在乎是路由器还是交换机向主机查询IGMP响应。我甚至无权更改任何有关网络配置的内容