当前位置: 首页 > news >正文

单播、广播、组播和任播

文章目录

  • 一、单播
  • 二、广播
  • 三、组播
  • 四、任播
    • 代码示例:
  • 五、各种播的比较


一、单播

  1. 单播(Unicast)是一种网络通信方式,它指的是在网络中从一个源节点到一个单一目标节点对的传输模式。单播传输时,数据包从发送端直接发送到指定接收端,而不是广播给网络中的所有节点或组播给多个指定节点。单播是最常见的网络通信方式,主要应用于日常的互联网通信,如访问网页、发送电子邮件、文件下载等。
  2. 单播的特点
    在这里插入图片描述

在这里插入图片描述
举个例子

  • 当用户访问一个网页时,用户的设备会通过单播请求服务器的网页内容,服务器再单播传输响应给用户设备。
  • 发送电子邮件也是一个单播过程:邮件从发送者的邮件服务器传输到接收者的邮件服务器。

二、广播

  1. 什么是广播?
    广播(Broadcast)这种网络通信方式,用于将数据从一个节点传输到同一网络中的所有其他节点。广播数据包会被发送到一个特殊的广播地址,网络中的所有设备都会接收到这个数据包,不论设备是否需要该信息。这种通信方式一般用于局域网(LAN)中的信息共享。

广播这个东西,并不是所有的网络都支持,通常广播只是在局域网中,IPv6也不只是广播。在以太网中使用全1的地址,来表示广播地址。例如255.255.255.255 。在广播中,发送端并不指定特定的接收方,而是将数据包发送到该网络中的所有设备。由于广播会广泛传播,在网络中光标的数据通常是诸如网络探测和广告等,这种方式也常被黑客用来进行入侵和攻击。

在这里插入图片描述

  1. 广播的特点
    在这里插入图片描述

  2. 广播的类型
    在计算机网络中,广播有两种主要类型

  • 有限广播(Limited Broadcast):
    使用特殊的IP地址255.255.255.255
    仅在发送数据包的子网中传播,不能跨越路由器
    例如:DHCP请求使用有限广播,因为客户端不知道服务器的IP地址
  • 定向广播(Directed Broadcast)
    使用的是子网广播地址,例如在192.168.1.0/24子网中的定向广播地址是192.。168.1.255 。
    定向广播包只会被发送到特定的子网,因此可以跨越一些允许定向广播的路由器
    通常用于特定子网中发送广播信息,二人不是整个局域网
  • 假如有一个网络192.168.1.0/224,它的广播地址是192.168.1.255,那么向1192.168.1.255发送的数据包会被该子网中的所有设备接收
    如果有设备A向192.168.1.55发送广播包,那么192.168.1.0/24子网内的所有设备都会接收到该数据包
    使用ping255.255.255.255命令(有限广播),可以测试网络中是否有设备响应,常用于网络调试。
  1. 广播的应用场景
    在这里插入图片描述

  2. 广播在不同协议中的使用

  • IP v4协议:IPv4中支持广播,有专门的广播地址
  • IPv6协议:IPv6取消了广播功能,代之以组播(Multicast)和任播(Anycast)通信方式,组播比广播高效且对资源利用更优化。
  1. 代码示例
    下面是一个用C++实现UDP广播的示例代码,这个程序将创建一个UDP套接字,并向局域网内的广播地址发送消息。代码将消息广播到默认的局域网广播地址(如255.255.255.255或某个特定的子网广播地址,比如192.168.1.255)

注:运行广播代码时,请确保防火墙允许广播包的发送,否则可能会被拦截。另外,这段代码需要在支持BSD套接字的环境中允许,比如Linux或Windows。

