网络协议

计算机网络体系结构

OSI 七层模型

  • 开放系统互连参考模型 (Open System Interconnect 简称 OSI)是国际标准化组织(ISO) 和国际电报电话咨询委员会(CCITT)联合制定的开放系统互连参考模型,为开放式互连信息系统提供了一种功能结构的框架。其目的是为计算机互连提供一个共同的基础和标准框架, 并为保持相关标准的一致性和兼容性提供共同的参考。这里所说的开放系统,实质上指的是遵循 OSI 参考模型和相关协议能够实现互连的具有各种应用目的的计算机系统。
  • OSI 采用了分层的结构化技术,共分七层,物理层、数据链路层、网络层、传输层、会话层、表示层、应用层。

TCP/IP 模型

  • OSI 模型比较复杂且学术化,所以我们实际使用的 TCP/IP 模型,共分 4 层,链路层、网络层、传输层、应用层。 两个模型之间的对应关系如图所示:

在这里插入图片描述

  • 无论什么模型,每一个抽象层建立在低一层提供的服务上,并且为高一层提供服务。

TCP/IP 协议族

  • Transmission Control Protocol/Internet Protocol 的简写,中译名为传输控制协议/因特网互联协议,是 Internet 最基本的协议、Internet 国际互联网络的基础,由网络层的 IP 协议和 传输层的 TCP 协议组成。协议采用了 4 层的层级结构。然而在很多情况下,它是利用 IP 进行通信时所必须用到的协议群的统称。也就是说,它其实是个协议家族,由很多个协议组成, 并且是在不同的层,是互联网的基础通信架构。

在这里插入图片描述

TCP/IP 网络传输中的数据

  • 每个分层中,都会对所发送的数据附加一个首部,在这个首部中包含了该层必要的信息, 如发送的目标地址以及协议相关信息。通常,为协议提供的信息为包首部,所要发送的内容为数据。在下一层的角度看,从上一层收到的包全部都被认为是本层的数据。
  • 网络中传输的数据包由两部分组成:一部分是协议所要用到的首部,另一部分是上一层传过来的数据。首部的结构由协议的具体规范详细定义。在数据包的首部,明确标明了协议应该如何读取数据。反过来说,看到首部,也就能够了解该协议必要的信息以及所要处理的数据。
  • 包是全能性术语;
  • 用于表示数据链路层中包的单位;
  • 网络层 IP中数据的单位;
  • 则表示传输层 TCP 数据流中的信息;
  • 消息是指应用层协议中数据的单位。
    在这里插入图片描述
    ① 应用程序处理
    首先应用程序会进行编码处理,这些编码相当于 OSI 的表示层功能; 编码转化后,邮件不一定马上被发送出去,这种何时建立通信连接何时发送数据的管理功能, 相当于 OSI 的会话层功能。
    ② TCP 模块的处理
    TCP 根据应用的指示,负责建立连接、发送数据以及断开连接。TCP 提供将应用层发来的数据顺利发送至对端的可靠传输。为了实现这一功能,需要在应用层数据的前端附加一个 TCP 首部。
    ③ IP 模块的处理
    IP 将 TCP 传过来的 TCP 首部和 TCP 数据合起来当做自己的数据,并在 TCP 首部的前端加上自己的 IP 首部。IP 包生成后,参考路由控制表决定接受此 IP 包的路由或主机。
    ④ 网络接口(以太网驱动)的处理
    从 IP 传过来的 IP 包对于以太网来说就是数据。给这些数据附加上以太网首部并进行发送处理,生成的以太网数据包将通过物理层传输给接收端。
    ⑤ 网络接口(以太网驱动)的处理
    主机收到以太网包后,首先从以太网包首部找到 MAC 地址判断是否为发送给自己的包,若不是则丢弃数据。 如果是发送给自己的包,则从以太网包首部中的类型确定数据类型,再传给相应的模块,如 IP、ARP 等。这里的例子则是 IP 。
    ⑥ IP 模块的处理
    IP 模块接收到数据后也做类似的处理。从包首部中判断此 IP 地址是否与自己的 IP 地址 匹配,如果匹配则根据首部的协议类型将数据发送给对应的模块,如 TCP、UDP。这里的例子则是 TCP。 另外,对于有路由器的情况,接收端地址往往不是自己的地址,此时,需要借助路由控制表,在调查应该送往的主机或路由器之后再进行转发数据。
    ⑦ TCP 模块的处理
    在 TCP 模块中,首先会计算一下校验和,判断数据是否被破坏。然后检查是否在按照序号接收数据。最后检查端口号,确定具体的应用程序。数据被完整地接收以后,会传给由端口号识别的应用程序。
    ⑧ 应用程序的处理
    接收端应用程序会直接接收发送端发送的数据。通过解析数据,展示相应的内容。

