1 / 26

广播与多播

广播与多播. 单播 / 广播 / 多播通信. 单播通信:网络中单一的源节点发送封包到单一的目的节点。 广播通信:将封包从一个节点发送到所有其他节点。 多播通信:将封包从一个节点发送到其他多个网络节点的集合。. 广播通信. 广播、多播仅适用于 UDP 协议 广播的负面作用是明显的:多个进程都发送广播数据,网络性能会受到影响。 几乎所有路由器都不转发广播数据,广播程序仅应用于本地子网。. 发送广播数据. SOCKET s = ::socket(AF_INET, SOCK_DGRAM, 0); // 有效 SO_BROADCAST 选项

jayden
Download Presentation

广播与多播

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 广播与多播

  2. 单播 / 广播 / 多播通信 • 单播通信:网络中单一的源节点发送封包到单一的目的节点。 • 广播通信:将封包从一个节点发送到所有其他节点。 • 多播通信:将封包从一个节点发送到其他多个网络节点的集合。

  3. 广播通信 • 广播、多播仅适用于UDP协议 • 广播的负面作用是明显的:多个进程都发送广播数据,网络性能会受到影响。 • 几乎所有路由器都不转发广播数据,广播程序仅应用于本地子网。

  4. 发送广播数据 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. \r\n"; while(TRUE) { ::sendto(s, sz, strlen(sz), 0, (sockaddr*)&bcast, sizeof(bcast)); ::Sleep(5000); }

  5. 套接字选项 • 套接字选项和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所指缓冲区的大小

  6. level • 网络是分层的,每层上又有多个协议,因此套接字选项有不同的级别 • 常见级别: • SOL_SOCKET(对应应用层) • IPPROTO_TCP(对应传输层的TCP协议 • IPPROTO_UDP (对应传输层的UDP协议) • IPPROTO_IP (对应网络层的IP协议)

  7. optname • 各级别的选项不同,同一级别不同协议的选项也可能不同

  8. SOL_SOCKET级别的选项 • SO_BROADCAST • BOOL型 • 设置套接字传输和接收广播消息。如果给定套接字已进行过设置,则返回TRUE 。该选项只对不是SOCKET_STREAM类型的套接字有效 • SO_REUSEADDR • BOOL型 • 设置为TRUE,套接字可以被绑定到一个已经使用的本地地址。 • 不能将两个监听套接字绑定到相同的本地地址

  9. IPPROTO_IP级别的选项 • IP_TTL • 设置和获取IP头中的TTL参数 • IP_ADD_MEMBERSHIP • 加入多播组 • IP_DROP_MEMBERSHIP • 离开多播组

  10. 程序实例 • BOOL bBroadcast = TRUE; setsockopt(s, SOL_SOCKET, SO_BROADCAST, (char*)&bBroadcast, sizeof(BOOL)); • level: SOL_SOCKET • optname: SO_BROADCAST • optval: TRUE,但需要进行类型转换 • optlen: 一个bool值所需要的缓冲区大小

  11. 广播地址 • 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

  12. 接收广播数据 • 接收程序只需要将套接字绑定到广播端口,即可接收同一子网内的该端口上的广播数据 • 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; }

  13. recv()与recvfrom() • recvfrom()还可以得到数据来源端的地址 • 示例程序中用recv()也可以完成功能

  14. 多播(Multicast)通信 • 广播的负面作用是显而易见的,多播是将封包发送到多个节点的更为可行的方法

  15. 多播地址 • 发送多播数据需要一个多播地址。每个多播地址代表一个多播组。 • 多播地址的范围 224.0.0.0 ~ 239.255.255.255

  16. 保留的多播地址

  17. 组管理协议(IGMP) • IPV4用于管理多播客户和他们之间关系的协议 • IGMP用于通知路由器对指定组的数据感兴趣 • 终端加入多播组时,将指定TTL值,指明终端的多播程序想要经过多少个路由器发送和接收数据

  18. 加入多播组 • 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)); • 通过设置套接字选项,加入多播组

  19. ip_mreq结构 Typedef struct { //多播地址 struct in_addr imr_multiaddr; //将要加入或离开多播组的本地地址 struct in_addr imr_interface; }

  20. 离开多播组 • 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)); • 通过设置套接字选项,离开多播组

  21. 接收多播数据 • 接收多播数据,必须加入特定的多播组,并将套接字绑定到特定的端口。 • char buf[1280]; int nAddrLen = sizeof(si); … … int nRet = ::recvfrom(s, buf, strlen(buf), 0, (sockaddr*)&si, &nAddrLen);

  22. 发送多播数据 • 向特定的组发送多播数据,并不必要加入这个组。 • 准备好多播数据,准备好多播地址,即可调用sendto()发送 • char sz[] = "This is just a test. \r\n"; while(TRUE) { ::sendto(s, sz, strlen(sz), 0, (sockaddr*)&bcast, sizeof(bcast)); ::Sleep(5000); }

  23. 带有源地址的IP多播 • 带源地址的IP多播允许加入组时指定要接收哪些成员的数据。 • 可以使用“包含”和“排除”两种方式加入组 • “包含”方式:指定多个有效的源地址,套接字仅接收来自这些源地址的数据 • “排除”方式:指定多个有效的源地址,套接字不接收来自这些源地址的数据

  24. “包含”方式 • 使用IP_ADD_SOURCE_MEMBERSHIP选项配置套接字,加入多播组,并指定数据的源地址 • 选项的值为一个ip_mreq_source结构 • 使用IP_DROP_SOURCE_MEMBERSHIP从集合中移除源地址

  25. ip_mreq_source结构 struct ip_mreq_source { //多播组地址 struct in_addr imr_multiaddr; //指定的源地址 struct in_addr imr_sourceaddr; //本地地址接口 struct in_addr imr_interface; }

  26. “排除”方式 • 使用IP_ADD_MEMBERSHIP选项加入组,此时使用的就是“排除”方式 • 使用IP_BLOCK_SOURCE选项来指定要派出的源地址

More Related