//Linux版本
#include <iostream>
#include <cstring>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <unistd.h>
using namespace std;#define BROADCAST_PORT 8888   //发送广播的端口
#define BROADCAST_IP "255.255.255.255"    //广播地址int main() {//创建UDP套接字int sockfd = socket(AF_INET, SOCK_DGRAM, 0);if (sockfd < 0) {perror("socket");return -1;}//启用广播选项int BroadcastEnable = 1;//启用广播if(setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &BroadcastEnable, sizeof(BroadcastEnable))){close(sockfd);perror("setsockopt");return -1;}//配置广播地址struct sockaddr_in broadcastAddr;       //配置广播地址memset(&broadcastAddr, 0, sizeof(broadcastAddr));broadcastAddr.sin_family = AF_INET;broadcastAddr.sin_addr.s_addr = inet_addr(BROADCAST_IP);broadcastAddr.sin_port = htons(BROADCAST_PORT);//广播的消息const char* message="HEllo,this is a broadcast message!";//发送广播消息int sendResult=sendto(sockfd, message, strlen(message),0,(struct sockaddr*)&broadcastAddr,sizeof(broadcastAddr));if(sendResult<0){perror("send Faliure!");}else{cout<<"send success!"<<"and sent:"<<message<<endl;}//关闭套接字close(sockfd);return 0;
}
//Windows版本
#include <iostream>
#include <cstring>
#include <winsock2.h>  //Windows套接字库
#include <Ws2tcpip.h>  //Windows套接字IPv4地址库using namespace std;#pragma comment(lib, "Ws2_32.lib")  //自动连接ws2_32.lib库#define BROADCAST_PORT 8888   //发送广播的端口
#define BROADCAST_IP "255.255.255.255"    //广播地址int main() {//初始化Winsock库WSADATA wsaData;if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {cerr << "WSAStartup failed." <<WSAGetLastError()<< endl;return -1;}//创建UDP套接字SOCKET sockfd = socket(AF_INET, SOCK_DGRAM, 0);if (sockfd < 0) {perror("socket");return -1;}//启用广播选项int BroadcastEnable = 1;//启用广播if(setsockopt(sockfd,SOL_SOCKET,SO_BROADCAST,(char *)&BroadcastEnable,sizeof(BroadcastEnable))){cerr<<"setsockopt failed."<<WSAGetLastError()<<endl;closesocket(sockfd);WSACleanup();return -1;}//配置广播地址struct sockaddr_in broadcastAddr;       //配置广播地址memset(&broadcastAddr, 0, sizeof(broadcastAddr));broadcastAddr.sin_family = AF_INET;broadcastAddr.sin_addr.s_addr = inet_addr(BROADCAST_IP);broadcastAddr.sin_port = htons(BROADCAST_PORT);//广播的消息const char* message="HEllo,this is a broadcast message!";//发送广播消息int sendResult=sendto(sockfd, message, strlen(message),0,(struct sockaddr*)&broadcastAddr,sizeof(broadcastAddr));if(sendResult<0){perror("send Faliure!");}else{cout<<"send success!"<<"and sent:"<<message<<endl;}//关闭套接字closesocket(sockfd);return 0;
}

三、组播

  1. 什么是组播多播?
    组播和多播实际上是同一个概念,两者只是翻译上的差异。组播(或多播)也是一种网络通信方法,允许数据只发送一次,但可以由多台主机接收。其主要应用于需要多个接收方实时同步数据的场景,比如在线视频直播、网络游戏、股票行情等
    组播通常用于局域网,因为许多路由器和网络设备(特别是家用和小型网络设备)不支持跨互联阿的组播路由。此外,组播的管理和传输在局域网中更为高效和可控。。不过,大型企业或互联网服务提供商可能在其内部网络中使用组播、以实现高效的数据分发。

在这里插入图片描述

  1. 组播的原理
    在这里插入图片描述
    在这里插入图片描述
  • 具体来说,在一个局域网中的组播过程如下:
    1.假设在局域网内有5台主机:A、B、C、D、E
    2.通过分配一个组播地址和端口(比如239.255.0.1:8888)来定义组
    3.现在,如果主机A、B和C加入了这个组播组(即订阅了233.255.0.。1:8888的组播消息),那么D和E不会收到该组播消息,因为它们没有加入该组.
    4.当A发送一条组播消息到239.255.0.1:8888时,B和C会接收这条消息,而D和E不会收到,因为组播只会将数据发送给加入了该组播地址的主机
    5.组播的IP和端口是程序自己随意选择的(避开常用端口,要大于1024),只要在239.0.0.0到239.。255.。255.255这个范围内就可以。
  1. 代码实现(基于Windows版本)
    发送端

