UDP组播接收的代码如下:
struct sockaddr_in localSock;
struct ip_mreq group;
int sd;
int datalen;
char databuf[1024];
int main (int argc, char *argv[])
{
sd = socket(AF_INET, SOCK_DGRAM, 0);
if (sd < 0) {
perror("opening datagram socket");
exit(1);
}
memset((char *) &localSock, 0, sizeof(localSock));
localSock.sin_family = AF_INET;
localSock.sin_port = htons(5555);;
localSock.sin_addr.s_addr = INADDR_ANY; // or mcast_ip
if (bind(sd, (struct sockaddr*)&localSock, sizeof(localSock))) {
perror("binding datagram socket");
close(sd);
exit(1);
}
group.imr_multiaddr.s_addr = inet_addr("225.1.1.1"); //mcast_ip
group.imr_interface.s_addr = inet_addr("9.5.1.1"); //local_ip
if (setsockopt(sd, IPPROTO_IP, IP_ADD_MEMBERSHIP,
(char *)&group, sizeof(group)) < 0) {
perror("adding multicast group");
close(sd);
exit(1);
}
datalen = sizeof(databuf);
if (read(sd, databuf, datalen) < 0) {
perror("reading datagram message");
close(sd);
exit(1);
}
}
socket有两个操作,一个是bind, 一个是setsockopt(sd, IPPROTO_IP, IP_ADD_MEMBERSHIP,…)。
- bind()
TCP中bind()的意思是将该socket绑定到某个IP:PORT上,组播的意思是socket只接收该组播组的数据包。
如果这里绑定的是INADDR_ANY
, 这个socket就讲接收到能听到的所有组播组IP相同端口的数据包, 即组播IP不同,端口相同时,组播串线的情况。
如果这里绑定的是某个具体组播组的IP, 这里内核向socket发送数据的时候就会过滤掉不是该组播组的数据。
据说在Windows中应该绑定物理网卡的IP地址, 而不是组播地址。
- IP_ADD_MEMBERSHIP
IP_ADD_MEMBERSHIP意思是加入组播组。 根据IGMP协议,主机将会向组播管理端发送一个报文,报告本机要加入某个交换机,交换机就会向相应的端口转发这个组播组的数据包。 group.imr_multiaddr.s_addr
为组播组IP。
group.imr_interface.s_addr
一般写要加入组播组主机的接口/网卡的 IP, 以确定收取哪一个子网的组播信息,会通过该接口接收组播包。如果设为INADDR_ANY(0.0.0.0),则使用默认的IPV4组播接口。
route -n
可以显示默认组播路由。
只有交换机的某个端口有对应组播组的接收host加入过组播组, 交换机才会向该端口组播数据包,否则默认是不不组播的。
补充:
IP_ADD_SOURCE_MEMBERSHIP可以指定组播源的IP, 即source_ip.
IP_MULTICAST_IF 可以设置组播发送端口
Ref:
https://www.ibm.com/support/knowledgecenter/ssw_ibm_i_71/rzab6/x2multicast.htm