访问一个URL经历了哪些过程

本文详细介绍了从用户在浏览器输入域名到网页加载完毕的全过程,包括客户端获取URL、DNS解析、TCP连接、HTTP请求与响应、浏览器渲染等关键步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

从大致上来讲经历了

客户端获取URL - > DNS解析 - > TCP连接 - >发送HTTP请求 - >服务器处理请求 - >返回报文 - >浏览器解析渲染页面 - > TCP断开连接

1、概要

从用户在浏览器输入域名开始,到web页面加载完毕,这是一个说复杂不复杂,说简单不简单的过程,下文暂且把这个过程称作网页加载过程。下面我将依靠自己的经验,总结一下整个过程。如有错漏,欢迎指正。

阅读本文需要读者已有一定的计算机知识,了解TCP、DNS等。

2、分析

众所周知,打开一个网页的过程中,浏览器会因页面上的css/js/image等静态资源会多次发起连接请求,所以我们暂且把这个网页加载过程分成两部分:

html(jsp/php/aspx) 页面加载(假设存在简单的Nginx负载均衡)
css/js/image等 网页静态资源加载(假设使用CDN)

2.1 页面加载

先上一张图,直观明了地让大家了解下基本流程,然后我们再逐一分析。
在这里插入图片描述

2.1.1 DNS解析

什么是DNS解析?当用户输入一个网址并按下回车键的时候,浏览器得到了一个域名。而在实际通信过程中,我们需要的是一个IP地址。因此我们需要先把域名转换成相应的IP地址,这个过程称作DNS解析。

  1. 浏览器首先搜索浏览器自身缓存的DNS记录。

或许很多人不知道,浏览器自身也带有一层DNS缓存。Chrome 缓存1000条DNS解析结果,缓存时间大概在一分钟左右。

(Chrome浏览器通过输入:chrome://net-internals/#dns 打开DNS缓存页面)

  1. 如果浏览器缓存中没有找到需要的记录或记录已经过期,则搜索hosts文件和操作系统缓存。

在Windows操作系统中,可以通过 ipconfig /displaydns 命令查看本机当前的缓存。

通过hosts文件,你可以手动指定一个域名和其对应的IP解析结果,并且该结果一旦被使用,同样会被缓存到操作系统缓存中。

Windows系统的hosts文件在%systemroot%\system32\drivers\etc下,linux系统的hosts文件在/etc/hosts下。

3) 如果在hosts文件和操作系统缓存中没有找到需要的记录或记录已经过期,则向域名解析服务器发送解析请求。

其实第一台被访问的域名解析服务器就是我们平时在设置中填写的DNS服务器一项,当操作系统缓存中也没有命中的时候,系统会向DNS服务器正式发出解析请求。这里是真正意义上开始解析一个未知的域名。

一般一台域名解析服务器会被地理位置临近的大量用户使用(特别是ISP的DNS),一般常见的网站域名解析都能在这里命中。

4) 如果域名解析服务器也没有该域名的记录,则开始递归+迭代解析。

这里我们举个例子,如果我们要解析的是mail.google.com

首先我们的域名解析服务器会向根域服务器(全球只有13台)发出请求。显然,仅凭13台服务器不可能把全球所有IP都记录下来。所以根域服务器记录的是com域服务器的IP、cn域服务器的IP、org域服务器的IP……。如果我们要查找.com结尾的域名,那么我们可以到com域服务器去进一步解析。所以其实这部分的域名解析过程是一个树形的搜索过程。
在这里插入图片描述
根域服务器告诉我们com域服务器的IP。

接着我们的域名解析服务器会向com域服务器发出请求。根域服务器并没有mail.google.com的IP,但是却有google.com域服务器的IP。

接着我们的域名解析服务器会向google.com域服务器发出请求。…

如此重复,直到获得mail.google.com的IP地址。

为什么是递归:问题由一开始的本机要解析mail.google.com变成域名解析服务器要解析mail.google.com,这是递归。

为什么是迭代:问题由向根域服务器发出请求变成向com域服务器发出请求再变成向google.com域发出请求,这是迭代。

5) 获取域名对应的IP后,一步步向上返回,直到返回给浏览器。

2.1.2 发起TCP请求