#include <iostream>
#include <winsock2.h>
#include <ws2tcpip.h>#pragma comment(lib, "Ws2_32.lib")using namespace std;int main()
{//初始化WinSockWSADATA wsaData;WSAStartup(MAKEWORD(2, 2), &wsaData);if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2){WSACleanup();return 1;}//创建UDP套接字SOCKET sendsock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);if(sendsock==INVALID_SOCKET){cerr<<"socket error"<<endl;WSACleanup();return -1;}//设置组播地址和端口sockaddr_in multicastAddr;multicastAddr.sin_family = AF_INET;multicastAddr.sin_addr.s_addr = inet_addr("239.255.0.1");multicastAddr.sin_port = htons(8888);//设置套接字为可广播,以确保数据可以通过广播发送到组播地址int ttl = 1;setsockopt(sendsock, IPPROTO_IP, IP_MULTICAST_TTL, (char*)&ttl, sizeof(ttl));//发送组播消息const char* message = "Hello, multicast!";int sendResult = sendto(sendsock, message, strlen(message), 0, (sockaddr*)&multicastAddr, sizeof(multicastAddr));if(sendResult==SOCKET_ERROR){cerr<<"sendto error"<<endl;closesocket(sendsock);WSACleanup();return -1;}cout<<"sendto success and message is:"<<message<<endl;//关闭套接字closesocket(sendsock);WSACleanup();}

接收端

#include <iostream>
#include <winsock2.h>
#include <ws2tcpip.h>#pragma comment(lib, "Ws2_32.lib")using namespace std;int main()
{//初始化WinSockWSADATA wsaData;WSAStartup(MAKEWORD(2, 2), &wsaData);if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2){WSACleanup();return 1;}//创建UDP套接字SOCKET recvsock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);if(recvsock==INVALID_SOCKET){cerr<<"socket error"<<endl;WSACleanup();return -1;}//绑定组播地址和端口sockaddr_in recvAddr;recvAddr.sin_family = AF_INET;recvAddr.sin_addr.s_addr = INADDR_ANY;recvAddr.sin_port = htons(8888);if(bind(recvsock,(sockaddr*)&recvAddr,sizeof(recvAddr))==SOCKET_ERROR){cerr<<"bind error"<<endl;closesocket(recvsock);WSACleanup();return -1;}//加入组播组ip_mreq multicastRequest;multicastRequest.imr_multiaddr.s_addr = inet_addr("239.255.0.1");//组播地址multicastRequest.imr_interface.s_addr = INADDR_ANY;   //本地任意接口if(setsockopt(recvsock,IPPROTO_IP,IP_ADD_MEMBERSHIP,(char *)&multicastRequest,sizeof(multicastRequest))){cerr<<"setsockopt error"<<endl;closesocket(recvsock);WSACleanup();return -1;}//接收组播消息char recvBuf[1024];sockaddr_in senderAddr;int senderAddrLen = sizeof(senderAddr);int recvlen= recvfrom(recvsock,recvBuf,sizeof(recvBuf),0,(sockaddr*)&senderAddr,&senderAddrLen);if(recvlen>0){recvBuf[recvlen] = '\0';cout<<"receive message:"<<recvBuf<<endl;}else{cerr<<"recvfrom error"<<endl;}//退出组播组setsockopt(recvsock,IPPROTO_IP,IP_DROP_MEMBERSHIP,(char *)&multicastRequest,sizeof(multicastRequest));//关闭套接字closesocket(recvsock);WSACleanup();return 0;;
}
  • 注意事项
    1.组播地址选择,在局域网中,239.0.0.0到239.255.255.255是专用组播地址,通常用于本地组播
    2.TTL设置:通过设置TTL(Time-To_Live)为1,可确保组播消息不会被路由器转发到其他网段
int ttl = 1;
setsockopt(sendsock, IPPROTO_IP, IP_MULTICAST_TTL, (char*)&ttl, sizeof(ttl));

IPPORTTO_IP:这个参数指定了将要设置对的选项所需的协议级别,IPPORTTO_IP表示这是IPv4协议级别的选项。对于IPv6,相应的常量是IPPORTTO_IPV6 。
IP_MULTICAST_TTL:这是要设置的选项名,IP_MULTICAST_TTL用于指定多播数据包的生存时间(TTL),TTL定义了数据包在网络中可以经过的最大路由器数(或跳数)。每当数据包经过一个路由器时,其TTL值减1.当TTL值减到0时,数据包被丢弃。

if(setsockopt(recvsock,IPPROTO_IP,IP_ADD_MEMBERSHIP,(char *)&multicastRequest,sizeof(multicastRequest))){cerr<<"setsockopt error"<<endl;closesocket(recvsock);WSACleanup();return -1;}
  • sock:套接字描述符
  • IPPORTTO_IP:指定选项所在的协议层。
  • IP_ADD_MEMBERSHIP:这是要设置选项的名称。它告诉系统,我们想要将一个套接字加入到一个多播组中
  • &multicast_request:指向一个ip_mreq结构的指针,该结构包含了多播组的地址以及本地接口的地址(或者是一个特殊的值来表示所有接口)。这个结构定义了套接字将要加入的多播组。
  • ip_mreq结构通常定义如下(在<netinet/in.h>或类似头文件中):
struct ip_mreq{struct in_addr imr_umltiaddr;//多播组的IP地址struct in_addrr imr_interface;//本地接口的IP地址,或INADDR_ANY表示所有接口
}
  • sizeof(multicast_request):指定了multicast_request结构的大小,以字节为单位。
  1. 代码实现(基于Linux)
//服务端
#include <iostream>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <string.h>
#include <unistd.h>
using namespace std;#define PORT 8080
#define MAX_SIZE 1024int main()
{//创建UDP套接字int sendsock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);if(sendsock<0){cerr<<"socket error"<<endl;return -1;}//设置组播地址和端口sockaddr_in multicastAddr;multicastAddr.sin_family = AF_INET;multicastAddr.sin_addr.s_addr = inet_addr("239.255.0.1");multicastAddr.sin_port = htons(8888);//设置套接字为可广播,以确保数据可以通过广播发送到组播地址int ttl = 1;setsockopt(sendsock, IPPROTO_IP, IP_MULTICAST_TTL, (char*)&ttl, sizeof(ttl));//发送组播消息const char* message = "Hello, multicast!";int sendResult = sendto(sendsock, message, strlen(message), 0, (sockaddr*)&multicastAddr, sizeof(multicastAddr));if(sendResult<0){cerr<<"sendto error"<<endl;close(sendsock);return -1;}cout<<"sendto success and message is:"<<message<<endl;//关闭套接字close(sendsock);return 0;
}
#include <iostream>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <string.h>
#include <unistd.h>
using namespace std;#define PORT 8080
#define MAX_SIZE 1024int main()
{//创建UDP套接字int recvsock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);if(recvsock<0){cerr<<"socket error"<<endl;return -1;}//绑定组播地址和端口sockaddr_in recvAddr;recvAddr.sin_family = AF_INET;recvAddr.sin_addr.s_addr = INADDR_ANY;recvAddr.sin_port = htons(8888);if(bind(recvsock,(sockaddr*)&recvAddr,sizeof(recvAddr))<0){cerr<<"bind error"<<endl;close(recvsock);return -1;}//加入组播组ip_mreq multicastRequest;multicastRequest.imr_multiaddr.s_addr = inet_addr("239.255.0.1");//组播地址multicastRequest.imr_interface.s_addr = INADDR_ANY;   //本地任意接口//接收组播消息char recvBuf[1024];sockaddr_in senderAddr;socklen_t senderAddrLen = sizeof(senderAddr);int recvlen= recvfrom(recvsock,recvBuf,MAX_SIZE,0,(sockaddr*)&senderAddr,&senderAddrLen);if(recvlen>0){recvBuf[recvlen] = '\0';cout<<"receive message:"<<recvBuf<<endl;}else{cerr<<"recvfrom error"<<endl;}//退出组播组setsockopt(recvsock,IPPROTO_IP,IP_DROP_MEMBERSHIP,(char *)&multicastRequest,sizeof(multicastRequest));//关闭套接字close(recvsock);
}

四、任播

  1. 什么是任播?
    任播(Anycast)是指多个服务器或节点共享一个IP地址,通过网络协议中的路由机制,用户的请求自动选择距离最近或最优的服务器进行响应。与传统的单播(Unicast)和组播(Multicast)不同,任播的核心在于“发送到最近的一个”

任播与组播的区别:在组播中,消息会被发送到一组所有订阅该IP地址的节点。但在任播中,消息只会到达同一IP地址下的一个最优节点。
任播可以使用任何可路由的IP地址,通常是常规的单播地址(A类、B类或C类IP地址),而不是D类地址。
任播实现的关键在于多个主机共享同一单播IP地址,通过路由协议(例如BGP或OSPF)来决定最近或最佳路径,而不是通过适用特殊的IP地址类被来实现。

  1. 任播的特点
    在这里插入图片描述

  2. 任播的原理

在这里插入图片描述

  1. 任播最优路由决策的过程
    任播的最优路由通常由BGP(边界网关协议)或OSPF(开放式最短路径优先协议)等网络路由协议来实现。以下是最优路由的决策过程
  • 地理距离和路径开销:在同一任播IP地址的情况下,路由器根据用户的地理位置选择最短路径或最低延迟的路径,以减少数据传输时间

  • 网络延迟:当路径开销类似时,路由器会优先选择网络延迟较低的路径。网络延迟可以通过探测或协议交换获得。

  • 路径稳定性:路由协议会优先选择路径稳定性较高的节点,路径的不稳定性可能会导致路由频繁更改,从而增加网络开销。

  • 路由协议的计算与更新:在BGP等动态路由协议中,节点定期交换路由信息,一旦有节点发生变化(如故障、延迟增加),路由表会根据新的路由哦条件进行更新

  • 负载平衡机制:如果多个节点的延迟相似,路由器会分配请求给不同节点,以实现负载平衡。这种策略也用于避免某个节点出现瓶颈。

举个例子:互联网中的任播-----Google DNS服务
假设你在中国访问Google的公共DNS服务器(如IP地址8.8.8.8).Google在全球多个地点(美国、欧洲、亚洲等)部署了多个共享这个IP地址的DNS服务器,这些服务器都配置为任播节点。

  1. 当你请求访问8.8.8.8时,路由器会根据你的地理位置和当前的网络状况,选择距离最近或响应最快的服务器节点来处理请求。例如,你的请求会被引导到位于亚洲的一个GoogleDNS服务器,而不是到美国或欧洲的服务器。
  2. 这样做的好处是降低了请求延迟,用户可以更快的速度获得DNS解析结果,同时,入股亚洲的服务器出现故障,请求会自动转向其他位置的服务器,确保服务的高可用性。
    也就是说:在互联网中的任播应用,通过全局BGP协议实现,将全球用户的请求引导至最近的服务器节点。
  • 再举个例子就是
  • 主句A在北京,而主机B在石家庄、C和D在上海、E在硅谷。所有节点BCDE都监听同一个任播地址239.255.255.250和端口8080.
  • 当A发送UDP消息到任播地址239.255.255.250:8080时,路由协议会选择一个最优路径,将消息转发给其中距离最近的一个节点,而不是多个节点。

在这里插入图片描述
在这里插入图片描述

代码示例:

  • 场景设定
    假设网络已经配置支持任播
    发送方主机A位于北京,向任播地址239.255.255.250发送消息,端口为8080
    接收方主机(B、C、D、E)都监听239.255.255.250:8080上。
    我们可以使用UDP套接字实现该功能,并且需要网络配置支持任播路径选择,比确保消息能正确到达距离最近的节点。
  1. 发送方代码(主机A)–sender.cpp
    发送方会向任播IP地址239.255.255.250的端口8080发送UDP消息。
#include <iostream>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <unistd.h>
#include <cstring>
using namespace std;#define ANYCAST_IP "239.255.255.250"   //任播IP地址
#define PORT 8080int main() {int sockdf;struct sockaddr_in servaddr;//创建UDP套接字sockdf = socket(AF_INET, SOCK_DGRAM, 0);if (sockdf < 0) {perror("socket create Failure!");return -1;}//设置目标地址memset(&servaddr, 0, sizeof(servaddr));servaddr.sin_family = AF_INET;servaddr.sin_port=htons(PORT);if(inet_pton(AF_INET, ANYCAST_IP, &servaddr.sin_addr)<=0)//任播地址{perror("inet_pton Failure!");clsoe(sockdf);return -1;}//准备消息内容const char* message="Hello from A(BeiJing)";int msg_len=strlen(message);//发送消息if(sendto(sockfd,message,msg_len,0,((struct sockaddr*)&servaddr),sizeof(servaddr))<0){perror("sendto Failure!");close(sockdf);return -1;}cout<<"Message send to"<<ANYCAST_IP<<":"<<PORT<<endl;//关闭套接字close(sockdf);return 0;
}
  1. 接收方代码(主机B/C/D/E)–receiver.cpp
    接收方监听在任播IP地址239.255.255.250和端口8080上,等待来自发送方的UDP消息
