IGMPv2通过查询器选举机制为所连网段选举唯一的查询器。查询器周期性的发送普遍组查询消息进行成员关系查询;主机发送报告消息来应答查询。当要加入组播组时,主机不必等待查询消息,主动发送报告消息。当要离开组播组时,主机发送离开组消息;收到离开组消息后,查询器发送特定组查询消息来确定是否所有组成员都已离开。
通过上述IGMP机制,在组播路由器里建立起一张表,其中包含路由器的各个端口以及在端口所对应的子网上都有哪些组的成员。当路由器接收到某个组G的数据报文后,只向那些有G的成员的端口上转发数据报文。至于数据报文在路由器之间如何转发则由路由协议决定,IGM
socket创建UDP通信描述符后,setsockopt加入多播组,再bind绑定到该网卡上//在指定的IP和端口上接收多播组的报文
int recv_msg(char *ip , unsigned short port , char *mult_ip )
{
//建立通讯套接字
int fd = socket( PF_INET , SOCK_DGRAM , 0 )
if( -1 == fd )
{
perror("socket failed")
return -1
}
//设置地址重用和接收多播
{
int reuse = 1
struct ip_mreqn mult_addr = {0}
mult_addr.imr_multiaddr.s_addr = inet_addr( mult_ip )
mult_addr.imr_address.s_addr = inet_addr( ip )
if( -1 == setsockopt( fd , IPPROTO_IP , IP_ADD_MEMBERSHIP ,
&mult_addr , sizeof(mult_addr)))
{
perror("setsockopt add failed")
goto _out
}
if( -1 == setsockopt( fd , SOL_SOCKET, SO_REUSEADDR,
&reuse , sizeof(reuse) ) )
{
perror("setsockopt reuse failed")
}
}
//绑定地址和端口
{
struct sockaddr_in addr = {0}
addr.sin_family = PF_INET
addr.sin_port = htons( port )
addr.sin_addr.s_addr = INADDR_ANY
if( -1 == bind( fd , (struct sockaddr*)&addr ,
sizeof(addr) ) )
{
perror("bind failed")
goto _out
}
}
//接收信息
while(1)
{
char buf[128] = {0}
int ret = 0
struct sockaddr_in client_addr = {0}
int len = sizeof(client_addr)
ret = recvfrom( fd , buf , sizeof(buf), 0 ,
(struct sockaddr*)&client_addr ,
&len )
//被信号中断则重启
if( (-1 == ret)&&(EINTR ==errno ))
{
continue
}
else if( -1 ==ret )
{
perror("recvfrom failed")
goto _out
}
else if( ret >0 )
{
printf("%s\n" , buf )
}
usleep( 100*1000 )
}
_out:
if( fd >= 0)
{
close( fd )
}
return 0
}
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)