浏览器会选择一个大于1024的本机端口向目标IP地址的80端口发起TCP连接请求。经过标准的TCP握手流程,建立TCP连接。
在这里插入图片描述
客户端:

(应用层开始)获取URL,通过负责域名解析的DNS服务获取网址的IP地址,根据HTTP协议生成HTTP请求报文(应用层结束)

(传输层开始)根据TCP协议连接从客户端到服务端(通过三次握手)客户端给服务端发送一个带SYN(同步)标志的数据包给客户端,然后客户端接收到信息再给客户端回传一个带有SYN / ACK(确认)标志的数据包以示传达确认信息,客户求最后端的再传送一个带ACK标志的数据包,代表“握手”结束,连接成功.TCP协议在把请求报文按序号分割成多个报文段(传输层结束)

(网络层开始)根据IP协议(传输数据),ARP协议(获取MAC地址),OSPF协议(选择最优路径),搜索服务器地址,一边中转一边传输数据(网络层结束)

(数据链路层开始)到达后通过数据链路层,物理层负责0,1比特流与物理设备电压高低,光的闪灭之间的互换。数据链路层负责将0,1序列划分为数据帧从一个节点传输到临近的另一个节点,这些节点是通过MAC来唯一标识的(MAC,物理地址,一个中主机会有一个MAC地址)。 (数据链路层结束)

服务端

通过数据链路层 - >通过网络层 - >再通过传输层(根据TCP协议接收请求报文并重组报文段) - >再通过应用层(通过HTTP协议对请求的内容进行处理) - >再通过应用层 - >传输层 - >网络层 - >数据链路层 - >到达客户端

客户端

通过数据链路层 - >网络层 - >传输层(根据TCP协议接收响应报文并重组) - >应用层(HTTP协议对响应进行处理) - >浏览器渲染页面 - >断开连接协议四次挥手)

四次挥手

主动方发送标志位:(ACK + FIN)+(发送序号= 200 +确认序号= 500)第一次挥手

被动方接收后发送标志位:ACK +(发送序号=主动方确认序号500 +确认序号=主动方发送序号+1201)第二次挥手

标志位:(ACK + FIN)+(发送序号=主动方确认序号+1 501)第三次挥手

主动方接收后发送标志位:(ACK)+(发送序号=被动方的确认序号201 +确认序号=被动方的发生序号+1502)
在这里插入图片描述

2.1.3 发起HTTP请求

其实这部分又可以称为前端工程师眼中的HTTP,它主要发生在客户端。发送HTTP请求的过程就是构建HTTP请求报文并通过TCP协议中发送到服务器指定端口(HTTP协议80/8080, HTTPS协议443)。HTTP请求报文是由三部分组成: 请求行, 请求报头和请求正文。

请求行

格式如下:
Method Request-URL HTTP-Version CRLF

eg: GET index.html HTTP/1.1

常用的方法有: GET, POST, PUT, DELETE, OPTIONS, HEAD。

TODO:

GET和POST有什么区别?

请求报头

请求报头允许客户端向服务器传递请求的附加信息和客户端自身的信息。
PS: 客户端不一定特指浏览器,有时候也可使用Linux下的CURL命令以及HTTP客户端测试工具等。
常见的请求报头有: Accept, Accept-Charset, Accept-Encoding, Accept-Language, Content-Type, Authorization, Cookie, User-Agent等。

上图是使用Chrome开发者工具截取的对百度的HTTP请求以及响应报文,从图中可以看出,请求报头中使用了Accept, Accept-Encoding, Accept-Language, Cache-Control, Connection, Cookie等字段。Accept用于指定客户端用于接受哪些类型的信息,Accept-Encoding与Accept类似,它用于指定接受的编码方式。Connection设置为Keep-alive用于告诉客户端本次HTTP请求结束之后并不需要关闭TCP连接,这样可以使下次HTTP请求使用相同的TCP通道,节省TCP连接建立的时间。

请求正文

当使用POST, PUT等方法时,通常需要客户端向服务器传递数据。这些数据就储存在请求正文中。在请求包头中有一些与请求正文相关的信息,例如: 现在的Web应用通常采用Rest架构,请求的数据格式一般为json。这时就需要设置Content-Type: application/json。