#include <iostream>
#include <cstring>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <unistd.h>
#include <netinet/in.h>
using namespace std;#define ANYCAST_IP "239.255.255.250"   //任播IP地址
#define PORT 8080int main()
{int sockfd;struct sockaddr_in servaddr,clientaddr;//创建UDP套接字sockfd = socket(AF_INET,SOCK_DGRAM,0);if(sockfd < 0){cout << "create socket error" << endl;return -1;}//设置地址复用选项,允许多个节点绑定到相同的端口int opt=1;if(setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt))){cout << "set socket option error" << endl;close(sockfd);return -1;}//设置服务器地址memeset(&servaddr,0,sizeof(servaddr));servaddr.sin_family = AF_INET;servaddr.sin_port = htons(PORT);servaddr.sin_addr.s_addr = inet_addr(ANYCAST_IP);//绑定套接字来任播地址if(bind(sockfd,(struct sockaddr *)&servaddr,sizeof(servaddr)) < 0){cout << "bind socket error" << endl;close(sockfd);return -1;}//接收数据char buf[1024];socklen_t len = sizeof(clientaddr);cout<<"Receiver listening on "<<ANYCAST_IP<<":"<<PORT<<endl;while(true){int n = recvfrom(sockfd,buf,sizeof(buf)-1,0,(struct sockaddr *)&clientaddr,&len);if(n<0){perror("recvfrom");break;}buf[n] = '\0';cout<<"Received message :"<<buf<<"from "<<inet_ntoa(clientaddr.sin_addr)<<":"<<ntohs(clientaddr.sin_port)<<endl;}//关闭套接字close(sockfd);return 0;
}
  1. 代码说明和重要的函数参数
  • 发送方:通过UDP套接字向任播地址239.255.255.250:8080发送消息

  • 接收方:通过UDP套接字绑定到相同的任播地址和端口号239.255.255.250:8080,监听并接收消息。

  • a. 在多个接收方节点(如B、C、D、E)上运行receiver.cpp,并确保网络配置支持任播

  • b. 在发送方节点A上运行sender.cpp发送消息

    • 难点代码
