突破编程_C++_网络编程(OSI 七层模型(物理层与数据链路层))

1 OSI 七层模型概述

OSI(Open Systems Interconnection)七层模型,即开放系统互联参考模型,起源于 20 世纪 70 年代和 80 年代。随着计算机网络技术的快速发展和普及,不同厂商生产的计算机和网络设备之间的互操作性成为了一个亟待解决的问题。为了解决这个挑战,国际标准化组织(ISO)开始着手研究如何将各种网络设备和协议统一为一个标准的框架。

1977 年,ISO 成立了一个专门的工作小组,负责研究网络互操作性的标准。经过数年的深入研究、讨论和完善,ISO与国际电报电话咨询委员会(CCITT,现已成为国际电信联盟ITU的一部分)于 1978 年共同发布了第一版的OSI参考模型。这个模型初步为网络通信提供了一个通用的架构。

随着技术的不断进步和需求的日益复杂,OSI七层模型经过了进一步的完善和调整。终于在 1984 年,ISO 正式发布了 OSI 七层参考模型的标准,它将通信过程划分为七个抽象层次:物理层、数据链路层、网络层、传输层、会话层、表示层和应用层。每个层次都有其特定的功能和协议,共同协作以实现网络中的有效通信:

物理层: 物理层是OSI参考模型中最底层,负责将数字信号转换为物理信号,并在网络中进行传输。它涉及到电缆、光缆、中继器等物理设备的连接和传输技术。
数据链路层: 数据链路层在物理层之上,以帧为单位传输数据。它负责数据的封装和解封装,以及流量控制和差错控制等功能。
网络层: 网络层负责数据的路由和转发,实现主机之间的通信。它使用IP地址来确定数据包的传输路径,并通过路由器等设备将数据包从一个网络转发到另一个网络。
传输层: 传输层为端到端的通信提供可靠的传输服务。它负责将数据分割成小的数据包,并在接收端将数据包重新组合成原始数据。TCP和UDP是传输层中的两种主要协议。
表示层: 这一层负责数据格式的转换,使得不同的系统能够互相理解。它将来自应用层的数据转换成一种适合网络传输的格式,并进行加密和压缩等操作。
会话层: 会话层负责建立、管理和结束会话,确保应用程序之间的通信能够顺利进行。它负责同步不同应用程序之间的对话,并在通信失败时重新建立会话。
应用层: 这是OSI参考模型中最靠近用户的一层,为应用程序提供服务,例如电子邮件、网页浏览、文件传输等。它负责识别网络进程和应用程序,并对它们进行通信。

OSI 七层模型的提出,不仅为网络通信提供了一个标准化的框架,还促进了不同厂商生产的设备之间的兼容性和互操作性。这一模型为计算机网络的发展奠定了坚实的基础,并对后续的网络技术发展和创新产生了深远的影响。

尽管 OSI 七层模型在理论上非常完善,但在实际应用中,TCP/IP 协议族因其简单、高效和广泛的应用而更为流行。然而,OSI七层模型仍然被广泛用于教学和理论研究,帮助人们深入理解网络通信的原理和机制。

2 物理层

2.1 物理层的功能与作用

首先,物理层的主要功能是以二进制数据形式在物理媒体上传输数据。它利用传输介质为数据链路层提供物理连接,实现比特流的透明传输。也就是说,物理层负责处理原始的比特流,这些比特流通过物理媒体进行传输,并在到达目的地后再进行解码,确保数据的完整性和准确性。

其次,物理层规定了激活、维持、关闭通信端点之间的机械特性、电气特性、功能特性以及过程特性。这意味着物理层不仅负责数据的传输,还确保传输过程中的稳定性和可靠性,避免因电气信号的不稳定或物理连接的断开而导致的通信故障。

再者,物理层负责选择合适的传输介质,并规定相关的接口标准。这些接口标准确保不同设备间的互操作性,使得不同厂商的设备可以在同一网络中进行通信。同时,物理层还负责控制数据传输的时序,确保发送端和接收端的速率匹配,防止因速率不匹配而导致的数据丢失或混乱。

此外,物理层还进行基本的错误检测与纠正,以确保数据的可靠传输。它通过检测比特流中的错误,并进行必要的纠正,防止传输中出现丢失、替换或损坏的数据。

