计算机网络——应用层

这篇博客深入探讨了应用层的网络技术,重点介绍了HTTP协议的工作原理、请求方法和响应头,包括GET、POST、HEAD等请求类型,以及Cookie、Session、缓存策略等内容。还涉及了DNS域名解析、DHCP协议、HTTPS协议及其加密模型,以及跨域问题的解决方案。同时,文章讨论了HTTP1.0、HTTP1.1和HTTP2.0之间的区别,强调了HTTP2.0的多路复用技术和性能提升。

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

计算机网络——应用层

DNS

DNS,(Domain Name System)域名系统。
因为当我们访问一个网站的时候,其实访问的是一系列的IP地址+主机等一系列数字,记录十分麻烦,而且也记不住。

但其实我们访问各个网站的时候,你会发现根本不是一系列的数字,其实就是利用了DNS服务器将域名转换成IP地址和端口。

DNS域名解析过程

bupt.edu.cn
cn 顶级域名
edu 二级域名
bupt 三级域名

域名采用上述的树状结构,因此也有各种不同种类的域名服务器:本地域名服务器、根域名服务器、顶级域名服务器、权限域名服务器等。

域名到IP地址的解析就是由上面这些域名服务器程序共同合作完成的。

当浏览器需要一个域名的真实IP地址时,它会首先将域名发送给本地域名服务器,如果本地域名服务器有IP,则直接返回,否则,本地域名服务器就会向根域名服务器继续发出查询请求报文;如果根域名服务器没有IP,就会告知本地域名服务器,去哪个顶级域名服务器,然后本地域名服务器会访问相应的顶级域名服务器,如果还是没有,顶级域名服务器会告知本地域名服务器去哪个响应的权限域名服务器,直到找到IP。

本地域名服务器----》根域名服务器----》顶级域名服务器----》权限域名服务器

DHCP协议

DHCP,Dynamic Host Configoration Protocol,动态主机配置协议。一个局域网协议,并应用于UDP协议之上的应用层。

提出一个问题,IP地址的网络前缀是会随着局域网的不同而改变,但是我们的主机设备在更换局域网的时候并不需要配置任何设置,这就是DHCP协议在帮助我们

HTTP协议

HTTP协议,HyperText Transfer Protocol,超文本传输协议(同时也是明文传输)
超文本,超级文本,带有超链接的文本。

访问其他网站需要地址:http://<主机>:<端口>/<路径>

HTTP协议是可靠的传输协议,也就是依赖于TCP协议完成。

工作原理

HTTP协议采用了请求/响应模型:客户端向服务器发送一个请求报文(请求报文包含请求的方法、URL、协议版本、请求头部和请求数据);服务器以一个状态行作为响应(协议的版本、成功或者错误代码、服务器信息、响应头部和响应数据)

1、一个HTTP客户端,通常是浏览器,与Web服务器的HTTP端口(默认为80)建立一个TCP套接字连接
2、通过TCP套接字,客户端向Web服务器发送一个文本的请求报文
3、Web服务器解析请求,定位请求资源。服务器响应,将资源复本写到TCP套接字,由客户端读取。
4、若connection 模式为close,则服务器主动关闭TCP连接,客户端被动关闭连接,释放TCP连接;若connection 模式为keepalive,则该连接会保持一段时间,在该时间内可以继续接收请求;
5、客户端浏览器首先解析状态行,查看表明请求是否成功的状态代码。然后解析每一个响应头,响应头告知以下为若干字节的HTML文档和文档的字符集。客户端浏览器读取响应数据HTML,根据HTML的语法对其进行格式化,并在浏览器窗口中显示。

🌰:在浏览器地址栏键入URL,按下回车之后会经历以下流程

1、浏览器首先会寻找缓存,查看缓存中是否有记录,缓存的查找记录为:浏览器缓存-》系统缓存-》路由器缓存,缓存中没有则查找系统的hosts文件中是否有记录
2、如果没有缓存,浏览器向 DNS 服务器请求解析该 URL 中的域名所对应的 IP 地址;
3、解析出 IP 地址后,根据该 IP 地址和默认端口 80,和服务器建立TCP连接;
4、浏览器发出(URL 中域名后面部分对应的文件)HTTP 请求,该请求报文作为 TCP 三次握手的第三个报文的数据发送给服务器;
5、服务器对浏览器请求作出响应,并把对应的 html 文本发送给浏览器;
6、页面渲染html文件,首先构建DOM树
7、CSS样式渲染CSSOM树
8、两棵树最终构建一个render树,之后渲染到真实DOM中
9、释放 TCP连接;(两种模式,keep-alive = true / false)

