【Linux C | 网络编程】多播的概念、多播地址、UDP实现多播的C语言例子

news2025/1/15 8:00:04

😁博客主页😁:🚀https://blog.csdn.net/wkd_007🚀
🤑博客内容🤑:🍭嵌入式开发、Linux、C语言、C++、数据结构、音视频🍭
🤣本文内容🤣:🍭介绍多播的概念、多播地址、UDP实现广播的C语言例子 🍭
😎金句分享😎:🍭你不能选择最好的,但最好的会来选择你——泰戈尔🍭
⏰发布时间⏰:

本文未经允许,不得转发!!!

目录

  • 🎄一、多播概述
  • 🎄二、多播地址
    • ✨2.1、IPv4 多播地址
    • ✨2.2、IPv6 多播地址
    • ✨2.3、多播地址映射为MAC地址
  • 🎄三、多播的过程
  • 🎄四、源特定多播
    • ✨4.1 广域网的多播
    • ✨4.2 源特定多播(Source-Specific Multicast)
  • 🎄五、UDP实现多播的例子
    • ✨5.1 多播接收端代码
    • ✨5.2 多播发送端代码
  • 🎄六、总结


在这里插入图片描述

🎄一、多播概述

在网络编程中,有三种常见的通信方式:单播、广播、多播(组播),这三种方式对比如下表:

类型IPv4IPv6TCPUDP所标识接口数递送到的接口数
单播支持支持支持支持一个一个
广播支持支持全体全体
多播可选支持支持一组整个组

多播的概念
IP 多播(也称多址广播组播)技术,是允许一台主机多台主机 发送消息的一种通信方式。单播只向单个IP接口发送数据,广播是向子网内所有IP接口发送数据,多播则介于两者之间,向一组IP接口发送数据。
多播支持IPv4,也支持IPv6。在IPv6中没有广播,认为广播只是特殊(把整个子网视为多播组)的多播。
多播支持UDP,不支持TCP。
多播既可用于局域网,也可用于广域网,而广播一般在局域网使用。

多播的优点
比起广播,多播数据报只会发送到加入多播组的主机,不会像广播那样发给所有主机。


在这里插入图片描述

🎄二、多播地址

多播地址用来标识多播组,IPv4使用D类地址的某一个来表示一个多播组地址,IPv6多播地址的高序字节值为ff

✨2.1、IPv4 多播地址

IPv4的D类地址(从224.0.0.0到239.255.255.255)是IPv4多播地址,见下图:
在这里插入图片描述
D类地址的低序28位构成多播组ID(group ID),整个32位地址则称为组地址(group address)。

IPv4的多播地址可分为三类:

  • 链路局部多播地址:224.0.0.0224.0.0.255,这是为路由协议和其它用途保留的地址,路由器并不转发属于此范围的IP包;
  • 预留多播地址:224.0.1.0238.255.255.255,可用于全球范围(如Internet)或网络协议。
  • 管理权限多播地址:239.0.0.0239.255.255.255,可供组织内部使用,类似于私有 IP 地址,不能用于 Internet,可限制多播范围。
下面是若干个IPv4特殊多播地址,这些地址是由IANA确定的,作为永久主机组:
224.0.0.1    所有组播主机
224.0.0.2    所有组播路由器
224.0.0.4    DRMRP 路由器
224.0.0.5    所有 OSPF 的路由器
224.0.0.6    OSPF 指派路由器
224.0.0.9    RPIv2 路由器
224.0.0.10   EIGRP 路由器
224.0.0.13   PIM 路由器
224.0.0.22   IGMPv3
224.0.0.25   RGMP
224.0.1.1    NTP 网络时间协议

✨2.2、IPv6 多播地址