TCP 和 UDP

  • 网络层 IP 是 TCP/IP 中非常重要的协议。负责对数据加上 IP 地址(包括发送它的主机的地址(源地址)和接收它的主机的地址(目的地址))和其他的数据以确定传输的目标。
  • 而 TCP 和 UDP 都是传输层的协议,传输层主要为两台主机上的应用程序提供端到端的通信。
  • 但是 TCP 和 UDP 最不同的地方是,TCP 提供了一种可靠的数据传输服务,TCP 是面向连接的,也就是说,利用 TCP 通信的两台主机首先要经历一个建立连接的过程,等到连接建立后才开始传输数据,而且传输过程中采用“带重传的肯定确认”技术来实现传输的可靠性。TCP 还采用一种称为“滑动窗口”的方式进行流量控制,发送完成后还会关闭连接。所以 TCP 要比 UDP 可靠的多。
  • UDP(User Datagram Protocol - 用户数据报协议)是把数据直接发出去,而不管对方是不是在接收,也不管对方是否能接收的了,也不需要接收方确认,属于不可靠的传输,可能会出现丢包现象,实际应用中要求程序员编程验证。
  • 注意: 我们一些常见的网络应用基本上都是基于 TCP 和 UDP 的,这两个协议又会使用网络层的 IP 协议。但是我们完全可以绕过传输层的 TCP 和 UDP,直接使用 IP,比如 Linux 中 LVS, 甚至直接访问链路层,比如 tcpdump 程序就是直接和链路层进行通信的。

在这里插入图片描述

  • TCP - 面向连接的、可靠的流协议
  • UDP - 面向无连接的通讯协议
  • IP - 在源地址和目的地址之间传送的数据包
  • ICMP - 控制报文协议
  • IGMP - internet组管理协议
  • ARP - 地址解析协议
  • RARP - 反向地址转化协议

地址和端口号

MAC 地址

  • MAC 地址全称叫做媒体访问控制地址,也称为局域网地址(LAN Address),MAC 位址, 以太网地址(Ethernet Address)或物理地址(Physical Address),由网络设备制造商生产时写在硬件内部。MAC 地址与网络无关,也即无论将带有这个地址的硬件(如网卡、集线器、 路由器等)接入到网络的何处,都有相同的 MAC 地址,它由厂商写在网卡的 BIOS 里,从理论上讲是唯一的。
  • MAC 地址共 48 位(6 个字节)。前 24 位由 IEEE(电气和电子工程师协会)决定如何分配,后 24 位由实际生产该网络设备的厂商自行制定。例如:FF:FF:FF:FF:FF:FF 或 FF-FF-FF-FF-FF-FF

IP 地址

  • IP 地址(Internet Protocol Address)的全称叫作互联网协议地址,它的本义是为互联网 上的每一个网络和每一台主机配置一个唯一的逻辑地址,用来与物理地址作区分。
  • 所以 IP 地址用来识别 TCP/IP 网络中互连的主机和路由器。IP 地址基于逻辑,比较灵 活,不受硬件限制,也容易记忆。
  • IP 地址分为:IPv4 和 IPv6。IPv4 是由 32 位的二进制数组成,它们通常被分为 4 个“8 位二进制数”,我们可以把它理解为 4 个字节,格式表示为:(A.B.C.D)。其中,A,B,C,D 这四个英文字母表示为 0-255 的十进制的整数。例: 192.168.1.1

IP 地址和 MAC 地址之间的区别
1、对于网络中的一些设备,路由器或者是 PC 及而言,IP 地址的设计是出于拓扑设计出来的,只要在不重复 IP 地址的情况下,它是可以随意更改的;而 MAC 地址是根据生产厂 商烧录好的,它一般不能改动的,一般来说,当一台 PC 机的网卡坏了之后,更换了网卡之后 MAC 地址就会变了。