最后,物理层还负责管理传输媒介的分配和使用,确保网络资源的有效利用。

总的来说,OSI物理层在网络通信中起到了至关重要的作用,它负责数据的物理传输和连接管理,确保数据的完整性和可靠性,为上层协议提供了一个稳定、可靠的物理媒体。

2.2 物理层的传输介质与设备

OSI物理层的传输介质主要包括电缆、光纤、无线电波等。这些传输介质的选择取决于特定的通信需求和场景。

电缆是一种常见的传输介质,其中网线在以太网中尤为常见。网线有多种类型,如屏蔽双绞线和非屏蔽双绞线,它们分别适用于不同的环境和需求。光纤则以其高速率和长距离传输的特性在通信领域得到广泛应用。

除了传输介质,物理层还涉及一系列设备,这些设备在数据的传输和连接中起着关键作用。典型的物理层设备包括网卡、集线器、中继器和调制解调器等。

  • 网卡是计算机与传输介质之间的接口,它负责将计算机内部的数据转换成适合传输介质传输的格式。
  • 集线器和中继器都是用于扩展网络覆盖范围的设备。集线器采用广播的形式来传输信息,而中继器则负责在信号衰减到一定程度时,对信号进行放大和再生,以确保信号能够继续传输。
  • 调制解调器则用于数字信号和模拟信号之间的转换,使得数据可以在不同类型的传输介质上进行传输。

这些设备共同工作,确保数据能够在物理层上进行有效的传输和连接。它们不仅关注数据的传输效率,还致力于确保数据的完整性和安全性。通过选择合适的传输介质和设备,物理层为上层协议提供了一个稳定、可靠的物理通信基础。

2.3 物理层协议与标准

OSI物理层的主要协议与标准涉及多种物理连接和数据传输的技术和规范。以下是其中一些重要的协议与标准:

Ethernet(以太网协议):

  • 是一种局域网(LAN)的物理连接和数据传输协议。
  • 它定义了如何在不同类型的电缆(如双绞线、同轴电缆和光纤)上进行数据传输。
  • 以太网已成为当今局域网中最常用的技术之一。

RS-232:

  • 是一种用于串行通信的标准接口协议。
  • 它定义了数据终端设备(DTE)和数据通信设备(DCE)之间的接口标准,常用于计算机与外部设备(如调制解调器)之间的连接。

USB(Universal Serial Bus,通用串行总线):

  • 是一种用于连接计算机和外部设备的接口标准。
  • 它支持热插拔,即在不关闭计算机电源的情况下插入或拔出设备。
  • USB 具有多种版本,如 USB 2.0、USB 3.0 等,每个版本都提供了不同的传输速度和功能。

光纤分布式数据接口(FDDI):

  • 是一种使用光纤作为传输介质的高速网络协议。
  • 它为工作站和服务器之间的连接提供了一种高带宽、低延迟的通信方式。
  • 此外,物理层还涉及一些特定的物理连接规范,如网络接口类型、光纤接口类型以及传输介质的速率等相关的电器特性。这些规范确保了不同设备之间的互操作性和兼容性。

需要注意的是,随着技术的不断发展,新的物理层协议与标准也在不断出现和更新。因此,在实际应用中,需要根据具体的网络环境和需求选择适合的协议与标准。

3 数据链路层

3.1 数据链路层的功能与作用

OSI数据链路层是计算机网络中的一个关键层次,位于物理层和网络层之间。它的主要功能和作用包括以下几个方面:

  • 帧同步与封装:数据链路层负责将原始比特流分割成帧,并添加必要的地址信息,以便在直接连接的设备之间传输数据。帧是数据链路层的传送单位,其组织结构被设计成使得接收方能够明确地从物理层收到的比特流中识别出帧的起始与终止。
  • 数据链路管理:数据链路层管理物理链路上的数据传输,处理发送和接收过程中的错误、帧丢失等问题。它利用错误检测和纠正技术,如循环冗余校验(CRC),来确保数据的完整性。
  • 流量控制:为了避免发送方发送数据过快而导致接收方无法处理的情况,数据链路层负责进行流量控制。通过发送方和接收方之间的通信,数据链路层可以控制和调整数据的发送速率。
  • 差错控制:数据链路层还负责确保数据的可靠传输。它采用各种差错控制技术,如奇偶校验、循环冗余校验(CRC)和前向纠错码等,来检测和纠正数据传输中的错误。
  • 访问控制:在多个设备共享同一物理链路资源的情况下,数据链路层通过访问控制来解决可能出现的冲突和竞争问题。