请求方法

GET、POST、PUT、DELETE

OPTIONS

OPTIONS请求方法的主要用途有两个:

1、获取服务器支持的HTTP请求方法;例如:Allow:GET, POST(只是举个例子)
2、用来检查服务器的性能,跨域请求时的预检

HEAD

HEAD方法允许客户端仅向服务器请求某个资源的响应头,而不要真正的下载该资源本身.服务器返回的响应头应该和客户端使用GET方法请求该资源时返回的请求头相同,比起GET方法,只是省略了响应体。

请求头

Accept 可接受响应数据类型
Referer HTTP请求来自浏览器的哪个URL
Accept-Encoding 告诉服务器能接受什么编码格式,包括字符编码,压缩形式(一般都是压缩形式)

例如:Accept-Encoding:gzip, deflate(这两种都是压缩格式)

Connection 客户端(浏览器)想要优先使用的连接类型(keep-alive)
Cookie 会话标识,后面会详细讲解
Host 服务器域名与端口号
If-None-Match 用来询问Etag是否过期
If-Modified-Since 用来判断Last-Modify是否过期

响应头

Cache-Control 是否支持强缓存(no-cache/max-age以s为单位设置过期时间)后面在缓存处有详细讲解
ETag 请求资源的当前版本(字符串),用来进行协商缓存
Last-Modify 请求资源上次修改的时间(时间戳)用来协商缓存
Set-Cookie 服务端可以设置客户端的cookie

响应码

2XX:此次请求成功

200   服务器已成功处理了请求。通常,这表示服务器提供了请求的网页
201   请求成功并且服务器创建会修改了资源
202   服务器已接受请求,但尚未处理,允许服务器先接受其他请求
204   服务器成功处理了请求,但没有返回任何内容(可以用来响应删除)
205   服务器成功处理了请求,但没有返回任何内容,但是与204响应不同,返回此状态码的响应要求请求者重置文档视图
206   服务器成功处理了部分 GET 请求,这种响应是在客户端表明自己只需要目标URL上的部分资源的时候返回的
204与200的区别

200就是最最普通的成功请求,而204是成功请求但是没有返回响应体,本质上200如果没有有响应体,二者区别不大,但是当出现点击导航转换URL的时候,就会出现问题:

如果导航到的URL返回了一个没有响应体的HTTP/200响应,则页面将会显示一个空白文档(就是一片白色).页面的URL地址也会变成新指定的URL.
如果服务器返回的是一个HTTP/204响应,当前页面不会有任何变化,就好像根本没有进行导航操作一样.页面的URL地址也保持不变.
206

206 响应码主要是请求响应数据只有服务器资源的一部分,客户端并不需要很多资源,只需要资源的一部分,之后服务器进行响应,返回206响应码,然后将资源的返回范围告知客户端:

Content-Range:bytes 0-1048575/2027665
// 0-1048575 是指分段的数据
// 2027665 是指总文件大小

3XX:重定向
本服务器没有请求资源,资源在另外一个服务器上,可以帮助提供新的URL

300    Multiple Choices    多种选择。请求的资源可包括多个位置,相应可返回一个资源特征与地址的列表用于用户终端(例如:浏览器)选择
301    Moved Permanently    永久移动。请求的资源已被永久的移动到新URI,返回信息会包括新的URI,浏览器会自动定向到新URI。今后任何新的请求都应使用新的URI代替
302    Found 临时移动。与301类似。但资源只是临时被移动。客户端应继续使用原有URI
303    See Other    查看其它地址。与301类似。使用GET和POST请求查看
304    Not Modified 未修改。所请求的资源未修改,服务器返回此状态码时,不会返回任何资源。客户端通常会缓存访问过的资源,通过提供一个头信息指出客户端希望只返回在指定日期之后修改的资源
305    Use Proxy    使用代理。所请求的资源必须通过代理访问