2、长度不同,IP 地址的长度为 32 位,而 MAC 地址为 48 位。

3、它们的寻址协议层不同。IP 地址应用于 OSI 模型的网络层,而 MAC 地址应用在 OSI 模型的数据链路层。 数据链路层协议可以使数据从一个节点传递到相同链路的另一个节点 上(通过 MAC 地址),而网络层协议使数据可以从一个网络传递到另一个网络上(ARP 根据目的 IP 地址,找到中间节点的 MAC 地址,通过中间节点传送,从而最终到达目的网络)。

4、分配依据不同。IP 地址的分配是基于我们自身定义的网络拓扑,MAC 地址的分配是基于制造商。

端口号

  • 在传输层也有这种类似于地址的概念,那就是端口号。端口号用来识别同一台计算机中 进行通信的不同应用程序。因此,它也被称为程序地址。
  • 一台计算机上同时可以运行多个程序。传输层协议正是利用这些端口号识别本机中正在 进行通信的应用程序,并准确地将数据传输。

端口号的确定

  • 标准既定的端口号:这种方法也叫静态方法。它是指每个应用程序都有其指定的端口号。但并不是说可以随意使用任何一个端口号。例如 HTTP、FTP、TELNET 等广为使用的应用协议中所使用的端口号就是固定的。这些端口号被称为知名端口号,分布在 0 ~ 1023 之间;除知名端口号之外,还有一些端口号被正式注册,它们分布在 1024 ~ 49151 之间,不过这些端口号可用于任何通信用途。
  • 时序分配法:服务器有必要确定监听端口号,以让客户端程序访问服务器上的服务。 但是使用服务的客户端没必要确定端口号。在这种方法下,客户端应用程序完全可以不用自己设置端口号,而全权交给操作系统进行分配。动态分配的端口号范围在 49152~65535 之间。

综述

  • 不管计算机中有多少网卡,每个网卡都会有自己的 MAC 地址,这个 MAC 地址是不会变化的。而每个网卡在正常工作的情况下,都会有一个 IP 地址,这个 IP 地址完全是可以变化的。而这台计算机中承载的各种应用程序可以拥有自己的端口号,然后通过服务器的网卡,正确地进行网络通信。
  • 所以通过源 IP 地址、目标 IP 地址、协议号(协议类型)、源端口号以及目标端口号这五个元素唯一性的识别一个网络上的通信。

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

TCP

  • TCP的基本特性
    1、面向连接
    2、可靠性
    3、RTT和RTO
    4、数据排序
    5、流量控制
    6、全双工
  • TCP(Transmission Control Protocol)是面向连接的通信协议,通过三次握手建立连接, 然后才能开始数据的读写,通讯完成时要拆除连接,由于 TCP 是面向连接的所以只能用于端到端的通讯。
  • TCP 提供的是一种可靠的数据流服务,数据有可能被拆分后发送,那么采用超时重传机制和应答确认机制是组成 TCP 可靠传输的关键设计。
  • 而超时重传机制中最最重要的就是重传超时(RTO,Retransmission TimeOut)的时间选择,很明显,在工程上和现实中网络环境是十分复杂多变的,有时候有延迟,有时候很顺畅。在数据发送的过程中,如果用一个固定的值一直作为超时计时器的时长是非常不经济也非常不准确的方法,因此超时的时长就需要根据网络情况动态调整,就需要采样统计一个数据包从发送端发送出去到接收到这个包的回复这段时长来动态设置重传超时值,这个时长就是为 RTT(round-trip time,一个连接的往返时间),然后再根据这个 RTT 通过各种算法和公式平滑 RTT 值后,最终确定重传超时值。
  • 而 IP 层进行数据传输时,是不能保证数据包按照发送的顺序达到目的机器。当 IP 将把 它们向‘上’传送到 TCP 层后,TCP 将包排序并进行错误检查。TCP 数据包中包括序号和确认, 所以未按照顺序收到的包可以被排序,而损坏的包可以被重传。
  • TCP 还采用一种称为“滑动窗口”的方式进行流量控制,所谓窗口实际表示接收能力,用以限制发送方的发送速度。
  • 同时 TCP 还允许在一个 TCP 连接上,通信的双方可以同时传输数据,也就是所谓的全双工(好比对讲机就可以理解为单工,同一时刻只能有一个人讲话)。
  • 面向连接的服务(例如 Telnet、FTP、rlogin、X Windows 和 SMTP)需要高度的可靠性, 所以它们使用了 TCP。DNS 在某些情况下使用 TCP(发送和接收域名数据库),但使用 UDP 传送有关单个主机的信息。