服务器处理请求并返回HTTP报文

自然而然这部分对应的就是后端工程师眼中的HTTP。后端从在固定的端口接收到TCP报文开始,这一部分对应于编程语言中的socket。它会对TCP连接进行处理,对HTTP协议进行解析,并按照报文格式进一步封装成HTTP Request对象,供上层使用。这一部分工作一般是由Web服务器去进行,我使用过的Web服务器有Tomcat, Jetty和Netty等等。

HTTP响应报文也是由三部分组成: 状态码, 响应报头和响应报文。

状态码

状态码是由3位数组成,第一个数字定义了响应的类别,且有五种可能取值:

  • 1xx 【消息】服务器收到请求,需要请求者继续执行操作
  • 2xx 【成功】请求已成功被服务器接收、理解、并接受。
  • 3xx 【重定向】客户端需要采取进一步的操作以完成请求
  • 4xx 【客户端请求错误】客户端错误,请求包含语法错误或无法完成请求
  • 5xx 【服务器错误】服务器在处理请求的过程中发生了错误

平时遇到比较常见的状态码有:200, 204, 301, 302, 304, 400, 401, 403, 404, 422, 500等:

  • 200 OK //客户端请求成功
  • 304 Not Modified // 未修改。所请求的资源未修改,服务器返回此状态码时,不会返回任何资源
  • 400 Bad Request //客户端请求有语法错误,不能被服务器所理解
  • 401 Unauthorized // 当前请求要求用户的身份认证
  • 403 Forbidden // 服务器理解请求客户端的请求,但是拒绝执行此请求
  • 404 Not Found //请求资源不存在,输入了错误的URL
  • 500 Internal Server Error //服务器发生不可预期的错误
  • 503 Server Unavailable // 由于超载或系统维护,服务器暂时的无法处理客户端的请求。一段时间后可能恢复正常

更多可见:http://www.webmasterhome.cn/httpstatus/

TODO:

301和302有什么区别?

HTTP缓存

响应报头

常见的响应报头字段有: Server, Connection…。

响应报文

服务器返回给浏览器的文本信息,通常HTML, CSS, JS, 图片等文件就放在这一部分。

2.1.4 负载均衡

什么是负载均衡?当一台服务器无法支持大量的用户访问时,将用户分摊到两个或多个服务器上的方法叫负载均衡。

什么是Nginx?Nginx是一款面向性能设计的HTTP服务器,相较于Apache、lighttpd具有占有内存少,稳定性高等优势。

负载均衡的方法很多,Nginx负载均衡、LVS-NAT、LVS-DR等。这里,我们以简单的Nginx负载均衡为例。关于负载均衡的多种方法详情大家可以Google一下。

Nginx有4种类型的模块:core、handlers、filters、load-balancers。

我们这里讨论其中的2种,分别是负责负载均衡的模块load-balancers和负责执行一系列过滤操作的filters模块。

1) 一般,如果我们的平台配备了负载均衡的话,前一步DNS解析获得的IP地址应该是我们Nginx负载均衡服务器的IP地址。所以,我们的浏览器将我们的网页请求发送到了Nginx负载均衡服务器上。

2) Nginx根据我们设定的分配算法和规则,选择一台后端的真实Web服务器,与之建立TCP连接、并转发我们浏览器发出去的网页请求。

Nginx默认支持 RR轮转法 和 ip_hash法 这2种分配算法。

前者会从头到尾一个个轮询所有Web服务器,而后者则对源IP使用hash函数确定应该转发到哪个Web服务器上,也能保证同一个IP的请求能发送到同一个Web服务器上实现会话粘连。

也有其他扩展分配算法,如:

fair:这种算法会选择相应时间最短的Web服务器

url_hash:这种算法会使得相同的url发送到同一个Web服务器

3) Web服务器收到请求,产生响应,并将网页发送给Nginx负载均衡服务器。

4) Nginx负载均衡服务器将网页传递给filters链处理,之后发回给我们的浏览器。
在这里插入图片描述
  而Filter的功能可以理解成先把前一步生成的结果处理一遍,再返回给浏览器。比如可以将前面没有压缩的网页用gzip压缩后再返回给浏览器。