//设置地址复用选项,允许多个节点绑定到相同的端口int opt=1;if(setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt))){cout << "set socket option error" << endl;close(sockfd);return -1;}

(1)sockfd:这是套接字文件描述符,socket()函数返回的值。setsockopt将对这个套接字应用配置选项。
(2)SOL_SOCKET:这是套接字层的选项类型,用于指定选项在套接字级别(例如,SO_REUSEADDR、SO_KEEPALIVE等)。当你想要设置通用的套接字选项(而不是协议特定的选项)时,会将此参数设置为SOL_SOCKET。
(3)SO_REUSEADDR:这是具体的选项标志,表示地址重用。它允许一个本地端口可以被多个套接字绑定,特别是在以下场景中使用:
···
····服务器快速重启:如果服务器进程使用某个端口并意外终止,那么在短时间内重新启动该进程时,端口可能还被操作系统标记为“正在使用”,SO_REUSEADDR可以使端口立即可用。
···多播和任播:多个进程可用监听同一个端口,这对于多播和任播应用非常重要,因为多个服务器实例可能同时监听同一端口来接收数据。
···端口共享:允许多个套接字同时绑定到同一IP地址和端口,但其中只有一个会接收传入数据。
···&opt:这是指向opt变量的指针,表示SO_REUSEADDR的值。我们将其设置为1(即opt=1),表示启用端口重用。若将其设置为0,则表示禁用端口重用。
···sizeof(opt):指定opt的大小,用于告诉setsockopt函数opt变量的长度。

  1. 预期结果
    在正确配置任播的情况下,只有一个接收方节点(例如距离A最近的B节点)会接收到消息,并在控制台上打印发送方A的消息内容。这是因为任播路由的设计会自动将消息引导到最优路径的单一节点。