综上所述,OSI数据链路层的主要功能与作用在于通过帧同步与封装、数据链路管理、流量控制、差错控制以及访问控制等手段,确保数据在物理链路上的可靠、高效传输。它为上层协议提供了稳定、可靠的通信基础,使得整个计算机网络能够正常、高效地运行。

3.2 数据帧的构成与传输

在OSI数据链路层中,数据帧是数据传输的基本单位。它负责将数据从发送方传递到接收方,并确保数据的完整性和准确性。数据帧的构成与传输是数据链路层功能的重要组成部分。

首先,数据帧的构成通常包括以下几个部分:

(1)帧头(Frame Header):

帧头包含了关于帧的元信息,用于标识帧的起始、目的地址、源地址以及帧的类型等信息。其中,目的地址和源地址用于标识数据帧的接收方和发送方,确保数据能够准确地传输到目标设备。

(2)数据字段(Data Field):

数据字段是帧中实际传输的数据部分,它包含了来自上层(如网络层)的数据信息。数据字段的长度可以根据通信需求进行调整,但通常受到物理层和数据链路层的限制。

(3)帧尾(Frame Trailer):

帧尾用于提供数据完整性检查和帧结束标识。它通常包含帧校验序列(FCS),用于检测帧在传输过程中是否出现错误。帧尾还可以用于标识帧的结束,帮助接收方正确地解析数据。

为了方便理解,可以使用 C++ 来定义一个数据帧的简化数据结构:

#include <vector>  
#include <cstdint>  
  
// 假设地址和数据字段的最大长度  
const uint16_t MAX_ADDRESS_LENGTH = 6; // 例如,对于以太网地址  
const uint16_t MAX_DATA_LENGTH = 1500; // 例如,对于以太网的最大MTU  
  
// 帧头(Frame Header)结构  
struct FrameHeader {  
    std::vector<uint8_t> destinationAddress; // 目的地址  
    std::vector<uint8_t> sourceAddress;      // 源地址  
    uint16_t frameType;                      // 帧类型  
    // 可以添加其他元信息字段,如帧长度、序列号等  
  
    FrameHeader() : frameType(0) {  
        destinationAddress.resize(MAX_ADDRESS_LENGTH, 0);  
        sourceAddress.resize(MAX_ADDRESS_LENGTH, 0);  
    }  
  
    // 可以添加构造函数、拷贝构造函数、赋值运算符等  
};  
  
// 帧尾(Frame Trailer)结构  
struct FrameTrailer {  
    std::vector<uint8_t> frameCheckSequence; // 帧校验序列  
  
    FrameTrailer() {  
        frameCheckSequence.resize(4, 0); // 假设FCS为32位  
    }  
  
    // 可以添加计算FCS的方法等  
};  
  
// 数据帧(Data Frame)结构  
struct DataFrame {  
    FrameHeader header;  
    std::vector<uint8_t> dataField; // 数据字段  
    FrameTrailer trailer;  
  
    DataFrame() {  
        dataField.resize(0);  
    }  
  
    // 可以添加方法来设置和获取帧的各个部分  
    void setDataField(const std::vector<uint8_t>& data) {  
        if (data.size() <= MAX_DATA_LENGTH) {  
            dataField = data;  
        } else {  
            // 处理数据过大的情况,如截断或抛出异常  
        }  
    }  
  
    const std::vector<uint8_t>& getDataField() const {  
        return dataField;  
    }  
  
    // 其他操作数据帧的方法  
};

这只是一个非常简化的示例,实际的数据帧结构可能会更复杂,并且会包含更多的字段和特性。此外,根据实际的通信协议和网络环境,数据帧的最大长度、地址长度、帧类型等可能有所不同。而且,在实际应用中还需要实现一些方法,如计算帧校验序列(FCS)、序列化帧为字节流以便传输、从字节流中解析帧等。

接下来,数据帧的传输过程如下:

(1)封装成帧:

在发送端,数据链路层将来自上层的数据信息封装成帧。这包括添加帧头和帧尾,以及可能的其他控制信息。封装成帧的目的是确保数据在传输过程中能够被正确地识别和解析。