2.1.5 浏览器渲染

1) 浏览器根据页面内容,生成DOM Tree。根据CSS内容,生成CSS Rule Tree(规则树)。调用JS执行引擎执行JS代码。

2) 根据DOM Tree和CSS Rule Tree生成Render Tree(呈现树)

3) 根据Render Tree渲染网页

浏览器是一个边解析边渲染的过程。首先浏览器解析HTML文件构建DOM树,然后解析CSS文件构建渲染树,等到渲染树构建完成后,浏览器开始布局渲染树并将其绘制到屏幕上。这个过程比较复杂,涉及到两个概念: reflow(回流)和repain(重绘)。DOM节点中的各个元素都是以盒模型的形式存在,这些都需要浏览器去计算其位置和大小等,这个过程称为relow;当盒模型的位置,大小以及其他属性,如颜色,字体,等确定下来之后,浏览器便开始绘制内容,这个过程称为repain。页面在首次加载时必然会经历reflow和repain。reflow和repain过程是非常消耗性能的,尤其是在移动设备上,它会破坏用户体验,有时会造成页面卡顿。所以我们应该尽可能少的减少reflow和repain。

JS的解析是由浏览器中的JS解析引擎完成的。JS是单线程运行,也就是说,在同一个时间内只能做一件事,所有的任务都需要排队,前一个任务结束,后一个任务才能开始。但是又存在某些任务比较耗时,如IO读写等,所以需要一种机制可以先执行排在后面的任务,这就是:同步任务(synchronous)和异步任务(asynchronous)。JS的执行机制就可以看做是一个主线程加上一个任务队列(task queue)。同步任务就是放在主线程上执行的任务,异步任务是放在任务队列中的任务。所有的同步任务在主线程上执行,形成一个执行栈;异步任务有了运行结果就会在任务队列中放置一个事件;脚本运行时先依次运行执行栈,然后会从任务队列里提取事件,运行任务队列中的任务,这个过程是不断重复的,所以又叫做事件循环(Event loop)。

浏览器在解析过程中,如果遇到请求外部资源时,如图像,iconfont,JS等。浏览器将重复1-6过程下载该资源。请求过程是异步的,并不会影响HTML文档进行加载,但是当文档加载过程中遇到JS文件,HTML文档会挂起渲染过程,不仅要等到文档中JS文件加载完毕还要等待解析执行完毕,才会继续HTML的渲染过程。原因是因为JS有可能修改DOM结构,这就意味着JS执行完成前,后续所有资源的下载是没有必要的,这就是JS阻塞后续资源下载的根本原因。CSS文件的加载不影响JS文件的加载,但是却影响JS文件的执行。JS代码执行前浏览器必须保证CSS文件已经下载并加载完毕。

2.2 网页静态资源加载

以阿里巴巴的淘宝网首页的logo为例,其url地址为 img.alicdn.com/tps/i2/TB1bNE7LFXXXXaOXFXXwFSA1XXX-292-116.png_145x145.jpg

我们清楚地看到了url中有cdn字样。

什么是CDN?如果我在广州访问杭州的淘宝网,跨省的通信必然造成延迟。如果淘宝网能在广东建立一个服务器,静态资源我可以直接从就近的广东服务器获取,必然能提高整个网站的打开速度,这就是CDN。CDN叫内容分发网络,是依靠部署在各地的边缘服务器,使用户就近获取所需内容,降低网络拥塞,提高用户访问响应速度。

接下来的流程就是浏览器根据url加载该url下的图片内容。本质上是浏览器重新开始第一部分的流程,所以这里不再重复阐述。区别只是负责均衡服务器后端的服务器不再是应用服务器,而是提供静态资源的服务器。

Web优化

上面部分主要介绍了一次完整的请求对应的过程,了解该过程的目的无非就是为了Web优化。在谈到Web优化之前,我们回到一个更原始的问题,Web前端的本质是什么。我的理解是: 将信息快速并友好的展示给用户并能够与用户进行交互。快速的意思就是在尽可能短的时间内完成页面的加载,试想一下当你在淘宝购买东西的时候,淘宝页面加载了10几秒才显示出物品,这个时候你还有心情去购买吗?怎么快速的完成页面的加载呢?优雅的学院派雅虎给出了常用的一些手段,也就是我们熟悉的雅虎34条军规。这34军规实际上就是围绕请求过程进行的一些优化方式。