五、各种播的比较

特性单播(Unicast)广播(Broadcast)任播(Anycast)组播(Multicast)
地址类型A、B、C类IP地址D类地址(以255.255.255.255结尾)A、B、C类IP地址D类地址(224.0.0.0-239.255.255.255)
数据传输范围一个发送者到一个接收者一个发送者到同一网络内的所有接收者一个发送者到多个节点之一,选择最近的一个节点一个发送者到指定组内的多个接收者
数据传输效率效率低,需要多个单独的传输效率低,所有设备都接收,无论是否需要效率较高,只发送到最优接收者效率较高,只发送到订阅的接收者
应用场景点对点通信,例如CS模型局域网中的广播(如ARP请求)CDN、DNS等分布式服务,将流量引导到最近节点视频会议、IPTV、在线直播等
IP地址范围常规单播IP地址(如A类、B类、C类)子网广播(如192.168.1.255),或全网广播常规单播IP地址(如A类、B类、C类)D类地址范围(224.0.0.0-239.255.255.255)
路由实现常规路由、根据目标单个IP地址不路由,一般局限于局域网内通过路由协议选择最近或最优的路径依靠多播路由协议(如PIM)
典型协议TCP、UDPUDPBGP(用于选择最近节点)IGMP、PIM
适用范围适用于需要专用通信的场景局限于局域网广域网和局域网均适用,要求网络支持任播配置局域网和广域网均适用
优势通信明确、安全性高易于实现,无需复杂配置实现负载均衡、提高服务性能节省带宽、优化数据传输效率
缺点不适用于大规模接收者的通信消耗带宽、增加不必要的网络流量依赖路由协议支持,配置复杂需要额外的组播路由配置