4XX:客户端请求有误,请核实查看
5XX:服务器错误

HTTP1.0 和 HTTP1.1 和 HTTP2.0 的区别

上面讲到过keep-alive,如果keep-alive这个参数为true,表示一次HTTP连接可以使用多次进行数据传输,不需要每次请求都握手。

HTTP1.0默认keep-alive为false,必须显式的开启才可以进行多次传输连接;
HTTP1.1默认keep-alive为true,一定程度上弥补了HTTP1.0每次请求都要创建连接的缺点;HTTP1.1支持只发送一个header信息(不带任何body信息);新增设了Host域;

host:服务器IP+端口号

HTTP2.0使用了多路复用的技术,做到同一个连接并发处理多个请求,而且并发请求的数量比HTTP1.1大了好几个数量级;同时提升了请求速度;采用二进制格式分帧;增加服务器端信息推送;将需要重复发送的headers进行首部压缩;

跨域

同源准则

同源准则也叫做浏览器同源政策,是浏览器安全机制只有浏览器才有,首先说一下同源,同源包括三样:

1、域名
2、协议
3、端口

只有上面三个全部满足,才能说明两个url地址是同源地址,同源地址之间可以进行:

1、cookie、localstorage信息获取
2、DOM节点获取
3、Ajax数据请求

以上三种信息交互,但是同源一般只有在同一个网站、同一个页面才能实现。

跨域

跨域,其实就是说规避掉同源策略,实现以上三种信息的交互;简单来讲,就是客户端浏览器和服务器的域名不一样、协议不一样、端口号不一样,从一台电脑向另外一台主机或云服务器请求数据,那么就会存在跨域问题,因为地盘变了,就不会给你数据了。

Cookie

Cookie也是只有同源的页面才能互相读取,首先来谈谈关于Cookie如何实现跨域。简单来讲,当我们同时打开两个不同的页面时,如何让他们能够互通Cookie。

cookie的跨域实现基础是两个页面拥有相同的一级域名,例如:

http://w1.example.com/a.html
http://w2.example.com/b.html

二者拥有相同的一级域名,那么我们需要在浏览器中设置:

document.domain = 'example.com';

这样就可以让上面两个页面互通Cookie的使用。

也许你会问,如何设置 document.domain??????

那需要了解一下Cookie的生成,Cookie生成有两种方法:(详情在下面cookie与 session模块)
1、服务器生成,然后存浏览器中,这也是平时用到最多的情况,一种登陆状态存储会设置一个 domain字段;
2、浏览器的script脚本自己生成,也是同样设置domain字段,生成方式是相通的,不过是位置的不同。

iframe

iframe与window.open是用来打开新窗口的,但是此时新窗口与父窗口无法通信,因为不同源,那么此时实现跨域也是通过document.domain,这里直接通过script脚本就可以完成。

localstorage

localstorage本地缓存,不同页面直接的本地缓存不能互通,同时上面的document.domain也不能实现跨域,就需要另外一种方式了:postMessage。

Ajax

Ajax的跨域就可以很简单的理解,浏览器向服务器请求数据,发现不同源,直接拒绝。

1、JSONP

当我们编写HTML的时候,我们希望使用其他网站的一张图片,一般会这么写:

<img src="https://ss3.baidu.com/sign=xxx.jpg"> // url 是我瞎写的,不要在意

但是实际上,可以显示出来图片,哎,它没被跨域限制,这就是因为它用了JSONP。

但是jsonp跨域只能用get请求,所以一般情况下的请求会是这样子的:

