单播、广播、组播和任播

文章目录

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


一、单播

  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.rhkb.cn/news/38972.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

1-1 MATLAB深度极限学习机

本博客来源于CSDN机器鱼&#xff0c;未同意任何人转载。 更多内容&#xff0c;欢迎点击本专栏目录&#xff0c;查看更多内容。 参考[1]魏洁.深度极限学习机的研究与应用[D].太原理工大学[2023-10-14].DOI:CNKI:CDMD:2.1016.714596. 目录 0.引言 1.ELM-AE实现 2.DE…

头歌 数据采集概述答案

问题1&#xff1a;以下哪个不是Scrapy体系架构的组成部分&#xff1f; 正确答案&#xff1a;B. 支持者(Support) 解释&#xff1a;Scrapy的主要组成部分包括&#xff1a; 爬虫(Spiders)&#xff1a;定义如何爬取网站和提取数据 引擎(Engine)&#xff1a;负责控制数据流在系统中…

【uniapp】记录tabBar不显示踩坑记录

由于很久没有使用uniapp了&#xff0c;官方文档看着又杂乱&#xff0c;底部tab导航栏一直没显示&#xff0c;苦思许久&#xff0c;没有发现原因&#xff0c;最后网上搜到帖子&#xff0c;list里的第一个数据&#xff0c;pages 的第一个 path 必须与 tabBar 的第一个 pagePath 相…

JVM 知识点梳理

JDK 、JRE、JVM JDK&#xff08; Java Development Kit &#xff09; Java开发工具包 JRE 开发命令工具&#xff08;运行java.exe、编译javac.exe、javaw.exe&#xff09; JRE&#xff08; Java Runtime Environment &#xff09;Java运行环境 JVM Java核心类库&#xff08;l…

蓝桥杯 之 第27场月赛总结

文章目录 习题1.抓猪拿国一2.蓝桥字符3.蓝桥大使4.拳头对决5.未来竞赛6.备份比赛数据 习题 比赛地址 1.抓猪拿国一 十分简单的签到题 print(sum(list(range(17))))2.蓝桥字符 常见的字符匹配的问题&#xff0c;是一个二维dp的问题&#xff0c;转化为对应的动态规划求解 力扣…

Ambari、Bigtop源码编译最新支持情况汇总

以下是目前的版本情况 支持了绝大部分的组件编译及安装 版本组件名称组件版本env 版本v1.0.5Ozone1.4.11.0.5Impala4.4.11.0.5Nightingale7.7.21.0.5Categraf0.4.11.0.5VictoriaMetrics1.109.11.0.5Cloudbeaver24.3.31.0.5Celeborn0.5.31.0.5v1.0.4Doris2.1.71.0.4v1.0.3Phoen…

仅靠prompt,Agent难以自救

Alexander的观点很明确&#xff1a;未来 AI 智能体的发展方向还得是模型本身&#xff0c;而不是工作流&#xff08;Work Flow&#xff09;。还拿目前很火的 Manus 作为案例&#xff1a;他认为像 Manus 这样基于「预先编排好的提示词与工具路径」构成的工作流智能体&#xff0c;…

【Docker系列一】Docker 简介

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

Sqoop 常用命令

Sqoop 是用于在 Hadoop 和关系型数据库&#xff08;如 MySQL、Oracle 等&#xff09;之间高效传输数据的工具。以下是常用的 Sqoop 命令及示例&#xff1a; CREATE TABLE employees (id INT AUTO_INCREMENT PRIMARY KEY, -- 自增主键&#xff0c;用于唯一标识每一行name VAR…

连续型随机变量及其分布

连续型随机变量 数学公式可以看作一门精确描述事物的语言&#xff0c;比语言尤其是汉语的模糊性精确多了&#xff01;离散型数据的处理可以通过枚举和相加进行处理。而连续型数据则没有办法这样处理。我们必须要通过函数和取值区间还有微积分计算。 &#xff3b;定义1&#x…