http://www.mrgr.cn/news/95470.html

相关文章:

  • 【通过Groovy去热修复线上逻辑】1.执行线上数据修复 2.写工具
  • STM32__红外避障模块的使用
  • Cursor从小白到专家
  • Jupyter Notebook 常用命令(自用)
  • 动态规划入门详解
  • DeepSeek本地搭建
  • git | 回退版本 并保存当前修改到stash,在进行整合。[git checkout | git stash 等方法 ]
  • C语言【文件操作】详解中(会使用fgetc,fputc,fgets,fputs,fscanf,fprintf,fread,fwrite函数)
  • 【day1】数据结构刷题 链表
  • 通俗易懂搞懂@RequestParam 和 @RequestBody
  • 细说卫星导航:测距定位原理
  • 【算法笔记】图论基础(一):建图、存图、树和图的遍历、拓扑排序、最小生成树
  • TCP | 序列号和确认号 [逐包分析] | seq / ack 详解
  • 介绍一个测试boostrap表格插件的好网站!
  • 自动驾驶系统的车辆动力学建模:自行车模型与汽车模型的对比分析
  • [学习笔记] VM虚拟机安装Ubuntu系统
  • Axure大屏可视化模板:赋能多领域,开启数据展示新篇章
  • [AI速读]混合验证方案:如何高效解决RISC-V向量扩展的验证难题
  • 文献分享: XTR——优化Token级检索的高效多向量模型
  • 【数学建模】最大最小值模型详解