xxx.onclick = function(){
    var url = "./getdata.js";
    var script = document.createElement('script');   // 创建一个script标签
    script.setAttribute('src', url);   // 标签上放上src属性以及url
    document.getElementsByTagName('head')[0].appendChild(script); // 最后利用JS中script标签的自动跨域实现请求

2、CORS跨域资源共享

是一种基于HTTP 头的机制,允许服务器声明哪些源站通过浏览器有权限访问哪些资源,说白了,就是在服务器那边的header上增加一个字段,说明一下允许谁可以跨域访问我。

Access-Control-Allow-Origin

所以可以认为,只有服务器知道谁可以跨域访问,因此客户端在实际请求之前,需要先发送一个预先检查请求,这是的请求方法是 OPTION, 询问看看本客户端可不可以跨域,如果可以,那么此时就可以发送任意(POST、DELETE、PUT、GET)请求。

所以更加广泛应用的还是第二种,就是让后端开放跨域权限,就完全不需要钻漏洞

3、proxy代理跨域

在Vue里面的devSever里面有一个proxy属性,这个属性是用来让我们做代理跨域的。这个代理的意思是,在本地浏览器上开一个虚拟的服务器,然后利用这个虚拟的服务器去访问服务器资源,因为服务器与服务器之间是不存在跨域问题的,这样子利用一个代理就解决了跨域问题。

proxyTable: {
  '/api': {  //以这个开头的请求
      target: "http://101.200.83.63:8000",    //配置需要跨域的IP地址(访问目标地址)
      secure: false,                 // https协议需要配置,如果是https此处改为true
      changeOrigin: true,            //是否跨域,true为允许跨域
      pathRewrite: {
        '^/api': '/api'     //      代表重写,前边的是匹配规则,后边的是写入规则
      }
}

关于浏览器跨域的知识,更加详细信息可以看:http://www.ruanyifeng.com/blog/2016/04/same-origin-policy.html

HTTPS协议

顾名思义,HTTPS协议在HTTP协议上增加了Secure安全协议,从而保证了网络通信中一些隐私信息的保护。

因为HTTP协议是明文传输,存在着安全隐患,因此需要HTTPS协议进行加密传输。

HTTPS协议的端口也不再是80,而是443端口。

加密模型

1、对称加密

所谓加密,便是要在传输之前对Data进行加密保护,因此接收方也需要解密来读取Data,如果加密与解密的密钥一摸一样,那么我们称之为对称加密

2、非对称加密

非对称加密中,加密和解密的密钥是不一致的。对于非对称加密,最常见的便是公钥与私钥了,一般客户端会利用公钥进行加密数据,然后到达服务器,就会利用独特的私钥来解密从而解读请求。

SSL

SSL,Secure Sockets Layer,安全套接层,也就是HTTPS协议上增加的部分,这一层位于传输层与应用层之间,它提供数据安全与数据完整的服务,对传输层的数据进行加密。

传输过程

1、通过443端口进行TCP连接
2、SSL进行安全参数握手
3、客户端发送请求到服务器端
4、服务器端响应数据到客户端

其中最重要的就是SSL安全参数握手。

SSL安全参数握手(重点)
客户端                                            服务器端
————————————————————————————————————————————————————》
					请求进行安全握手   
《————————————————————————————————————————————————————
					数字证书(含有公钥)
 ————————————————————————————————————————————————————》
		客户端确认数字证书有效,利用公钥加密对称加密的加密码,
《————————————————————————————————————————————————————
	服务器利用私钥查看对称加密码,之后接受利用该对称加密码加密过的请求

cookie与session

会话跟踪是Web程序中常用的技术,用来跟踪用户的整个会话。常用的会话跟踪技术是Cookie与Session。
这里就需要了解一下HTTP机制,HTTP是无状态链接,下一次的连接不会关注上一场连接的状态,所以为了保证会话期间的联系,就需要进行状态跟踪。

cookie机制

Cookie可以弥补HTTP协议无状态的不足,帮助进行会话跟踪,标记用户身份。在Session出现之前,基本上所有的网站都采用Cookie来跟踪会话。

由于HTTP是一种无状态的协议,服务器单从网络连接上无从知道客户身份。怎么办呢????????

客户端向服务器发送请求(第一次登陆),服务器需要使用response向浏览器颁发一个Cookie,注意,这个cookie是服务器生成的,标识的是session的ID。浏览器会把Cookie保存起来,然后每次访问就把cookie放在请求头里面,这样就可以匹配到相应的会话session。

服务器端向客户端发送Cookie是通过HTTP响应报文实现的,在Set-Cookie中设置需要像客户端发送的cookie:

Set-Cookie: “name=value;domain=.domain.com;path=/;expires=Sat, 11 Jun 2016 11:29:42 GMT;HttpOnly;secure”

上面是服务器进行cookie设置,对于前端没有深刻的体验。

举个🌰: 以Cookie帮助记住用户名这个
在我的项目中,需要在登陆页面记住用户名密码,因此我就在cookie中需要存储用户名密码,并且设置停留时间:

exdate.setTime(exdate.getTime() + 24 * 60 * 60 * 1000 * exdays);      //保存的天数
window.document.cookie =
    "User_Name" + "=" + c_name + ";path=/;expires=" + exdate.toGMTString();

下面来一个字段一个字段的分析:

name: 一个唯一确定的cookie名称(例如User_Name、Password)

value:存储在cookie中的字符串值 

domain:Cookie对于哪个域是有效的,也就是允许Cookie跨域的一级域名

path: 表示这个Cookie影响到的路径,浏览器跟会根据这项配置,像指定域中匹配的路径发送Cookie

expires:失效时间,表示cookie何时应该被删除的时间戳。如果不设置这个时间戳,浏览器会在页面关闭时即将删除所有cookie;这个值是GMT时间格式

max-age: 与expires作用相同,用来告诉浏览器此cookie多久过期(单位是秒),而不是一个固定的时间点。正常情况下,max-age的优先级高于expires

HttpOnly: 告知浏览器不允许通过脚本document.cookie去更改这个值,这个可以用来帮助cookie防XSS攻击,同样这个值在document.cookie中也不可见。但在http请求张仍然会携带这个cookie。注意这个值虽然在脚本中不可获取,但仍然在浏览器安装目录中以文件形式存在。这项设置通常在服务器端设置

secure: 安全标志,指定后,只有在使用SSL链接时候才能发送到服务器,如果是http链接则不会传递该信息。就算设置了secure 属性也并不代表他人不能看到你机器本地保存的 cookie 信息,所以不要把重要信息放cookie就对了

当浏览器再请求该网站时,浏览器把请求的网址连同该Cookie一同提交给服务器。
在这里插入图片描述

Session

Session是服务器端使用的一种记录客户端状态的机制,使用上比Cookie简单一些,相应的也增加了服务器的存储压力。

如果说Cookie机制是通过检查客户身上的“通行证”来确定客户身份的话,那么Session机制就是通过检查服务器上的“客户明细表”来确认客户身份。Session相当于程序在服务器上建立的一份客户档案,客户来访的时候只需要查询客户档案表就可以了,同时session的ID就是cookie进行匹配,同时session的自动注销时间tomcat是20分钟,不过时间可以服务器自行定义。

cookie和session的区别

1、cookie数据存放在客户的浏览器上,session数据放在服务器上
2.    cookie不是很安全,别人可以分析存放在本地的COOKIE并进行COOKIE欺骗;考虑到安全应当使用session
3. session会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能考虑到减轻服务器性能方面,应当使用COOKIE
4. 单个cookie保存的数据不能超过4K,很多浏览器都限制一个站点最多保存20个cookie。

cookie安全防护

cookie里面存储着当前用户与服务器会话信息,包括用户ID,会话标识符(session-id),域,路径,安全属性(true/false)等。Cookie通常被用来让服务器追踪用户状态,很容易被攻击,所以需要进行保护。

CSRF攻击

CSRF:Cross-site request forgery 跨站请求伪造

攻击者盗用了用户的身份,以用户的名义发送了恶意请求。

举个🌰:

用户登录了一个网站A后,获取了A网站生成的cookie,然后存在本地浏览器里面,然后没有登出的情况下,访问了其他的网站B,B网站有一个img标签,标签的src属性里面放置着A网站的请求信息,这时候用户浏览器就会解析页面,然后访问这个url,因为浏览器里面有A网站的cookie,这时候写在B网站的img的url请求就会生效,CSRF就产生了,这时候攻击者就可以以用户的名义操作这个数据库。

1、检查https头部的refer,查看访问域名、配置等信息是否一致(session中存储着会话信息)
2、用户每次登陆后,服务器会根据 用户名+密码+时间戳 创建一个加密字串,然后和cookie一起返回浏览器,客户端每次访问要在头部加上cookie和token进行验证。

XSS攻击

XSS:跨站脚本攻击

XSS的重点不在于跨站点,而在于脚本的执行。那么XSS的原理是:

恶意攻击者在web页面中会插入一些恶意的script代码。当用户浏览该页面的时候,那么嵌入到web页面中script代码会执行,因此会达到恶意攻击用户的目的攻击者通过注入恶意的脚本,在用户浏览网页的时候进行攻击,比如获取cookie,或者其他用户身份信息,可以分为存储型和反射型,存储型是攻击者输入一些数据并且存储到了数据库中,其他浏览者看到的时候进行攻击,反射型的话不存储在数据库中,往往表现为将攻击代码放在url地址的请求参数中。

防御的话为cookie设置httpOnly属性,这样子便不可以通过document.cookie 进行更改,对用户的输入进行检查,进行特殊字符过滤

缓存

缓存是一个到处都存在的用空间换时间的例子。通过使用多余的空间,我们能够获取更快的速度。
缓存主要包含两部分。

第一个是用户浏览器端的缓存,第二个是服务器端为了提高访问速度而加的CDN。

CDN缓存策略

所谓CDN缓存策略,便是客户端在访问服务器之前,会先去CDN缓存节点访问一下,是否有所需资源,并检查是否资源已过期,如果有且没有过期,那么这次的http请求就得到了响应,就完全不需要去服务器去请求了。

但是如果CDN节点不存在缓存或已经过期,那么CDN节点就会去请求服务器,然后服务器将资源给CDN,CDN再给客户端,此时CDN也就有了这个资源的缓存,并进行资源更新,下次访问就不需要去服务器了。
在这里插入图片描述

CDN的优点

为什么我们要使用CDN呢????????

1、如果一个服务器同时要处理多个客户端请求,那么服务器的速度就会下降,我们增加CDN内容分发,可以将资源放到不同的CDN上,尽可能帮助减轻服务器的压力
2、就近原则,如果客户端离服务器太远,那么可能会因为网络拥塞而造成请求缓慢,增加CDN,可以一定程度上减少网络拓扑

浏览器缓存

强缓存

1、Expires

Expires存在于http响应报文的header里面,表示该响应资源会在某一时刻过期,在过期之前,都不用需要向服务器发送请求了,可以直接使用。

这是http1.0时的规范;它的值为一个绝对时间的GMT格式的时间字符串,如Mon, 10 Jun 2015 21:31:12 GMT

2、cache-control:max-age

cache-control也是存在于http响应报文的header里面,但是相对于Expires每次都会有一个具体的年月日比较复杂,max-age标签就相对于简单了,表示从当前时间算起,多少秒后失效,就不需要计算失效时间,直接告诉有效存在时间。

这是http1.1时出现的header信息,主要是利用该字段的max-age值来进行判断,它是一个相对值。

协商缓存

上面的两种叫做强缓存,意思是失效之前就不要访问服务器啦,直接拿浏览器的缓存就可以了;但是当强缓存失效后,其实还有一种可能,就是资源虽然经常变,但是刚好这次没有变,但是因为强缓存失效了,不能直接用,就需要问问浏览器资源改写了吗,没改写我就先用着浏览器的缓存。

1、Etag/If-None-Match

根据协商缓存的策略,那么首先就需要跟服务器确认一下资源更改了没有,怎么确认呢,这就是Etag标签的作用了。

Etag是一个标签,它表示资源当前状态,它是一串很长的字符串,然后每当资源更改,它就会自动进行更新,编程一个新的。

Etag存在于http响应报文的header里面,表示当前资源的更改状态。

那么只需要客户端向服务器发送一个请求,header里面加上If-None-Match标签,标签现实的是Etag,然后和服务器的Etag比较一下,就知道资源有没有改写了。

2、Last-Modified/If-Modified-Since

Last-Modified 指的是上次资源更改的时间,她也是存在于http响应报文的header里面,它的格式和Expires是一样的,一个准确的时间戳。不过一般进行协商缓存确认资源的时候还是先用Etag,然后再比较Last-Modified。

那为什么有了Last-Modified还会增加Etag呢??????????????????

这是因为Last-Modified记录的是上次文件更改的时间,但是文件更改过并不代表文件的真实内容变了;Etag表示文件资源当前状态标识,只有当文件真正改变了,Etag才会改变,所以回先判断Etag。

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值