资讯详情

TCP/IP 网络编程:多播与广播

📅 2026/10/2 16:42:03 | 华诺云谱 👁 阅读
TCP/IP 网络编程:多播与广播
1. 引言在网络编程中我们通常习惯的是「一对一」的通信模式一台客户端连接一台服务器数据在两者之间传递。这种模式被称为单播Unicast。然而在很多实际场景下我们需要把同一份数据同时发送给多个接收者例如视频会议、直播推流局域网内的设备发现与自动配置股票行情、游戏房间状态同步传感器网络中批量下发指令。如果采用单播逐台发送不仅浪费带宽还会增加发送端的负担。为此TCP/IP 协议栈提供了两种高效的「一对多」通信方式广播Broadcast与多播Multicast。本文将围绕这两种方式展开先厘清它们与单播的区别再分别讲解 UDP 下广播与多播的编程模型最后给出可运行的代码示例与常见坑点。2. 单播、广播与多播2.1 单播Unicast单播是「一对一」通信。发送端把数据包发往一个明确的目的 IP 地址只有该地址对应的主机才会处理这个包。TCP 与 UDP 都支持单播这也是绝大多数网络应用的基础形态。2.2 广播Broadcast广播是「一对所有」通信。发送端把数据包发往广播地址位于同一广播域通常是同一子网内的所有主机都会收到该数据包。广播的特点仅限局域网内传播路由器默认不会转发广播包使用 UDP 实现TCP 不支持广播会对子网内所有主机造成处理开销因此不宜频繁使用。常见的广播地址是255.255.255.255受限广播或子网定向广播地址例如192.168.1.255。2.3 多播Multicast多播是「一对一组」通信。发送端把数据包发往一个多播组地址只有加入了该组的主机才会收到数据。多播的特点可以跨越路由器在广域网范围内传播使用 UDP 实现TCP 不支持多播相比广播多播只影响加入组的主机效率更高、更可控。IPv4 的多播地址范围是224.0.0.0~239.255.255.255D 类地址其中224.0.0.0~224.0.0.255为本地网络控制块通常不用于用户程序。2.4 三者对比特性单播广播多播通信对象一对一一对所有一对一组传输层协议TCP / UDP仅 UDP仅 UDP是否跨路由器是否是接收方开销仅目标主机子网内所有主机仅组成员典型场景Web、文件传输局域网设备发现直播、行情、组同步3. 广播编程UDP Broadcast广播基于 UDP 实现发送端与接收端的编程模型与普通 UDP 几乎一致区别主要在于目的地址与套接字选项。3.1 发送端要点发送广播数据前必须设置套接字的SO_BROADCAST选项否则发送广播包会返回错误。intsocksocket(AF_INET,SOCK_DGRAM,0);intbroadcast1;setsockopt(sock,SOL_SOCKET,SO_BROADCAST,broadcast,sizeof(broadcast));目的地址填写广播地址即可structsockaddr_inaddr;memset(addr,0,sizeof(addr));addr.sin_familyAF_INET;addr.sin_porthtons(9000);inet_pton(AF_INET,255.255.255.255,addr.sin_addr);3.2 接收端要点接收端使用普通 UDP 绑定流程即可无需额外选项intsocksocket(AF_INET,SOCK_DGRAM,0);structsockaddr_inaddr;memset(addr,0,sizeof(addr));addr.sin_familyAF_INET;addr.sin_addr.s_addrhtonl(INADDR_ANY);addr.sin_porthtons(9000);bind(sock,(structsockaddr*)addr,sizeof(addr));3.3 完整示例广播发送端#includestdio.h#includestring.h#includeunistd.h#includesys/socket.h#includenetinet/in.h#includearpa/inet.hintmain(){intsocksocket(AF_INET,SOCK_DGRAM,0);if(sock0){perror(socket);return1;}intbroadcast1;setsockopt(sock,SOL_SOCKET,SO_BROADCAST,broadcast,sizeof(broadcast));structsockaddr_inaddr;memset(addr,0,sizeof(addr));addr.sin_familyAF_INET;addr.sin_porthtons(9000);inet_pton(AF_INET,255.255.255.255,addr.sin_addr);constchar*msghello broadcast;sendto(sock,msg,strlen(msg),0,(structsockaddr*)addr,sizeof(addr));printf(broadcast sent: %s\n,msg);close(sock);return0;}3.4 完整示例广播接收端#includestdio.h#includestring.h#includeunistd.h#includesys/socket.h#includenetinet/in.hintmain(){intsocksocket(AF_INET,SOCK_DGRAM,0);if(sock0){perror(socket);return1;}structsockaddr_inaddr;memset(addr,0,sizeof(addr));addr.sin_familyAF_INET;addr.sin_addr.s_addrhtonl(INADDR_ANY);addr.sin_porthtons(9000);bind(sock,(structsockaddr*)addr,sizeof(addr));charbuf[1024];structsockaddr_inpeer;socklen_tlensizeof(peer);ssize_tnrecvfrom(sock,buf,sizeof(buf)-1,0,(structsockaddr*)peer,len);if(n0){buf[n]\0;printf(recv from %s: %s\n,inet_ntoa(peer.sin_addr),buf);}close(sock);return0;}4. 多播编程UDP Multicast多播的编程模型比广播稍复杂发送端需要设置多播 TTL接收端需要加入多播组。4.1 发送端要点发送端把目的地址设为多播组地址并可通过IP_MULTICAST_TTL设置数据包的生存时间TTL控制数据能跨越多少路由器intsocksocket(AF_INET,SOCK_DGRAM,0);unsignedcharttl1;setsockopt(sock,IPPROTO_IP,IP_MULTICAST_TTL,ttl,sizeof(ttl));structsockaddr_inaddr;memset(addr,0,sizeof(addr));addr.sin_familyAF_INET;addr.sin_porthtons(9001);inet_pton(AF_INET,239.0.0.1,addr.sin_addr);4.2 接收端要点接收端除了绑定端口还必须通过IP_ADD_MEMBERSHIP加入多播组否则收不到组内数据structip_mreqmreq;memset(mreq,0,sizeof(mreq));inet_pton(AF_INET,239.0.0.1,mreq.imr_multiaddr);mreq.imr_interface.s_addrhtonl(INADDR_ANY);setsockopt(sock,IPPROTO_IP,IP_ADD_MEMBERSHIP,mreq,sizeof(mreq));4.3 完整示例多播发送端#includestdio.h#includestring.h#includeunistd.h#includesys/socket.h#includenetinet/in.h#includearpa/inet.hintmain(){intsocksocket(AF_INET,SOCK_DGRAM,0);if(sock0){perror(socket);return1;}unsignedcharttl1;setsockopt(sock,IPPROTO_IP,IP_MULTICAST_TTL,ttl,sizeof(ttl));structsockaddr_inaddr;memset(addr,0,sizeof(addr));addr.sin_familyAF_INET;addr.sin_porthtons(9001);inet_pton(AF_INET,239.0.0.1,addr.sin_addr);constchar*msghello multicast;sendto(sock,msg,strlen(msg),0,(structsockaddr*)addr,sizeof(addr));printf(multicast sent: %s\n,msg);close(sock);return0;}4.4 完整示例多播接收端#includestdio.h#includestring.h#includeunistd.h#includesys/socket.h#includenetinet/in.h#includearpa/inet.hintmain(){intsocksocket(AF_INET,SOCK_DGRAM,0);if(sock0){perror(socket);return1;}structsockaddr_inaddr;memset(addr,0,sizeof(addr));addr.sin_familyAF_INET;addr.sin_addr.s_addrhtonl(INADDR_ANY);addr.sin_porthtons(9001);bind(sock,(structsockaddr*)addr,sizeof(addr));structip_mreqmreq;memset(mreq,0,sizeof(mreq));inet_pton(AF_INET,239.0.0.1,mreq.imr_multiaddr);mreq.imr_interface.s_addrhtonl(INADDR_ANY);setsockopt(sock,IPPROTO_IP,IP_ADD_MEMBERSHIP,mreq,sizeof(mreq));charbuf[1024];structsockaddr_inpeer;socklen_tlensizeof(peer);ssize_tnrecvfrom(sock,buf,sizeof(buf)-1,0,(structsockaddr*)peer,len);if(n0){buf[n]\0;printf(recv from %s: %s\n,inet_ntoa(peer.sin_addr),buf);}close(sock);return0;}5. 常见问题与注意事项5.1 广播收不到数据确认发送端已设置SO_BROADCAST确认发送端与接收端位于同一子网检查防火墙是否拦截了对应端口的 UDP 包。5.2 多播收不到数据确认接收端已调用IP_ADD_MEMBERSHIP加入组确认发送端与接收端使用相同的多播组地址与端口跨路由器时确认发送端 TTL 足够大且沿途路由器启用了多播路由协议如 PIM。5.3 广播与多播都不支持 TCPTCP 是面向连接的可靠传输无法表达「一对多」的语义。广播与多播只能基于 UDP 实现因此也继承了 UDP 不保证可靠、不保证有序的特点。若业务需要可靠性应在应用层自行实现确认与重传。5.4 多播地址的选择用户程序应避免使用224.0.0.0~224.0.0.255这段本地网络控制块地址推荐使用239.0.0.0~239.255.255.255范围内的地址该段为本地管理多播地址适合内部网络使用。6. 总结广播与多播是 TCP/IP 网络编程中实现「一对多」通信的两种重要手段广播实现简单但只限于局域网且会打扰子网内所有主机多播更高效、可控能够跨路由器传播但需要接收端主动加入多播组。在实际开发中应根据业务范围与网络环境选择合适的方案局域网内的设备发现可以优先考虑广播而需要跨网段、面向特定群体的数据分发则应使用多播。
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。

↑