IPv6多播地址的结构如下图,分成4个部分:

  • 高位8比特:全部为1,这是固定的,表示这是一个多播地址;
  • 标志4比特:分以下几种取值
    0000:众所周知的多播组;
    0001:临时的多播组;
    0010:表示多播地址是基于某个单播前缀赋予的;
    0011:表示基于单播的多播地址总是临时的。
  • 范围4比特:可能有以下取值
    0:保留。
    1:接口本地范围(Interface-Local scope )。
    2:链路本地范围(Link-Local scope )。
    3:基于单播前缀的地址(Unicast-Prefix-based address )。
    4:管理本地范围(Admin-Local scope )。
    5:站点本地范围(Site-Local scope)。
    6:未分配。
    7:汇聚点标记(Rendezvous Point flag )。
    8:组织本地范围(Organization-Local scope )。
    9-D:未分配。
    E:全局范围(Global scope。
    F:保留。
  • 组ID112比特:低序32位复制到以太网地址的低序32位

在这里插入图片描述

下面是若干特殊的IPv6多播地址。

  • ff01::1ff02::1是所有节点(all-nodes)组。子网上所有具有多播能力的节点(主机、路由器和打印机等)必须在所有具有多播能力的接口上加入该组,类似于IPv4的224.0.0.1多播地址。但多播是IPv6的一个组成部分,这与IPv4是不同的。
    尽管对应的IPv4组称为所有主机组,而IPv6组称为所有节点组,它们的含义是一致的。IPv6重新命名意在更为清晰地指出本组包括了子网上的主机、路由器、打印机,以及任何IP设备。
  • ff01::2ff02::2ff05::2是所有路由器(all-routers)组。子网上所有多播路由器必须在所有具有多播能力的接口上加入该组,类似于IPv4的224.0.0.2多播地址。

✨2.3、多播地址映射为MAC地址

将多播地址映射到以太网多播地址的过程是重要的,因为以太网是数据链路层的协议,而IPv4、IPv6的多播地址是网络层的协议。这种映射使得多播数据能够在以太网上正确传输到目标设备,确保只有加入了相应多播组的设备才会接收到相应的多播数据包。

以太网地址,通常称为MAC地址(Media Access Control address),是网络设备在数据链路层使用的唯一标识符。MAC地址由48位二进制数组成,通常以十六进制表示,每6位之间用冒号或连字符分隔,如 00:1A:2B:3C:4D:5E。通常,MAC地址是网络设备(如网卡)出厂设置好的,一般不会改变。

当一个IPv4多播数据包需要发送到多个接收者时,IPv4多播地址会被映射成对应的以太网多播地址。这种映射不会改变设备的硬件MAC地址,而是针对特定的多播传输而生成的临时多播MAC地址。多播MAC地址是一个虚拟的地址,源主机将数据发送到多播组对应的以太网多播地址,而不会影响到设备的真实MAC地址。设备仍然使用其固定的硬件MAC地址来标识自己,只是在多播通信过程中会使用临时的多播MAC地址来传输数据。

在这里插入图片描述

IPv4多播地址是通过特定规则映射到以太网多播地址的,映射规则如下:

  • 前24位以固定的前缀01:00:5E开头,第25位总是0。
  • 后23位直接由IPv4多播地址的低23位组成。IPv4多播地址高序4位固定为e,映射过程中,中间的5位被忽略,因此这个映射关系不是一对一的。

IPv6多播地址到以太网地址的映射是通过多播组里的成员关系进行的。下面是IPv6多播地址到以太网地址的映射过程:

  • 首先确定IPv6多播地址的范围,IPv6多播地址通常在ff00::/8的范围内。
  • 多播组的最低24位用于构建对应的以太网地址。这个过程使用了特殊的前缀:33:33。
  • 取IPv6多播地址的最低32位,将其转换为16进制,并插入到33:33之后,形成完整的以太网地址。
  • 以太网地址的第一个字节设置为01-00-5E。这个步骤可以保证以太网地址不会与单播地址冲突。

总的来说,IPv6多播地址到以太网地址的映射是通过将IPv6多播地址的一部分直接复制到以太网地址中,并添加特定的前缀来确保唯一性。


在这里插入图片描述

🎄三、多播的过程

下图是可以展示多播的过程:
在这里插入图片描述
多播的过程:

  • 首先,接收主机(图中右侧)需要在接收进程创建一个UDP套接字,绑定端口123,然后加入多播组224.0.1.1。该主机的IPv4层会保存这些信息,并告知合适的数据链路接收目的以太网地址为01:00:5e:00:01:01的以太网帧。
  • 然后,发送主机(图中左侧)的发送应用进程创建一个UDP套接字,往IP地址224.0.1.1的123端口发送一个数据报,并最后转换成以太网帧发到网络。发送多播数据报无需任何特殊处理,发送应用进程不必为此加入多播组。
  • 接着,不具备多播能力的主机(图中中间主机)会完全忽略该帧。因为:
    1、该帧的目的以太网地址不匹配该主机的接口地址;
    2、该帧的目的以太网地址不是以太网广播地址;
    3、该主机的接口未被告知接收任何组地址(高序字节的低序位被置为1的以太网地址,如图21-1所示)。
  • 最后,接收主机(图中右侧)的数据链路收取该帧后将承载的分组传递到IP层。IP层比较该地址和本机的接收应用进程已经加入的所有多播地址,根据比较结果确定是接受还是丢弃该分组。确定接受之后,再把承载的UDP数据报传递到UDP层。UDP层再把承载在数据报中的数据传递到绑定了端口123的套接字。

图中没有展示的还有以下三种情形:

  • (1)运行所加入多播地址为225.0.1.1的某个应用进程的一个主机。既然多播地址组ID的高5位在到以太网地址的映射中被忽略,该主机的接口也将接收目的以太网地址为01:00:5e:00:01:01的帧。这种情况下,由该帧承载的分组将由IP层中的完备过滤丢弃。
  • (2)运行所加入多播地址符合以下条件的某个应用进程的一个主机:由这个多播地址映射成的以太网地址恰好和01:00:5e:00:01:01一样被该主机执行非完备过滤的接口散列到同一个结果。该接口也将接收目的以太网地址为01:00:5e:00:01:01的帧,直到由数据链路层或IP层丢弃。
  • (3)目的地为相同多播组(224.0.1.1)不同端口(譬如4000)的一个数据报。图21-4中右侧主机仍然接收该数据报,并由P层接受并传递给UDP层,不过UDP层将丢弃它(假设绑定端口4000的套接字不存在)。

在这里插入图片描述

🎄四、源特定多播

✨4.1 广域网的多播

多播是不仅支持局域网,也支持广域网。

当某个主机上的一个进程加入一个多播组时,该主机向所有直接连接的多播路由器发送一个IGMP消息,告知它们本主机已加入了那个多播组。多播路由器随后使用多播路由协议(MRP)交换这些信息,这样每个多播路由器就知道在收到目的地为所加入多播地址的分组时该如何处理。


✨4.2 源特定多播(Source-Specific Multicast)

源特定多播的英文是Source-Specific Multicast,简称SSM,是基于源地址和目的地址的组合来定义多播组,接收者只能从单个源(或称为发送者)接收数据,而不是从任意源接收,这使得网络更加安全可靠。

  • 接收进程向多播路由器提供发送进程的源地址作为多播组加入操作的一部分。这种方式可以减少网络中的不必要流量,提高网络效率。
  • 把多播组的标识从单纯多播组地址细化为单播源地址和多播目的地址之组合(SSM称之为通道)。

在这里插入图片描述

🎄五、UDP实现多播的例子

下面给出一个使用UDP实现多播的例子,代码是之前文章的例子修改的,文章链接: 入门知识:UDP协议、一个最简单的UDP客户端、一个最简单的UDP服务端 。

✨5.1 多播接收端代码

接收端是使用UDP服务端代码修改,需要在交互数据之前,将套接字加入多播组239.0.1.1,让链路层接口接收该多播组的数据报,使用完需要离开多播组。

UDP多播接收端步骤:

  • 1、创建UDP套接字socket;
  • 2、准备本地ip接口和多播组端口;
  • 3、绑定多播组端口 bind;
  • 4、加入多播组 239.0.1.1;
  • 5、使用 sendto、recvfrom 交互数据;
  • 6、离开多播组
  • 7、关闭套接字
// multicastSer.c
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <unistd.h>

int main()
{
	// 1、创建UDP套接字socket
	int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
	if(sockfd<0)
		perror("socket error" );
	
	// 2、准备本地ip接口和多播组端口
	struct sockaddr_in servaddr;
	bzero(&servaddr, sizeof(servaddr));
	servaddr.sin_family = AF_INET;
	servaddr.sin_port = htons (10086);
	servaddr.sin_addr.s_addr = INADDR_ANY; // 指定ip地址为 INADDR_ANY,这样要是服务器主机有多个网络接口,服务器进程就可以在任一网络接口上接受客户端的连接
	
	// 3、绑定多播组端口 bind
	if (bind(sockfd,(struct sockaddr*)&servaddr, sizeof(servaddr)) < 0)
		perror("bind error" );
	
	// 4、加入多播组 239.0.1.1
	struct ip_mreq mreq;
	mreq.imr_multiaddr.s_addr = inet_addr("239.0.1.1");	// 多播组的IP地址
    mreq.imr_interface.s_addr = htonl(INADDR_ANY);		// 加入的客服端主机IP地址
    if (setsockopt(sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) == -1)    {
        perror("setsockopt");
        return -1;
    }
	
	// 5、使用 sendto、recvfrom 交互数据
	printf("UdpSer sockfd=%d, start \n",sockfd);
	char recvline[256];
	while(1)
	{
		struct sockaddr_in cliaddr;
		bzero(&cliaddr, sizeof(cliaddr));
		socklen_t addrLen=sizeof(cliaddr);
		int n = recvfrom(sockfd, recvline, sizeof(recvline), 0, (struct sockaddr*)&cliaddr, &addrLen);
		if(n>0)
		{
			recvline[n] = 0 ;/*null terminate */
			printf("recv sockfd=%d %d byte, [%s] addrLen=%d, cliIp=%s, cliPort=%d\n",
				sockfd, n, recvline, addrLen, inet_ntoa(cliaddr.sin_addr),cliaddr.sin_port);
			sendto(sockfd, "Hello,I am udp server", strlen("Hello,I am udp server"), 0, (struct sockaddr*)&cliaddr, addrLen);
		}
	}
	
	// 6、离开多播组
	setsockopt(sockfd, IPPROTO_IP, IP_DROP_MEMBERSHIP,&mreq, sizeof(mreq)); 
	
	// 7、关闭
	close(sockfd);

	return 0;
}

✨5.2 多播发送端代码

发送端是使用UDP客户端代码修改,整个流程都不需改动,只需要把要发送的目的地址改为多播组地址239.0.1.1。修改后代码如下:

// multicastCli.c
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <unistd.h>

int main()
{
	// 1、创建UDP套接字socket
	int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
	if(sockfd<0)
		perror("socket error" );
	
	// 2、准备多播组地址和端口
	struct sockaddr_in servaddr;
	bzero(&servaddr, sizeof(servaddr));
	servaddr.sin_family = AF_INET;
	servaddr.sin_port = htons (10086);
	if (inet_pton(AF_INET, "239.0.1.1", &servaddr.sin_addr) <= 0)
		perror("inet_pton error");
		
	// 4、使用 sendto 发送多播组数据报
	if(sendto(sockfd, "Hello,I am udp client", strlen("Hello,I am udp client"), 0, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0)
		perror("sendto error" );
	
	// 5、处理应答
	char recvline[256];
	int n = 0;
	struct sockaddr_in tmpAddr;
	bzero(&tmpAddr, sizeof(tmpAddr));
	socklen_t addrLen=sizeof(tmpAddr);
	while ( (n = recvfrom (sockfd, recvline, sizeof(recvline), 0, (struct sockaddr*)&tmpAddr, &addrLen)) > 0)
	{
		recvline[n] = 0 ;/*null terminate */
		printf("recvfrom ip=[%s], [%s]\n",inet_ntoa(tmpAddr.sin_addr), recvline);
		bzero(&tmpAddr, sizeof(tmpAddr));
	}
	
	if (n < 0)
		perror("read error" );
	
	// 6、关闭
	close(sockfd);

	return 0;
}

在这里插入图片描述

🎄六、总结

👉本文介绍多播的概念,多播地址,多播数据报发送过程,最后给出C语言实现多播的例子。

在这里插入图片描述
如果文章有帮助的话,点赞👍、收藏⭐,支持一波,谢谢 😁😁😁

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1497124.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

提高生产效率!虹科MSR165快速检测机器故障,实现精准优化

如今&#xff0c;各种生产机器、机床和运输机都采用了复杂的驱动技术&#xff0c;以便在三个轴上准确生成线性运动或者高效旋转运动。所有机械运动中都会出现特征性的振动或震动模式&#xff0c;可以在该背景下利用这些模式来监测和优化整个驱动技术的机电参数。在这个过程中&a…

太阳能光伏电池的simulink建模与仿真

目录 1.课题概述 2.系统仿真结果 3.核心程序与模型 4.系统原理简介 4.1 光伏电池的基本结构 4.2 光伏电池的工作原理 5.完整工程文件 1.课题概述 太阳能光伏电池的simulink建模与仿真.分析不同光照温度&#xff0c;光照强度下的光伏电池的U-I特性曲线以及P-V特性曲线。 …

备战蓝桥(模板篇)

扩展欧德里几算法 质数筛 分解质因数 LCA BFS floyd Dijkstra prime 日期是否合法 Tire异或 模拟散列表 字符哈希 Tire字符串统计

官方教程 | 在 OpenBayes 平台进行组织协作

想和好 homie 共享账户余额、存储、数据集、模型、容器等资源&#xff0c;又不想共享自己的账户密码&#xff1f; 想跟团队成员分工协作、高效 Coding、加速炼丹&#xff0c;又想隔离权限、差异化管理&#xff1f; 经过为期半年的内测和完善&#xff0c;OpenBayes贝式计算的组织…

平面纯弯梁单元Matlab有限元编程 |欧拉梁单元| 简支梁|悬臂梁|弯矩图 |变形图| Matlab源码 | 视频教程

专栏导读 作者简介&#xff1a;工学博士&#xff0c;高级工程师&#xff0c;专注于工业软件算法研究本文已收录于专栏&#xff1a;《有限元编程从入门到精通》本专栏旨在提供 1.以案例的形式讲解各类有限元问题的程序实现&#xff0c;并提供所有案例完整源码&#xff1b;2.单元…

Ajax、Axios、Vue、Element与其案例

目录 一.Ajax 二.Axios 三.Vue 四.Element 五.增删改查案例 一.依赖&#xff1a;数据库&#xff0c;mybatis&#xff0c;servlet&#xff0c;json-对象转换器 二.资源&#xff1a;elementvueaxios 三.pojo 四.mapper.xml与mapper接口 五.service 六.servlet 七.html页…

目前研一,是选 FPGA 还是 Linux 嵌入式?

目前研一&#xff0c;是选 FPGA 还是 Linux 嵌入式? 在开始前我有一些资料&#xff0c;是我根据网友给的问题精心整理了一份「Linux 的资料从专业入门到高级教程」&#xff0c; 点个关注在评论区回复“888”之后私信回复“888”&#xff0c;全部无偿共享给大家&#xff01;&a…

Sora:AI视频生成的新机遇与挑战

随着科技的飞速进步&#xff0c;人工智能&#xff08;AI&#xff09;和机器学习&#xff08;ML&#xff09;技术已经深入渗透到社会的各个领域。其中&#xff0c;Sora这类基于AI的视频生成工具因其高度逼真的生成能力而备受瞩目。然而&#xff0c;正如一枚硬币有两面&#xff0…

力扣刷题Days11第二题--141. 环形链表(js)

目录 1,题目 2&#xff0c;代码 2.1快慢指针 2.2&#xff0c;哈希表 3&#xff0c;学习与总结 3.1自己尝试写快慢指针 反思 1,题目 给你一个链表的头节点 head &#xff0c;判断链表中是否有环。 如果链表中有某个节点&#xff0c;可以通过连续跟踪 next 指针再次到达&…

蓝牙APP开发实现汽车遥控钥匙解锁汽车智能时代

在现代社会&#xff0c;随着科技的不断发展&#xff0c;汽车已经不再是简单的交通工具&#xff0c;而是与智能科技紧密相连的载体。其中&#xff0c;通过开发APP蓝牙程序实现汽车遥控钥匙成为了一种趋势&#xff0c;为车主带来了便捷与安全的体验。虎克技术公司作为行业领先者&…

HTML开发工具和环境介绍,内附超详细的VS code安装教程!

工欲善其事必先利其器&#xff0c;一款好的开发工具可以让我们事半功倍。前面我们对HTML的相关概念和基本结构已经有了基本的了解&#xff0c;下面我们就来安装在前端开发中的需要使用的开发工具及环境。 在众多HTML编辑器中&#xff0c;选择一个适合自己的工具至关重要。今天…

如何选择适合您需求的虚拟主机服务

随着互联网的发展&#xff0c;虚拟主机服务在网站托管领域扮演着至关重要的角色。我们在前几天遇到客户咨询如何在Hostease服务商选择适合的主机服务。本文将介绍如何选择适合您需求的虚拟主机服务&#xff0c;以确保您的网站或应用程序能够稳定运行并获得最佳性能。 确定您的需…

Spring之@Transactional源码解析

前言 我们在日常开发的时候经常会用到组合注解,比如:EnableTransactionManagement Transactional、EnableAsync Async、EnableAspectJAutoProxy Aspect。今天我们就来抽丝剥茧,揭开Transactional注解的神秘面纱 EnableTransactionManagement注解的作用 当我们看到类似Ena…

nodejs web服务器 之初始化路由

每当一个请求到达服务器之后&#xff0c;需要先经过路由的匹配&#xff0c;只有匹配成功之后&#xff0c;才会调用对应的处理函数。在匹配时&#xff0c;会按照顺序进行匹配&#xff0c;请求类型和请求的URL同时匹配成功&#xff0c;返回对应的数据。 我们可以创建一个js文件&a…

零售EDI:劳氏 Lowe‘s EDI项目案例

通过 EDI&#xff0c;企业与Lowes之间可以直接交换各种商业文档&#xff0c;如订单、发票、收据等&#xff0c;从而实现信息的实时交换&#xff0c;提高了供应链的效率和准确性。在现代供应链管理中&#xff0c;EDI 已经成为了不可或缺的重要工具。 作为一家拥有多条业务线的企…

【数据结构】矩阵的压缩存储

矩阵的压缩存储 5.1 普通矩阵的存储 用二维数组存储 分为行优先和列优先&#xff1a; 行优先&#xff1a;优先存放一行的数据。 列优先&#xff1a;优先存放一列的数据。 注意下标是从0还是1开始的&#xff01; 5.2 对称矩阵的存储 对称矩阵定义 若n阶方阵中任意一个元素 a i …

【Python】新手入门(8):什么是迭代?迭代的作用是什么?

【Python】新手入门&#xff08;8&#xff09;&#xff1a;什么是迭代&#xff1f;迭代有什么应用&#xff1f; &#x1f308; 个人主页&#xff1a;高斯小哥 &#x1f525; 高质量专栏&#xff1a;Matplotlib之旅&#xff1a;零基础精通数据可视化、Python基础【高质量合集】…

C++读取NC数据的结果与真实数值不一致的解决方法

本文介绍基于C 语言的netCDF库读取.nc格式的栅格文件时&#xff0c;代码读取到的数据与栅格文件的实际数据不一致的解决方法。 最近&#xff0c;由于需要读取ERA5气象数据&#xff0c;因此使用C 语言中的netCDF库读取.nc格式文件。其中&#xff0c;偶然发现在Visual Studio的代…

卷积神经网络(CNN)算法详解

注意&#xff1a;本文引用自专业人工智能社区Venus AI 更多AI知识请参考原站 &#xff08;[www.aideeplearning.cn]&#xff09; 引言 卷积神经网络&#xff08;Convolutional Neural Networks, CNN&#xff09;是一类包含卷积计算且具有深度结构的前馈神经网络&#xff08;…

Android Termux系统安装openssh实现公网使用SFTP远程访问

文章目录 1. 安装openSSH2. 安装cpolar3. 远程SFTP连接配置4. 远程SFTP访问4. 配置固定远程连接地址 SFTP&#xff08;SSH File Transfer Protocol&#xff09;是一种基于SSH&#xff08;Secure Shell&#xff09;安全协议的文件传输协议。与FTP协议相比&#xff0c;SFTP使用了…