TCP 三次握手

在这里插入图片描述

  • TCP 提供面向有连接的通信传输。面向有连接是指在数据通信开始之前先做好两端之间 的准备工作。
  • 所谓三次握手是指建立一个 TCP 连接时需要客户端和服务器端总共发送三个包以确认连接的建立。在 socket 编程中,这一过程由客户端执行 connect 来触发。
  • 第一次握手:客户端将标志位 SYN 置为 1,随机产生一个值 seq=J,并将该数据包发送 给服务器端,客户端进入 SYN_SENT 状态,等待服务器端确认。
  • 第二次握手:服务器端收到数据包后由标志位 SYN=1 知道客户端请求建立连接,服务 器端将标志位 SYN 和 ACK 都置为 1,ack=J+1,随机产生一个值 seq=K,并将该数据包发送给客户端以确认连接请求,服务器端进入 SYN_RCVD 状态。
  • 第三次握手:客户端收到确认后,检查 ack 是否为 J+1,ACK 是否为 1,如果正确则将 标志位 ACK 置为 1,ack=K+1,并将该数据包发送给服务器端,服务器端检查 ack 是否为 K+1, ACK 是否为 1,如果正确则连接建立成功,客户端和服务器端进入 ESTABLISHED 状态,完成三次握手,随后客户端与服务器端之间可以开始传输数据了。

为什么 TCP 握手需要三次?

  • TCP 是可靠的传输控制协议,而三次握手是保证数据可靠传输又能提高传输效率的最小 次数。为什么?RFC793,也就是 TCP 的协议 RFC 中就谈到了原因,这是因为:
  • 为了实现可靠数据传输, TCP 协议的通信双方,都必须维护一个序列号, 以标识发送出去的数据包中,哪些是已经被对方收到的。
  • 三次握手的过程即是通信双方相互告知序列号起始值,并确认对方已经收到了序列号 起始值的必经步骤
  • 如果只是两次握手, 至多只有连接发起方的起始序列号能被确认, 另一方选择的序列号则得不到确认。
  • 至于为什么不是四次,很明显,三次握手后,通信的双方都已经知道了对方序列号起始 值,也确认了对方知道自己序列号起始值,第四次握手已经毫无必要。

TCP 的三次握手的漏洞-SYN 洪泛攻击

  • 攻击者客户端利用伪造的IP地址向服务端发出请求(第一次握手),而服务端的响应(第二次握手)的报文将永远发送不到真实的客户端,服务端在等待客户端的第三次握手(永远都不会有的),服务端在等待这种半开的连接过程中消耗了资源,如果有成千上万的这种连接,主机资源将被耗尽,从而达到攻击的目的。
  • 面对这种攻击,有以下的解决方案,最好的方案是防火墙。
    1、无效连接监视释放
    这种方法不停监视所有的连接,包括三次握手的,还有握手一次的,反正是所有的,当达到一定阈值时拆除这些连接,从而释放系统资源。这种方法对于所有的连接一视同仁,不管是正常的还是攻击的,所以这种方式不推荐。
    2、延缓 TCB 分配方法
    一般的做完第一次握手之后,服务器就需要为该请求分配一个 TCB(传输控制块Transmission Control Block),通常这个资源需要 200 多个字节。延迟 TCB 的分配,当正常连接建立起来后再分配 TCB 则可以有效地减轻服务器资源的消耗。
    3、使用防火墙
    防火墙在确认了连接的有效性后,才向内部的服务器(Listener)发起 SYN 请求。

TCP 四次挥手

  • 四次挥手即终止 TCP 连接,就是指断开一个 TCP 连接时,需要客户端和服务端总共发送 4 个包以确认连接的断开。在 socket 编程中,这一过程由客户端或服务端任一方执行 close 来触发。
  • 由于 TCP 连接是全双工的,因此,每个方向都必须要单独进行关闭,这一原则是当甲方 完成数据发送任务后,发送一个 FIN 给乙方来终止这一方向的连接,乙方收到一个 FIN 只是意味着不会再收到甲方数据了,但是乙方依然可以给甲方发送数据,直到这乙方也发送了 FIN 给甲方。首先进行关闭的一方将执行主动关闭,而另一方则执行被动关闭。

