linux 在多网卡下的设备的UDP 组播问题总结
2016-09-15 18:33
1586 查看
参考博文:
解决接收不到组播包的问题 - Justlinux2010的专栏 - 博客频道 - CSDN.NET
http://blog.csdn.net/justlinux2010/article/details/11140383
1、问题描述
实现在多网卡设备上发送组播消息,实现设备搜索,并接收通过组播返回的搜索信息。
设备为多网卡nvr,有一个常规网卡和一个PPPOE口;在进行发送组播搜索ipc时,只可以在常规网卡上接收到反馈的组播信息,而在ppoe上没有
2、问题原因及解决方法
关键代码(组播socket的初始化):
3、综述
在多网卡设备上实现组播需要特别注意:
1、使用setsockopt设置IP_ADD_MEMBERSHIP组播地址时,对应的本地地址必须被明确指定为要发送组播数据包的网卡的ip地址,而不可以使用INADDR_ANY设置;如果使用INADDR_ANY,则系统会默认根据路由表绑定一个明确的地址,则在接收组播信息时,无法从发送的网卡处接收到数据,发送的网卡没有被添加到组播组中。
2、必须使用setsockopt设置IP_MULTICAST_IF选项,从而修改默认的组播出口网卡。否则系统根据路由表发送到默认网关。而不一定是指定的网卡。
3、在多网卡实现多播(如设备搜索)相关的功能时,可以针对多个网卡分别执行一次操作,同时可以区分设备是从哪个网卡搜索到的。
解决接收不到组播包的问题 - Justlinux2010的专栏 - 博客频道 - CSDN.NET
http://blog.csdn.net/justlinux2010/article/details/11140383
1、问题描述
实现在多网卡设备上发送组播消息,实现设备搜索,并接收通过组播返回的搜索信息。
设备为多网卡nvr,有一个常规网卡和一个PPPOE口;在进行发送组播搜索ipc时,只可以在常规网卡上接收到反馈的组播信息,而在ppoe上没有
2、问题原因及解决方法
关键代码(组播socket的初始化):
int CreateMuticastSocket(const std::string ðx, int port) { int ret = 0; int sockfd = socket(AF_INET,SOCK_DGRAM,0); if(-1 == sockfd) { printf("socket error!!!\n"); perror("socket:"); return -1; } /*test ip*/ struct sockaddr_in localaddr = {0}; localaddr.sin_family = AF_INET; localaddr.sin_port = htons(port); localaddr.sin_addr.s_addr = htonl(INADDR_ANY); ret = bind(sockfd,(struct sockaddr*)&localaddr,sizeof(struct sockaddr)); if(-1 == ret) { printf("bind localaddr error!!!\n"); perror("bind:"); close(sockfd); return -1; } int reuse = 1; if(setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (char *)&reuse, sizeof(reuse)) < 0) { perror("Setting SO_REUSEADDR error"); close(sockfd); return -1; } /*设置是否支持本地回环接收*/ int loopBack=1; ret = setsockopt(sockfd,IPPROTO_IP, IP_MULTICAST_LOOP, &loopBack, sizeof(loopBack)); if(-1 == ret) { printf("setsockopt broadcaset error!!!\n"); perror("setsockopt:"); close(sockfd); return -1; } /* 将本地socket添加到多播组中,注意,此处针对struct ip_mreq结构体需要填充两个成员, 成员ipmr.imr_interface.s_addr的值指定的是将要发送的网卡的ip地址, 成员impr.imr_multiaddr指定的是组播地址; 如果指定为INADDR_ANY则系统会绑定一个默认网卡的具体ip(根据默认网关选择),则会出现特定网卡可以发送和接收组播信息,另一网卡不可以。即指定INADDR_ANY并不能把所有网卡都添加多播组中,必须明确指定对应网卡ip才可以。*/ struct in_addr addr = {0}; addr.s_addr=inet_addr(get_local_ip(ethx).c_str()); struct ip_mreq ipmr; ipmr.imr_interface.s_addr = addr.s_addr; ipmr.imr_multiaddr.s_addr = inet_addr(CONST_MULTICAST_IP_V4); ret=setsockopt(sockfd,IPPROTO_IP,IP_ADD_MEMBERSHIP,(const char*)&ipmr,sizeof(ipmr)); /*此处指定组播数据的出口网卡,如果不设置则会根据路由表指定默认路由出口*/ if(-1 == setsockopt(sockfd, IPPROTO_IP, IP_MULTICAST_IF, (char *)&addr, sizeof(addr))) { printf("set error IP_MULTICAST_IF %s\n", ethx.c_str()); perror("Setting IP_MULTICAST_IF error:"); close(sockfd); sockfd = -1; } struct timeval tv; tv.tv_sec = 2; tv.tv_usec = 0; ret = setsockopt(sockfd,SOL_SOCKET,SO_RCVTIMEO,(char*)&tv,sizeof(tv)); if(-1 == ret) { printf("setsockopt recvtimeout error!!!\n"); perror("setsockopt:"); close(sockfd); return -1; } return sockfd; }
3、综述
在多网卡设备上实现组播需要特别注意:
1、使用setsockopt设置IP_ADD_MEMBERSHIP组播地址时,对应的本地地址必须被明确指定为要发送组播数据包的网卡的ip地址,而不可以使用INADDR_ANY设置;如果使用INADDR_ANY,则系统会默认根据路由表绑定一个明确的地址,则在接收组播信息时,无法从发送的网卡处接收到数据,发送的网卡没有被添加到组播组中。
2、必须使用setsockopt设置IP_MULTICAST_IF选项,从而修改默认的组播出口网卡。否则系统根据路由表发送到默认网关。而不一定是指定的网卡。
3、在多网卡实现多播(如设备搜索)相关的功能时,可以针对多个网卡分别执行一次操作,同时可以区分设备是从哪个网卡搜索到的。
相关文章推荐
- 修改linux下网卡设备名的问题
- Linux 下 adb usb 连接 usb 设备问题总结
- Linux设备上的Onvif实现18: ONVIF视频监视功能开发问题总结
- linux udp组播接收问题及原理分析
- linux下编译新内核,解决无法找到eth0设备问题,安装eth0网卡驱动
- linux udp组播接收问题及原理分析
- 中标麒麟(linux)下QUdpSocket无法使用组播发送数据问题
- linux下解决设备权限的问题总结
- linux 组播接收和发送代码和组播问题总结
- 克隆Linux系统后找不到eth0网卡问题
- linux下使用C语言接收和发送udp组播数据分别怎么写?
- Linux 运维面试问题总结
- Linux:解决配置静态ip后eth0网卡启动不了的问题
- linux下 查看网卡流量办法总结
- linux下 查看网卡流量办法总结
- 建立LINUX开发环境并编译LINUX和UBOOT以及生成设备树过程总结
- linux下 查看网卡流量办法总结
- Linux下搭建 PPPoE Server 搭建及问题总结
- 解决linux(centos 6.5)下解决http://ip:50070 不显示DataNode的问题总结
- Linux UDP严重丢包问题的解决