(2)物理层传输:

封装好的数据帧被传递给物理层,由物理层负责将数据帧转换为适合在物理介质上传输的信号形式。这可以涉及比特编码、调制等过程,以确保数据能够在物理链路上稳定地传输。

(3)接收与解析:

在接收端,物理层接收到信号后将其还原为数据帧。数据链路层随后解析帧头、数据字段和帧尾,以提取出实际的数据信息。同时,数据链路层还会对帧进行完整性检查,以确保数据在传输过程中没有受到损坏。

需要注意的是,数据链路层还负责处理传输过程中的错误和流量控制等问题。它可能采用各种机制来确保数据的可靠传输,如重传机制、流量控制算法等。

3.3 数据链路层协议与标准(如 SDLC、HDLC、PPP 等)

数据链路层协议包括多种类型,如 SDLC(同步数据链路控制)、HDLC(高级数据链路控制)以及PPP(点对点协议)。其中SDLC 是一种IBM的数据链路层协议,适用于系统网络体系结构(SNA)。HDLC 由ISO制定的面向比特的协议,采用比特填充法实现帧的透明传输。PPP 则用于计算机之间通过串行线路进行连接的标准协议,支持多种链路类型。

在实际应用中,需要根据具体的网络环境和需求来选择合适的数据链路层协议。例如,在广域网中,PPP和HDLC等协议较为常见;而在局域网中,以太网协议则占据主导地位。

(1) SDLC(Synchronous Data Link Control,同步数据链路控制)

数据链路层协议 SDLC(Synchronous Data Link Control,同步数据链路控制)是一种 IBM 开发的传输协议,它在 19 世纪 70 年代取代了二进制同步(BSC)协议,成为当时的主流协议。SDLC 协议在数据链路层为特定通信网络提供了网络可寻址单元(NAUs)间的数据差错释放(Error-Free)功能,确保数据在传输过程中的准确性和可靠性。

在 SDLC 协议中,信息流经过数据链路控制层由上层往下传送至物理控制层,然后通过一些接口传送到通信链路。它支持各种链路类型和拓扑结构,可以应用于点对点和多点链接、有界和无界媒体、半双工和全双工传输方式,以及电路交换网络和分组交换网络。此外,SDLC 还支持识别两类网络节点:主节点(Primary)和次节点(Secondary)。

在IBM大型机网络中,主机通常是主节点,而工作站和其他设备则为次节点。多个设备或次节点可以使用多点排列连接到一条公共线。SDLC 也支持点到点通信,特别是在宽域网(WAN)的远程通信中。

SDLC 协议不仅广泛应用于 IBM 的系统网络体系结构(SNA)和系统应用结构(ASS),而且它还是国际标准化组织(ISO)的标准数据链协议高层次数据链控制(HDLC)的基础。由于其在确保数据可靠传输方面的出色表现,SDLC 至今仍被广泛使用于大型机的数据链控制。

(2) HDLC(High-Level Data Link Control,高级数据链路控制)

数据链路层协议 HDLC(High-Level Data Link Control,高级数据链路控制)是一种面向比特的同步通信网络的数据链路层协议。它在 OSI 参考模型的第二层(数据链路层)中起到关键作用,主要用于实现远程用户间的资源共享以及信息交互。

HDLC 协议的基本原理是通过控制字符进行帧的分隔与标识,并采用逐比特的同步位同步方式进行数据传输。每个比特都经过帧同步字段的定界,以确保数据的准确传输。这种同步性保证了数据的有效传输和接收。发送端和接收端通过切换控制字段来切换发送和接收的状态。

HDLC 协议具有以下显著特点:

  • 面向比特:以比特为单位进行数据传输,每个比特都经过帧同步字段的定界,确保数据的准确传输。
  • 同步传输:使用时钟信号来同步发送端和接收端的数据传输,保证数据的有效传输和接收。
  • 流量控制:提供了流量控制机制,可以控制数据的传输速率,防止数据的溢出和丢失。它使用确认帧(S帧)和窗口机制来控制发送端的数据发送速率。
  • 错误检测和纠正:使用CRC校验码来检测和纠正传输过程中可能出现的错误。接收端在接收数据时会对CRC校验码进行验证,以确保数据的完整性。
  • 可靠传输:通过确认帧(S帧)和超时重传帧(U帧)来确保数据的可靠传输。接收端会确认接收到的数据,并在需要时请求重传。

