*,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,广播与多播,单播,/,广播,/,多播通信,单播通信:网络中单一的源节点发送封包到单一的目的节点。,广播通信:将封包从一个节点发送到所有其他节点。,多播通信:将封包从一个节点发送到其他多个网络节点的集合。,广播通信,广播、多播仅适用于,UDP,协议,广播的负面作用是明显的:多个进程都发送广播数据,网络性能会受到影响。,几乎所有路由器都不转发广播数据,广播程序仅应用于本地子网。,发送广播数据,SOCKET s=:,socket(AF_INET,SOCK_DGRAM,0);,/,有效,SO_BROADCAST,选项,BOOL,bBroadcast,=TRUE;,:,setsockopt(s,SOL_SOCKET,SO_BROADCAST,(char*)&,bBroadcast,sizeof(BOOL,);,/,设置广播地址,这里的广播端口号(电台)是,4567,SOCKADDR_IN,bcast,;,bcast.sin_family,=AF_INET;,bcast.sin_addr.s_addr,=INADDR_BROADCAST;,/:inet_addr(255.255.255.255);,bcast.sin_port,=htons(4567);,/,发送广播,printf,(,开始向,4567,端口发送广播数据,.n,n,);,char,sz,=This is just a test.,rn,;,while(TRUE,),:,sendto(s,sz,strlen(sz,),0,(,sockaddr,*)&,bcast,sizeof(bcast,);,:Sleep(5000);,套接字选项,套接字选项和,I/O,控制命令用于改变套接字的默认行为,主要的函数:,getsockopt(SOCKET,s,int,level,int,optname,char,*,optval,int,*,optlen,);,setsockopt(SOCKET,s,int,level,int,optname,char,*,optval,int,optlen,);,s,:套接字句柄,level,:指定选项定义在哪个级别,optname,:套接字选项名称,optval,:指定一个缓冲区,用于选项的值,optlen,:,optval,所指缓冲区的大小,level,网络是分层的,每层上又有多个协议,因此套接字选项有不同的级别,常见级别:,SOL_SOCKET,(对应应用层),IPPROTO_TCP,(对应传输层的,TCP,协议,IPPROTO_UDP,(对应传输层的,UDP,协议),IPPROTO_IP,(对应网络层的,IP,协议),optname,各级别的选项不同,同一级别不同协议的选项也可能不同,SOL_SOCKET,级别的选项,SO_BROADCAST,BOOL,型,设置套接字传输和接收广播消息。如果给定套接字已进行过设置,则返回,TRUE,。该选项只对不是,SOCKET_STREAM,类型的套接字有效,SO_REUSEADDR,BOOL,型,设置为,TRUE,,套接字可以被绑定到一个已经使用的本地地址。,不能将两个监听套接字绑定到相同的本地地址,IPPROTO_IP,级别的选项,IP_TTL,设置和获取,IP,头中的,TTL,参数,IP_ADD_MEMBERSHIP,加入多播组,IP_DROP_MEMBERSHIP,离开多播组,程序实例,BOOL,bBroadcast,=TRUE;,setsockopt(s,SOL_SOCKET,SO_BROADCAST,(char*)&,bBroadcast,sizeof(BOOL,);,level:SOL_SOCKET,optname,:SO_BROADCAST,optval,:TRUE,,但需要进行类型转换,optlen,:,一个,bool,值所需要的缓冲区大小,广播地址,SOCKADDR_IN,bcast,;,bcast.sin_family,=AF_INET;,bcast.sin_addr.s_addr,=INADDR_BROADCAST;,/:inet_addr(255.255.255.255);,bcast.sin_port,=htons(4567);,INADDR_BROADCAST,此处等价于特殊地址“,255.255.255.255”,此地址用于对所处网络几乎没有了解的条件下,一般的广播地址:,IP,地址中主机号为全,1,接收广播数据,接收程序只需要将套接字绑定到广播端口,即可接收同一子网内的该端口上的广播数据,SOCKADDR_IN sin;,sin.sin_family,=AF_INET;,sin.sin_addr.S_un.S_addr,=INADDR_ANY;,sin.sin_port,=:ntohs(4567);,if(:bind(s,(,sockaddr,*)&sin,sizeof(sin,)=SOCKET_ERROR),printf,(bind()failed n);,return;,recv,(),与,recvfrom,(),recvfrom,(),还可以得到数据来源端的地址,示例程序中用,recv,(),也可以完成功能,多播(,Multicast,)通信,广播的负面作用是显而易见的,多播是将封包发送到多个节点的更为可行的方法,多播地址,发送多播数据需要一个多播地址。每个多播地址代表一个多播组。,多播地址的范围,224.0.0.0 239.255.255.255,保留的多播地址,地址,用途,224.0.0.0,基地址(保留),224.0.0.1,本子网上的所有地址,224.0.0.2,本子网上所有路由器,224.0.0.4,网段中所有,DVMRP,路由器,224.0.0.5,所有的,OSPF,路由器,224.0.0.6,所有的,OSPF,指派路由器,224.0.0.9,所有,RIPv2,路由器,224.0.0.13,所有,PIM,路由器,事实上,许多路由器拒绝转发目的地址为,224.0.0.0224.0.0.255,间的任何多播数据,组管理协议(,IGMP,),IPV4,用于管理多播客户和他们之间关系的协议,IGMP,用于通知路由器对指定组的数据感兴趣,终端加入多播组时,将指定,TTL,值,指明终端的多播程序想要经过多少个路由器发送和接收数据,加入多播组,ip_mreq,mcast,;,mcast.imr_interface.S_un.S_addr,=INADDR_ANY;,mcast.imr_multiaddr.S_un.S_addr,=inet_addr(234.5.6.7);,/,多播地址为,234.5.6.7,setsockopt(s,IPPROTO_IP,IP_ADD_MEMBERSHIP,(char*)&,mcast,sizeof(mcast,);,通过设置套接字选项,加入多播组,ip_mreq,结构,Typedef,struct,/,多播地址,struct,in_addr,imr_multiaddr,;,/,将要加入或离开多播组的本地地址,struct,in_addr,imr_interface,;,离开多播组,ip_mreq,mcast,;,mcast.imr_interface.S_un.S_addr,=,dwInterFace,;,mcast.imr_multiaddr.S_un.S_addr,=,dwMultiAddr,;,setsockopt(s,IPPROTO_IP,IP_DROP_MEMBERSHIP,(char*)&,mcast,sizeof(mcast,);,通过设置套接字选项,离开多播组,接收多播数据,接收多播数据,必须加入特定的多播组,并将套接字绑定到特定的端口。,char buf1280;,int,nAddrLen,=,sizeof(si,);,int,nRet,=:,recvfrom(s,buf,strlen(buf,),0,(,sockaddr,*)&,si,&,nAddrLen,);,发送多播数据,向特定的组发送多播数据,并不必要加入这个组。,准备好多播数据,准备好多播地址,即可调用,sendto,(),发送,char,sz,=This is just a test.,rn,;,while(TRUE,),:,sendto(s,sz,strlen(sz,),0,(,sockaddr,*)&,bcast,sizeof(bcast,);,:Sleep(5000);,带有源地址的,IP,多播,带源地址的,IP,多播允许加入组时指定要接收哪些成员的数据。,可以使用“包含”和“排除”两种方式加入组,“包含”方式:指定多个有效的源地址,套接字仅接收来自这些源地址的数据,“排除”方式:指定多个有效的源地址,套接字不接收来自这些源地址的数据,“包含”方式,使用,IP_ADD_SOURCE_MEMBERSHIP,选项配置套接字,加入多播组,并指定数据的源地址,选项的值为一个,ip_mreq_source,结构,使用,IP_DROP_SOURCE_MEMBERSHIP,从集合中移除源地址,ip_mreq_source,结构,struct,ip_mreq_source,/,多播组地址,struct,in_addr,imr_multiaddr,;,/,指定的源地址,struct,in_addr,imr_sourceaddr,;,/,本地地址接口,struct,in_addr,imr_interface,;,“,排除”方式,使用,IP_ADD_MEMBERSHIP,选项加入组,此时使用的就是“排除”方式,使用,IP_BLOCK_SOURCE,选项来指定要派出的源地址,