在这里插入图片描述

1、某个应用进程首先调用 close,我们称该端执行主动关闭(active close)。该端的 TCP 于是发送一个 FIN ,表示数据发送完毕,应用进程进入 FIN-WAIT-1(终止等待 1)状态。

2、接收到这个 FIN 的对端执行被动关闭(passive close),发出确认报文。这个 FIN 由 TCP 确认。因为 FIN 的接收意味着接收端应用进程在相应连接上再无额外数据可接收。接收端进入了 CLOSE-WAIT(关闭等待)状态,这时候处于半关闭状态,即主动关闭端已经没有数据要发送了,但是被动关闭端若发送数据,主动关闭端依然要接受。这个状态还要持续一段时间,也就是整个 CLOSE-WAIT 状态持续的时间。主动关闭端收到确认报文后进入 FIN-WAIT-2 (终止等待 2)状态。

3、一段时间后,被动关闭的应用进程将调用 close 关闭它的套接字。这导致它的 TCP 也 发送一个 FIN。

4、接收这个最终 FIN 的原发送端 TCP(即执行主动关闭的那一端)确认这个 FIN 发出一 个确认 ACK 报文,并进入了 TIME-WAIT(时间等待)状态。注意此时 TCP 连接还没有释放, 必须经过 2∗MSL(最长报文段寿命/最长分节生命期 max segement lifetime,MSL 是任何 IP 数据报能够在因特网中存活的最长时间,任何 TCP 实现都必须为 MSL 选择一个值。RFC 1122[Braden 1989]的建议值是 2 分钟,不过源自 Berkelcy 的实现传统上改用 30 秒这个值。 这意味着 TIME_WAIT 状态的持续时间在 1 分钟到 4 分钟之间)的时间后,当主动关闭端撤销相应的 TCB 后,才进入 CLOSED 状态。

5、被动关闭端只要收到了客户端发出的确认,立即进入 CLOSED 状态。同样,撤销 TCB 后,就结束了这次的 TCP 连接。可以看到,被动关闭端结束 TCP 连接的时间要比主动关闭端早一些。

  • 既然每个方向都需要一个 FIN 和一个 ACK,因此通常需要 4 个分节。我们使用限定词“通常”是因为:某些情形下步骤 1 的 FIN 随数据一起发送;另外,步骤 2 和步骤 3 发送的分节都出自执行被动关闭那一端,有可能被合并成一个分节。

为什么 TCP 的挥手需要四次?

  • TCP 是全双工的连接,必须两端同时关闭连接,连接才算真正关闭。
  • 如果一方已经准备关闭写,但是它还可以读另一方发送的数据。发送 FIN 结束报文给对方,对方收到后,回复 ACK 报文。当这方也已经写完了准备关闭,发送 FIN 报文,对方回复 ACK。两端都关闭,TCP 连接正常关闭。

为什么需要 TIME-WAIT 状态?

  • TIME_WAIT 状态存在的原因有两点
    1、可靠的终止 TCP 连接。
    2、保证让迟来的 TCP 报文有足够的时间被识别并丢弃。
  • 根据前面的四次握手的描述,客户端收到服务器的连接释放的 FIN 报文后, 必须发出确认。如果最后这个 ACK 确认报文丢失,那么服务器没有收到这个 ACK 确认报文, 就要重发 FIN 连接释放报文,客户端要在某个状态等待这个 FIN 连接释放报文段然后回复确认报文,这样才能可靠的终止 TCP 连接。
  • 在 Linux 系统上,一个 TCP 端口不能被同时打开多次,当一个 TCP 连接处于 TIME_WAIT 状态时,我们无法使用该链接的端口来建立一个新连接。反过来思考,如果不存在 TIME_WAIT 状态,则应用程序能过立即建立一个和刚关闭的连接相似的连接(这里的相似,是指他们具有相同的 IP 地址和端口号)。这个新的、和原来相似的连接被称为原来连接的化身。新的化身可能收到属于原来的应用程序数据的 TCP 报文段(迟到的报文段),这显然是不该发生的。这是 TIME_WAIT 状态存在的第二个原因。