HDLC 协议的帧结构包括起始标志、地址字段、控制字段、信息字段、帧校验序列和结束标志。其中,地址字段可以表达单播、多播和广播等不同需求,控制字段用于指示操作和状态,信息字段则是实际传输的数据。

HDLC 协议的工作模式主要分为三种:无连接不可靠模式、有连接可靠模式和既有连接又有无连接的混合模式。无连接不可靠模式适用于短消息传输,而有连接可靠模式则适用于大容量数据传输,并且支持差错检测与纠正。

HDLC 协议具有简单高效、可靠可扩展等特点,在广域网和局域网中得到了广泛应用。它能够实现数据的可靠传输,提供高效稳定的通信服务,并具备较高的扩展性。此外,HDLC 协议还广泛应用于铁路自动化系统中,实现列车间的通信和控制,确保列车系统的高效运行和安全性。

(3) PPP(Point-to-Point Protocol,点对点协议)

数据链路层协议 PPP(Point-to-Point Protocol,点对点协议)是为在点对点连接上传输多协议数据包提供的一种标准方法。PPP 最初设计是为了在两个对等节点之间提供IP流量的传输封装协议,在TCP/IP协议集中,它是一种用于同步调制连接的数据链路层协议(OSI 模式中的第二层),替代了原来非标准的第二层协议,即 SLIP。

PPP 协议具有许多显著的特点和功能:

  • 通用性:PPP协议不仅支持IP协议,还可以携带其他协议,如DECnet和Novell的Internet网包交换(IPX)。这使得PPP能够在多种网络层协议上运行,如IP和IPX等,从而在同一条物理链路上支持多种网络层协议的运行。
  • 错误检测与处理:PPP协议具有处理错误检测的功能。接收方每收到一个帧,都会进行CRC检验,以确保数据的完整性和准确性。
  • 透明性:PPP协议能够确保数据传输的透明性。即使在数据中出现了和帧定界符一致的比特组合时,PPP协议也能通过一些措施来解决这个问题,从而确保数据的正确传输。
  • 封装与帧同步:PPP协议定义了特殊的字符作为帧定界符,以便接收端能够准确地从收到的比特流中找出帧的开始和结束位置。这种帧同步机制确保了数据的正确解析和处理。
  • 链路控制:PPP协议通过链路控制协议(LCP)来协商一些重要的参数,如PPP帧中Information字段所允许的最大长度(MRU)和错误控制等,以确保PPP链路能够正常工作。
  • 支持多种链路类型:PPP协议能够在多种类型的链路上运行,包括串行的、并行的、同步的、异步的、低速的、高速的、电的或光的、交换的或非交换的点对点链路。

PPP协议广泛应用于各种不同的场景中,包括家庭网络、企业网络、宽带接入、虚拟专线等。在家庭网络中,PPP协议通常用于拨号上网,这种方式适用于没有固定宽带接入的用户。在企业网络中,PPP协议常用于建立VPN(虚拟专用网络),以实现不同地点之间的数据互通。此外,PPP协议还支持身份认证等功能,为网络通信提供了安全保障。

然而,PPP协议也存在一些局限性,例如它不支持广播和多点连接。这意味着在某些特定的网络拓扑和通信需求下,PPP协议可能不是最佳选择。

3.4 差错控制

数据链路层的差错控制是确保数据在传输过程中准确、可靠地到达目的地的重要机制。在实际信道上传输数字信号时,由于信道传输特性不理想及加性噪声的影响,所收到的数字信号不可避免地会发生错误。为了检测并纠正这些错误,数据链路层采用了多种差错控制技术。

差错控制编码是实现差错控制的关键技术。这种编码在发送端被传输的信息序列上附加一些监督码元,这些多余的码元与信息码元之间以某种确定的规则相互关联(约束)。接收端则按照既定的规则检验信息码元与监督码元之间的关系。一旦传输过程中发生差错,信息码元与监督码元之间的关系将受到破坏,从而可以发现错误,乃至纠正错误。

