linux 在多网卡下的设备的UDP 组播问题总结
来源:互联网 发布:java基础教程 免费下载 编辑:程序博客网 时间:2024/04/30 17:07
参考博文:
解决接收不到组播包的问题 - 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、在多网卡实现多播(如设备搜索)相关的功能时,可以针对多个网卡分别执行一次操作,同时可以区分设备是从哪个网卡搜索到的。
0 0
- linux 在多网卡下的设备的UDP 组播问题总结
- rp_filter及Linux下多网卡接收多播的问题
- rp_filter及Linux下多网卡接收多播的问题
- Java UDP组播的总结
- Fedora16下的网卡设备命名问题
- Linux下UDP的组播接收和发送的简单例子
- 双网卡下使用udp带来的问题
- linux下双网卡接收组播需要修改的参数
- linux多网卡接收组播丢失问题
- linux下的多播
- UDP组播的实现
- linux下解决设备权限的问题总结
- 关于QT UDP组播的两个问题
- 关于QT UDP组播的两个问题
- CentOS多网卡下 应用层无法收到组播的问题解决
- LINUX下添加多个网卡的排序问题
- 使用组播来做设备搜索时要注意一下组播路由所在的网卡
- 设备发现(广播多播可能需要处理的问题)
- 一些常见HTTP状态码
- 蓄水池抽样算法及其python实现
- 51nod 1073 约瑟夫环
- 神经网络“动物园”
- svn提交忽略文件或文件夹
- linux 在多网卡下的设备的UDP 组播问题总结
- scala-problem26-30
- ubuntu16.4.sudoer
- 简单模拟Sping MVC
- Hadoop: CDH 5--不同步的 JournalNode
- RecyclerView的简单使用
- 【JLOI 2011】飞行路线 SPFA+分层图
- 【NOIP模拟】排序
- Windows和Mac下安装Beautiful Soup