HTTP

  • HTTP 协议全称是 Hyper Text Transfer Protocol(超文本传输协议),是用于从万维网 (WWW:World Wide Web )服务器传输超文本到本地浏览器的传送协议。

HTTP 协议

  • 我们使用 http 来访问 Web 上某个资源,比如 html/文本、word、avi 电影、其他资源。 官方协议网站:https://tools.ietf.org/html/rfc2608
  • HTTP 使用统一资源标识符(Uniform Resource Identifiers, URI)来传输数据和建立连接。 URL 是一种特殊类型的 URI,包含了用于查找某个资源的足够的信息。
  • URL,全称是 UniformResourceLocator, 中文叫统一资源定位符,是互联网上用来标识某一 处资源的地址。
  • URN: Uniform Resource Name,统一资源命名

区别和联系:

  • URL和URN都是URI的子集
  • URL和URN都是URI,但是URI不一定是URL或者URN
  • 这是一个URI
    https://www.baidu.com/news/detail?id=1681658779375522633#name
  • 这是一个URL
    https://www.baidu.com/news/detail?id=1681658779375522633
  • 这是一个URN
    www.baidu.com/news/detail?id=1681658779375522633#name

一次完整 http 请求的过程

1、首先进行 DNS 域名解析(本地浏览器缓存、操作系统缓存或者 DNS 服务器)
a)首先会搜索浏览器自身的 DNS 缓存(缓存时间比较短,大概只有 1 分钟,且只能容纳 1000 条缓存);
b)如果浏览器自身的缓存里面没有找到,那么浏览器会搜索系统自身的 DNS 缓存;
c)如果还没有找到,那么尝试从 hosts 文件里面去找;
d)在前面三个过程都没获取到的情况下,就去域名服务器去查找。

2、三次握手建立 TCP 连接
在 HTTP 工作开始之前,客户端首先要通过网络与服务器建立连接,HTTP 连接是通过 TCP 来完成的。HTTP 是比 TCP 更高层次的应用层协议,根据规则,只有低层协议建立之后,才能进行高层协议的连接,因此,首先要建立 TCP 连接,一般 TCP 连接的端口号是 80;

3、客户端发起 HTTP 请求

4、服务器响应 HTTP 请求

5、客户端解析 html 代码,并请求 html 代码中的资源
浏览器拿到 html 文件后,就开始解析其中的 html 代码,遇到 js/css/image 等静态资源时,就向服务器端去请求下载

6、客户端渲染展示内容

7、关闭 TCP 连接

  • 一般情况下,一旦服务器向客户端返回了请求数据,它就要关闭 TCP 连接,然后如果 客户端或者服务器在其头信息加入了这行代码 Connection:keep-alive ,TCP 连接在发送后将仍然保持打开状态,于是,客户端可以继续通过相同的连接发送请求,也就是说前面的 3到 6,可以反复进行。保持连接节省了为每个请求建立新连接所需的时间,还节约了网络带宽。

HTTP 协议报文结构

  • 用于 HTTP 协议交互的信息被称为 HTTP 报文。请求端(客户端)的 HTTP 报文叫做请求报文;响应端(服务器端)的叫做响应报文。HTTP 报文本身是由多行(用 CR+LF 作换行符)数据构成的字符串文本。
  • HTTP 报文大致可分为报文首部和报文主体两部分。两者由最初出现的空行(CR+LF) 来划分。通常,并不一定有报文主体。

在这里插入图片描述

请求报文结构

  • 请求报文的首部内容由以下数据组成:
  • 请求行 —— 包含用于请求的方法、请求 URI 和 HTTP 版本。
  • 首部字段 —— 包含表示请求的各种条件和属性的各类首部。(通用首部、请求首部、 实体首部以及 RFC 里未定义的首部如 Cookie 等)

在这里插入图片描述

响应报文结构

  • 状态行 —— 包含表明响应结果的状态码、原因短语和 HTTP 版本。
  • 首部字段 —— 包含表示请求的各种条件和属性的各类首部。(通用首部、响应首部、 实体首部以及 RFC 里未定义的首部如 Cookie 等)

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值