PostgreSQL_数据使用与日数据分享

目录 前置&#xff1a; 1 使用 1.1 获取前复权因子 1.2 查询股票的纵向数据 1.3 查询股票的横向数据 2 日数据分享&#xff08;截止至&#xff1a;2025-03-21&#xff09; 总结 前置&#xff1a; 本博文是一个系列。在本人“数据库专栏”-》“PostgreSQL_”开头的博文。…

Rocky9.5基于sealos快速部署k8s集群

首先需要下载 Sealos 命令行工具&#xff0c;sealos 是一个简单的 Golang 二进制文件&#xff0c;可以安装在大多数 Linux 操作系统中。 以下是一些基本的安装要求&#xff1a; 每个集群节点应该有不同的主机名。主机名不要带下划线。 所有节点的时间需要同步。 需要在 K8s …

qt实现一个简单http服务器和客户端

一、功能简介 服务器&#xff1a; 登录功能、下载文件功能 客户端&#xff1a; 登录功能、下载文件功能、上传成绩功能 二、服务器代码 //HttpServer.h #ifndef HTTPSERVER_H #define HTTPSERVER_H#include <QMainWindow> #include <QTcpSocket> #include <QTc…

基于Python+Django的旅游管理系统

项目介绍 PythonDjango旅游管理系统 平台采用B/S结构&#xff0c;后端采用主流的Python语言进行开发&#xff0c;前端采用主流的Vue.js进行开发。 整个平台包括前台和后台两个部分。 - 前台功能包括&#xff1a;首页、景点管理、门票管理、旅游资讯、在线反馈、。 - 后台功能包…

用数组模拟循环队列

设计一种循环队列&#xff0c;线性数据结构&#xff0c;其操作表现为 FIFO(先进先出)原则且队尾被连接在队首之后形成一个循环&#xff0c;称作“环形缓冲器” 循环队列的好处是可以利用这个队列之前使用过的空间&#xff0c;但是他的空间大小是固定的 循环队列我们使用单链表…

maven为什么发生依赖冲突?怎么解决依赖冲突?

maven为什么发生依赖冲突&#xff1f;怎么解决依赖冲突&#xff1f; 我们在开发的时候&#xff0c;偶尔会遇到依赖冲突的时候&#xff0c;一般都是NoClassDefFoundError、ClassNotFoundException、NoSuchMethodError。打开搜索框又发现有这个类&#xff0c;明明就是引入进来了&…

从国家能源到浙江交通投资,全息技术在能源交通领域的创新应用

一、3D全息技术行业应用参数及设计制作要求 全息投影 全息投影技术通过激光器、全息片等设备&#xff0c;将物体的三维信息记录下来&#xff0c;并在特定条件下再现。应用参数包括投影距离、投影面积、投影亮度等。设计制作要求&#xff1a;高清晰度、高亮度、低噪音、稳定性好…

Adobe After Effects 操作

Adobe After Effects &#xff08;AE&#xff09;可以实现将多个元素进行合成&#xff0c;实现特殊效果。AE的项目文件是aep&#xff0c;可以将素材、层、效果等一切信息&#xff0c;保存在这个项目文件中。 AE的原理&#xff0c;和PS的原理非常类似。 操作界面 操作界面如…

Flutter使用自签证书打包ipa

在 Flutter 中使用自签证书打包 IPA 文件&#xff0c;可以通过以下步骤完成&#xff1a; 1. 准备自签证书 方式一 生成自签证书&#xff1a; 打开 钥匙串访问 应用。选择 证书助理 > 创建证书。按照提示填写证书信息&#xff0c;选择证书类型为 代码签名&#xff0c;并保存…

三.Go的第一个程序hello.go

新建hello.go,代码如下 package mainimport "fmt"func main() {fmt.Println("hello world") }编译hello.go 控制台终端为hello.go同级目录 执行 go build hello.go编译成功同级目录下生成 同名exe文件 也可以直接执行 go run hello.go解释如下 一 .…