我需要使用相同的端口侦听2个不同的组播组。 Program A
将从230.0.0.1
和Program B
收听230.0.0.2
。两个组播组都使用相同的port 2000
,我无法控制它。
当我运行程序时,我会在每个程序中收到两个组播流,即230.0.0.1
和230.0.0.2
上广播的数据包。我怀疑问题是由于公共端口造成的。这是我用来订阅多播的代码:
if( (sd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0 ) {
perror("socket");
return -1;
}
if( setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0 ) {
perror("setsockopt SO_REUSEADDR");
return -1;
}
memset(&in_addr, 0, sizeof(in_addr));
in_addr.sin_family = AF_INET;
in_addr.sin_addr.s_addr = htonl(INADDR_ANY);
in_addr.sin_port = htons(2000);
if( bind(sd, (struct sockaddr*)&in_addr, sizeof(in_addr)) < 0 ) {
perror("bind");
return -1;
}
memset(&req, 0, sizeof(req));
inet_aton(intfc_ip, &req.imr_interface);
inet_aton("230.0.0.1", &req.imr_multiaddr);
if( setsockopt(sd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &req, sizeof(req)) < 0 ) {
perror("setsockopt IP_ADD_MEMBERSHIP");
return -1;
}
recv()...
如何在每个程序中过滤特定的多播组?
答案 0 :(得分:4)
如果你改变了
in_addr.sin_addr.s_addr = htonl(INADDR_ANY);
到
inet_aton(<your wanted IP address>, &in_addr.sin_addr.s_addr);
你可以取得更大的成功。
(如果您将程序更改为使用getaddrinfo()
,则可以使其面向未来。)
答案 1 :(得分:3)
“连接”可能就是你所需要的。通常,为了连接TCP套接字,手册页还建议它可以用于过滤掉来自其他地址的UDP数据包:
从发布的here手册页
如果套接字sockfd的类型为SOCK_DGRAM,那么addr就是地址 默认情况下发送哪些数据报,和唯一的地址 收到数据报。
答案 2 :(得分:2)
套接字代码的问题是“recvfrom”只会为您提供发送数据包的源地址。它不会告诉您数据包发送到的位置的IP地址。您希望能够检查UDP数据包的目标地址,以便过滤掉发送到您不感兴趣的多播IP地址的数据包。
您可以设置一个套接字选项,然后使用“recvmsg”而不是recv或recvfrom来获取发送数据包的目标IP地址。
1)将setsockopt与IP_PKTINFO一起使用,以便为在套接字上收到的数据获取传递到应用级别的目标IP地址。
int enable = 1;
setsockopt(sock, IPPROTO_IP , IP_PKTINFO , &enable, sizeof(enable));
2)使用recvmsg而不是recvfrom(或recv)来获取UDP数据包发送到的目标地址。我有一个名为“recvfromex”的辅助函数,它包装了recvmsg并镜像了recvfrom的功能 - 期望它有一个额外的参数供调用者获取数据包的目标IP。
发布有点大风 - 但你可以从我的github项目中查看我的C ++代码并获取你需要的东西。
查看recvfromex函数here
setsockopt调用here的更多代码示例(查找有关如何使用与IP_PKTINFO的setsockopt调用的函数“EnablePktInfo”)。还包含IPV6和BSD的扩展名。
答案 3 :(得分:1)
(来自answer的Receving multiple multicast feeds on the same port - C, Linux)
ip(7) manpage描述了一种可能的解决方案:
IP_MULTICAST_ALL(自Linux 2.6.31起)
此选项可用于修改交付策略 组播消息到绑定到通配符INADDR_ANY的套接字 地址。参数是一个布尔整数(默认为1)。 如果设置为1,套接字将接收来自所有的消息 在整个系统上全局加入的组。 否则,它将仅从组中传递消息 已明确加入(例如通过 IP_ADD_MEMBERSHIP选项)在这个特定的套接字上。
然后,您可以使用以下命令激活过滤器以接收已加入组的消息:
int mc_all = 0;
if ((setsockopt(sock, IPPROTO_IP, IP_MULTICAST_ALL, (void*) &mc_all, sizeof(mc_all))) < 0) {
perror("setsockopt() failed");
}