常见的差错控制编码方式有检错码和纠错码。检错码能够检测出差错的存在,但不能确定差错的具体位置。而纠错码不仅能检测出差错,还能确定差错的位置,并尝试恢复正确的数据。

数据链路层还采用了多种差错控制协议,如停等协议、回退 N 帧协议(GBN)和选择重传协议(SR)等。这些协议通过不同的方式实现差错控制和流量控制,确保数据的可靠传输。

差错控制的方式主要分为自动请求重发 ARQ(Automatic Repeat request,也叫检错重发)和前向纠错 FEC(Forward Error Correction)。ARQ 方式中,接收方在检测到错误后会向发送方发送请求,要求重传出错的数据。而 FEC 方式中,发送方会发送一些额外的信息,使得接收方在检测到错误时能够直接纠正错误,而无需请求重发。

此外,数据链路层还使用了校验和、循环冗余校验(CRC)等方法来检测帧中的错误。这些方法通过在发送的数据中附加一些校验信息,使得接收方能够通过计算校验信息来检测数据是否在传输过程中发生了改变。

总的来说,数据链路层的差错控制机制通过编码、协议和校验等手段,确保了数据的完整性和准确性,为上层协议提供了可靠的数据传输服务。

3.5 流量控制机制

数据链路层的流量控制机制是确保发送方发送数据的速率与接收方接收数据的速率相匹配的关键过程。这种控制机制有助于防止发送方发送数据过快,导致接收方缓冲区溢出,从而确保数据的可靠传输。

数据链路层的流量控制通常是点对点的,即每两个相邻节点间进行流量控制,如主机到路由器、路由器到路由器等。这种控制机制通过监控和调整发送方的发送速率来实现,具体可以通过多种方式来实现,以下详细讲解其中几种主要方式:

(1)停止-等待流量控制:

  • 基本原理:发送方每发送一帧,都需要等待接收方的应答信号,才能继续发送下一帧。接收方每接收到一帧,会反馈一个应答信号,表示可接受下一帧。如果接收方不反馈应答信号,发送方必须一直等待。
  • 优点:控制简单。
  • 缺点:传输效率很低,线路在很多时间内都处于空闲状态。

(2)滑动窗口流量控制:

  • 基本原理:在任意时刻,发送方都维持一组连续的允许发送的帧的序号,称为发送窗口;同时,接收方也维持一组连续的允许接收帧的序号,称为接收窗口。发送窗口用于对发送方进行流量控制,其大小WT代表在还未收到对方确认信息的情况下,发送方最多还能发送多少个数据帧。
  • 优点:相比停止-等待协议,滑动窗口协议可以连续发送多个数据帧,无需等待每个帧的确认,从而提高了传输效率。
  • 工作原理:只有当接收窗口向前滑动,并且接收方发送了确认帧时,发送窗口才有可能向前滑动。这种机制确保了发送方和接收方之间的数据流动是协调的。

(3)令牌桶算法:

  • 基本原理:发送方和接收方之间有一个令牌桶。发送方每发送一个数据包,都会从令牌桶中获取一个令牌。如果令牌桶中没有令牌,发送方需要等待令牌的生成。接收方则通过不断生成令牌来设置发送速率的上限。
  • 优点:可以有效控制发送速率,避免数据包的丢失和重传。
  • 缺点:需要精确控制令牌的生成速率。

这些流量控制机制各有优缺点,适用于不同的网络环境和应用需求。在实际应用中,可以根据具体情况选择合适的流量控制机制来确保数据的可靠传输。

最近更新

  1. TCP协议是安全的吗?

    2024-03-31 21:44:02       19 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-03-31 21:44:02       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-03-31 21:44:02       20 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-03-31 21:44:02       20 阅读

热门阅读

  1. 专升本-区块链

    2024-03-31 21:44:02       15 阅读
  2. 【八股】IOC

    2024-03-31 21:44:02       19 阅读
  3. 二分查找中的小细节

    2024-03-31 21:44:02       18 阅读
  4. http和https的区别!

    2024-03-31 21:44:02       15 阅读
  5. Python:魔法函数

    2024-03-31 21:44:02       19 阅读
  6. 滑动窗口算法详解及应用示例

    2024-03-31 21:44:02       18 阅读
  7. 第十五届蓝桥杯第二期模拟赛——python

    2024-03-31 21:44:02       17 阅读