如何尽快的加载资源?答案就是能不从网络中加载的资源就不从网络中加载,当我们合理使用缓存,将资源放在浏览器端,这是最快的方式。如果资源必须从网络中加载,则要考虑缩短连接时间,即DNS优化部分;减少响应内容大小,即对内容进行压缩。另一方面,如果加载的资源数比较少的话,也可以快速的响应用户。当资源到达浏览器之后,浏览器开始进行解析渲染,浏览器中最耗时的部分就是reflow,所以围绕这一部分就是考虑如何减少reflow的次数。

<think>好的,我现在要回答用户关于从浏览器输入URL到页面加载经历的步骤的问题。首先,我需要回忆之前的学习内容,确保自己对这个过程有正确的理解。用户之前已经问过页面渲染完成后提示用户的阶段,现在想了解整个加载流程,所以我需要详细但清晰地分步骤解释。 首先,用户输入URL后,浏览器可能会检查是否有缓存,比如之前访问过的页面资源,如果有的话可能直接加载,节省时间。但如果没有缓存或者缓存过期,就需要进行DNS解析,把域名转换成IP地址。这里可能需要解释DNS查询的过程,包括递归查询和缓存的作用。 接下来是建立TCP连接,三次握手的过程。这部分需要简明扼要地描述,因为用户可能不是技术人员,但需要准确。然后是SSL/TLS握手,如果网站使用HTTPS的话,这一步是必要的,确保安全连接。 然后,浏览器发送HTTP请求,服务器处理请求并返回响应。这里可能需要区分不同的HTTP方法,比如GET请求获取资源,POST提交数据。服务器处理可能涉及后端逻辑,数据库查询等。 之后,浏览器接收到响应后开始解析HTML,构建DOM树,同时遇到CSS和JS文件时会进行加载和执行。这里需要注意渲染阻塞的问题,比如JS的执行可能会影响DOM构建,所以现代浏览器的预解析扫描可能是个优化点。 构建CSSOM和渲染树,布局和绘制页面,最后合成图层显示出来。这个过程可能涉及重排和重绘,但用户的问题可能不需要深入到那个程度,所以保持概括。 此外,还需要考虑可能的重定向步骤,比如服务器返回301或302状态码时的处理。另外,在整个过程中,缓存的机制可能多次出现,比如DNS缓存、资源缓存等,需要提到但不过于深入。 用户可能还想知道各个阶段的时间线,或者如何优化页面加载速度,但当前问题主要是步骤,所以可能需要保持步骤的清晰,分阶段列出,并用例子或比喻帮助理解。 需要检查是否有遗漏的步骤,比如预加载、预渲染等,但这些可能属于更高级的优化,基础流程中可能不需要提及。保持回答结构清晰,分点说明,每个步骤简明扼要,避免技术术语过多,但也要准确。 最后,总结整个流程,帮助用户形成完整的认识。可能还需要对比之前的回答,确保没有重复,但提供新的信息。例如,之前讲的是渲染后的提示阶段,现在则是整个从输入到渲染的流程。 需要确保使用中文,语法正确,行内公式用$...$,独立公式用$$...$$,但在这个问题中可能较少涉及数学公式,但如果有技术术语可能需要正确格式。例如,HTTP状态码可能需要用代码块或引号标注。 总之,回答需要涵盖:URL解析、DNS查询、TCP连接、TLS握手、HTTP请求、服务器处理、响应接收、解析渲染等步骤,每个步骤简要说明,结构清晰,帮助用户逐步理解整个过程。</think>### 从浏览器输入 URL 到页面加载的完整流程 --- #### 1. **URL 解析与缓存检查** - **用户输入处理** 浏览器自动补全协议(如 `http://` 或 `https://`)并规范化 URL 格式。 **示例**:输入 `example.com` → 自动转换为 `https://example.com`。 - **缓存检查** 浏览器优先检查以下缓存(按优先级排序): - **Service Worker 缓存**(若注册了 Service Worker) - **内存缓存**(高频访问资源) - **磁盘缓存**(HTTP Cache,通过 `Cache-Control` 控制) --- #### 2. **DNS 域名解析** - **查询顺序** 1. 浏览器缓存 → 2. 操作系统缓存 → 3. 路由器缓存 → 4. ISP DNS 服务器 → 5. 递归查询根域名服务器 **关键记录**:最终获取目标服务器的 IP 地址(如 `93.184.216.34`)。 - **优化技术** - **DNS 预解析**:通过 `<link rel="dns-prefetch" href="//example.com">` 提前解析。 --- #### 3. **建立 TCP 连接(三次握手)** ```plaintext 1. 客户端 → 服务器:SYN(同步请求,Seq=x) 2. 服务器 → 客户端:SYN-ACK(确认响应,Seq=y, Ack=x+1) 3. 客户端 → 服务器:ACK(最终确认,Ack=y+1) ``` **耗时分析**:通常 1~3 个 RTT(Round-Trip Time)。 --- #### 4. **TLS 安全握手(仅 HTTPS)** - **协商加密套件**:选择 TLS 版本、对称加密算法(如 AES)、密钥交换方式(如 ECDHE)。 - **证书验证**:检查服务器证书链有效性(如 CA 机构签名)。 - **密钥交换**:通过非对称加密协商会话密钥。 **完整流程**: ```plaintext 1. ClientHello → 2. ServerHello + 证书 → 3. 密钥交换 → 4. 完成握手 ``` --- #### 5. **发送 HTTP 请求** - **请求结构** ```http GET /index.html HTTP/1.1 Host: example.com User-Agent: Mozilla/5.0 Accept: text/html ``` - **关键方法**:`GET`(获取资源)、`POST`(提交数据)。 - **头部控制**:`Cookie`、`Cache-Control`、`Accept-Encoding` 等。 --- #### 6. **服务器处理请求** - **后端逻辑**:Web 服务器(如 Nginx)转发请求到应用服务器(如 Node.js、Java)。 - **动态生成**:执行数据库查询、API 调用等操作,生成 HTML 响应。 - **响应返回**:包含状态码(如 `200 OK`)、响应头、响应体。 --- #### 7. **浏览器解析与渲染** - **构建 DOM 树** 解析 HTML → 生成 DOM 节点树(遇到 `<script>` 会暂停解析,除非标记 `async/defer`)。 - **构建 CSSOM** 解析 CSS 规则 → 生成 CSS 对象模型树。 - **合并渲染树(Render Tree)** 组合 DOM 和 CSSOM,排除不可见元素(如 `<head>`、`display: none`)。 - **布局(Layout/Reflow)** 计算元素几何位置(如宽度、边距),生成“盒模型”。 - **绘制(Paint)与合成(Composite)** 分层绘制 → 合成线程处理 GPU 加速(如 CSS `transform`)。 --- #### 8. **加载动态资源** - **异步内容处理**: ```javascript // AJAX 数据加载示例 fetch('/api/data') .then(response => response.json()) .then(data => updateDOM(data)); ``` - **延迟加载(Lazy Load)**:对图片/视频使用 `loading="lazy"`。 --- #### 9. **触发关键事件** | 事件 | 触发条件 | 典型用途 | |-----------------------|-----------------------------------|----------------------------| | `DOMContentLoaded` | HTML 解析完成(无需等待图片/CSS) | 绑定交互事件 | | `load` | 所有资源加载完毕 | 统计页面完全加载时间 | | `beforeunload` | 页面关闭前 | 提示用户保存未提交数据 | --- ### 流程优化关键点 1. **减少 DNS 查询**:使用 DNS 预解析或 HTTP/2 域名分片。 2. **压缩资源**:Gzip/Brotli 压缩文本资源,WebP 格式图片。 3. **复用连接**:HTTP/2 多路复用替代短连接。 4. **延迟非关键 JS**:通过 `async/defer` 控制脚本加载。 5. **关键渲染路径优化**:内联首屏 CSS,优先加载可见内容。 --- ### 总结流程图 ```plaintext 用户输入 URL → 缓存检查 → DNS 解析 → TCP 握手 → TLS 握手 → HTTP 请求 → 服务器响应 → 解析渲染 → 加载完成 ```
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值