网络全部总结

      最后更新:2022-01-26 08:10

      1. 说说HTTP常用的状态码及其含义?

      不管是不是面试需要,我们都要知道,日常开发中的这几个状态码的含义哈:

      请添加图片描述

      2. HTTP 常用的请求方式,区别和用途?

      请添加图片描述

      3. 请简单说一下你了解的端口及对应的服务?

      请添加图片描述

      4. 说下计算机网络体系结构

      思路:这道题主要考察候选人,计算机网络体系结构这个基础知识点。计算机网路体系结构呢,有三层:OSI七层模型、TCP/IP四层模型、五层体系结构。大家可以记住这个图,如下

      请添加图片描述

      4.1 ISO七层模型

      ISO七层模型是国际标准化组织(International Organization for Standardization)制定的一个用于计算机或通信系统间互联的标准体系。

      • 应用层:网络服务与最终用户的一个接口,常见的协议有:HTTP FTP SMTP SNMP DNS。
      • 表示层:数据的表示、安全、压缩。确保一个系统的应用层所发送的信息可以被另一个系统的应用层读取。
      • 会话层:建立、管理、终止会话,对应主机进程,指本地主机与远程主机正在进行的会话。
      • 传输层:定义传输数据的协议端口号,以及流控和差错校验,协议有TCP UDP。
      • 网络层:进行逻辑地址寻址,实现不同网络之间的路径选择,协议有ICMP IGMP IP等。
      • 数据链路层:在物理层提供比特流服务的基础上,建立相邻结点之间的数据链路。
      • 物理层:建立、维护、断开物理连接。

      4.2 TCP/IP 四层模型

      • 应用层:对应于OSI参考模型的(应用层、表示层、会话层)。
      • 传输层:对应OSI的传输层,为应用层实体提供端到端的通信功能,保证了数据包的顺序传送及数据的完整性。
      • 网际层:对应于OSI参考模型的网络层,主要解决主机到主机的通信问题。
      • 网络接口层:与OSI参考模型的数据链路层、物理层对应。

      4.3 五层体系结构

      • 应用层:对应于OSI参考模型的(应用层、表示层、会话层)。
      • 传输层:对应OSI参考模型的的传输层
      • 网络层:对应OSI参考模型的的网络层
      • 数据链路层:对应OSI参考模型的的数据链路层
      • 物理层:对应OSI参考模型的的物理层。

      5 如何理解HTTP协议是无状态的

      如何理解无状态这个词呢?

      当浏览器第一次发送请求给服务器时,服务器响应了;如果同个浏览器发起第二次请求给服务器时,它还是会响应,但是呢,服务器不知道你就是刚才的那个浏览器。简言之,服务器不会去记住你是谁,所以是无状态协议。

      可以通过一个生活中的例子,来更好理解并记住它:

      有状态场景:

      • 小红:今天吃啥子?
      • 小明:罗非鱼~
      • 小红:味道怎么样呀?
      • 小明:还不错,好香。

      无状态的场景:

      • 小红:今天吃啥子?
      • 小明:罗非鱼~
      • 小红:味道怎么样呀?
      • 小明:?啊?你说啥?什么鬼?什么味道怎么样?

      Http加了Cookie的话:

      • 小红:今天吃啥子?
      • 小明:罗非鱼~
      • 小红:你今天吃的罗非鱼,味道怎么样呀?
      • 小明:还不错,好香。

      6.从浏览器地址栏输入url到显示主页的过程

      HTTP的请求过程,DNS解析,TCP三次握手,四次挥手这几个要点,我们都可以讲下。

      1. DNS解析,查找域名对应的IP地址。
      2. 与服务器通过三次握手,建立TCP连接
      3. 向服务器发送HTTP请求
      4. 服务器处理请求,返回网页内容
      5. 浏览器解析并渲染页面
      6. TCP四次挥手,连接结束
        请添加图片描述

      7. 说下HTTP/1.0,1.1,2.0的区别

      HTTP/1.0默认是短连接,可以强制开启,HTTP/1.1默认长连接,HTTP/2.0采用多路复用。

      HTTP/1.0

      • 默认使用短连接,每次请求都需要建立一个TCP连接。它可以设置Connection: keep-alive这个字段,强制开启长连接。

      HTTP/1.1

      • 引入了持久连接(Persistent Connection),即TCP连接默认不关闭,可以被多个请求复用,使用Connection:close关闭。下图是1.1与1.0连接的区别。
        在这里插入图片描述
      • HTTP1/1.1的缺点是必须等下上一个请求接受才能发起下一个请求,所以会收到前面请求的阻塞。 因为请求响应的顺序必须和请求发送的顺序一致,如果中间有某个响应花了很长的时间,后面的响应就算已经完成了也要排队等阻塞的请求返回,这就是线头阻塞。
      • 分块传输编码(Chunked transfer encoding):将响应主体分成若干块,并在每一块前面加上该块数据的长度以及回车换行,这样Recipient(如浏览器)就可以根据这个长度值正确接收每一块数据,最后以一个0长度的分块作为消息体的结束标志。采用该传输方式Sender在开始传输响应内容到Recipient前不需要知道内容的长度。
        例:如要发送的内容(消息体)为:123456789那么消息体的格式为:
        9<CR><LF>
        123456789<CR><LF>
        0<CR><LF>
        好处:
        1、不需要缓存数据,由于在服务器发送数据到Recipient前不需要知道数据的字节长度,所以可以动态产生响应内容而不用先将所有数据进行缓存。
        2、分块传输编码允许服务器在最后发送消息头字段。对于那些头字段值在内容被生成之前无法知道的情形非常重要,例如消息的内容要使用散列进行签名,散列的结果通过HTTP消息头字段进行传输。没有分块传输编码时,服务器必须缓冲内容直到完成后计算头字段的值并在发送内容前发送这些头字段的值。
        3、HTTP服务器有时使用压缩(gzip或deflate)以缩短传输花费的时间。分块传输编码可以用来分隔压缩对象的多个部分。在这种情况下,块不是分别压缩的,而是整个负载进行压缩,压缩的输出使用本文描述的方案进行分块传输。在压缩的情形中,分块编码有利于一边进行压缩一边发送数据,而不是先完成压缩过程以得知压缩后数据的大小。
      • 管道机制,即在同一个TCP连接里面,客户端可以同时发送多个请求。在这里插入图片描述

      HTTP/2.0

      • 二进制协议,1.1版本的头信息是文本(ASCII编码),数据体可以是文本或者二进制;2.0中,头信息和数据体都是二进制。
      • 完全多路复用,在一个连接里,客户端和浏览器都可以同时发送多个请求或回应,而且不用按照顺序一一对应。 每一个TCP连接中承载了多个双向流通的流,每一个流都有一个独一无二的标识和优先级,而流就是由二进制帧组成的。二进制帧的头部信息会标识自己属于哪一个流,所以这些帧是可以交错传输,然后在接收端通过帧头的信息组装成完整的数据。这样就解决了线头阻塞的问题,同时也提高了网络速度的利用率。
      • 报头压缩,HTTP协议不带有状态,每次请求都必须附上所有信息。Http/2.0引入了头信息压缩机制,使用gzip或compress压缩后再发送。
      • 服务端推送,允许服务器未经请求,主动向客户端发送资源。

      8 POST和GET有哪些区别?

      请添加图片描述
      GET和POST本质上没有区别 ,GET/POST都是TCP链接。GET和POST能做的事情是一样一样的。你要给GET加上request body,给POST带上url参数,技术上是完全行的通的。

      悖论:GET产生一个TCP数据包;POST产生两个TCP数据包。

      对于GET方式的请求,浏览器会把http header和data一并发送出去,服务器响应200(返回数据);

      而对于POST,浏览器先发送header,服务器响应100 continue,浏览器再发送data,服务器响应200 ok(返回数据)。

      也就是说,GET只需要汽车跑一趟就把货送到了,而POST得跑两趟,第一趟,先去和服务器打个招呼“嗨,我等下要送一批货来,你们打开门迎接我”,然后再回头把货送过去。

      因为POST需要两步,时间上消耗的要多一点,看起来GET比POST更有效。因此Yahoo团队有推荐用GET替换POST来优化网站性能。但这是一个坑!跳入需谨慎。为什么?

      1. GET与POST都有自己的语义,不能随便混用。
      2. 据研究,在网络环境好的情况下,发一次包的时间和发两次包的时间差别基本可以无视。而在网络环境差的情况下,两次包的TCP在验证数据包完整性上,有非常大的优点。
      3. 并不是所有浏览器都会在POST中发送两次包,Firefox就只发送一次。
        大多数http post请求,都是一个tcp包发出去的,也就是不存在所谓的先发一个头,然后发body的。
        大多数框架都是尽量在一个tcp包里面把HTTP请求发出去的,但是也确实存在先发HTTP头,然后发body的框架。但是具体发多少个TCP包,这个是代码的问题,是tcp协议栈的问题,跟HTTP没关系。

      9. 在交互过程中如果数据传送完了,还不想断开连接怎么办,怎么维持?

      在HTTP中响应体的Connection字段指定为keep-alive即可

      10. HTTP 如何实现长连接?在什么时候会超时?

      HTTP的长连接实质是指TCP的长连接。至于什么时候超时,我们记住这几个参数如tcp_keepalive_time、tcp_keepalive_probes就好啦

      什么是HTTP的长连接?

      1. HTTP分为长连接和短连接,本质上说的是TCP的长短连接。TCP连接是一个双向的通道,它是可以保持一段时间不关闭的,因此TCP连接才具有真正的长连接和短连接这一说法哈。
      2. TCP长连接可以复用一个TCP连接,来发起多次的HTTP请求,这样就可以减少资源消耗,比如一次请求HTML,如果是短连接的话,可能还需要请求后续的JS/CSS。

      如何设置长连接?

      通过在头部(请求和响应头)设置Connection字段指定为keep-alive,HTTP/1.0协议支持,但是是默认关闭的,从HTTP/1.1以后,连接默认都是长连接。

      在什么时候会超时呢?

      • HTTP一般会有httpd守护进程,里面可以设置keep-alive timeout,当tcp连接闲置超过这个时间就会关闭,也可以在HTTP的header里面设置超时时间。
      • TCP 的keep-alive包含三个参数,支持在系统内核的net.ipv4里面设置;当 TCP 连接之后,闲置了tcp_keepalive_time,则会发生侦测包,如果没有收到对方的ACK,那么会每隔 tcp_keepalive_intvl再发一次,直到发送了tcp_keepalive_probes,就会丢弃该连接。

      11. HTTP 与 HTTPS 的区别。

      可以从安全性、数据是否加密、默认端口等这几个方面去回答

      我的答案如下:

      HTTP,即超文本传输协议,是一个基于TCP/IP通信协议来传递明文数据的协议。HTTP会存在这几个问题:

      • 请求信息是明文传输,容易被窃听截取。
      • 没有验证对方身份,存在被冒充的风险
      • 数据的完整性未校验,容易被中间人篡改

      为了解决Http存在的问题,Https出现啦。

      HTTPS= HTTP+SSL/TLS,可以理解Https是身披SSL(Secure Socket Layer,安全套接层)的HTTP。它们主要区别如下:

      请添加图片描述

      12 . Https流程是怎样的?

      公私钥、数字证书、加密、对称加密、非对称加密。

      • HTTPS = HTTP + SSL/TLS,也就是用SSL/TLS对数据进行加密和解密,Http进行传输。
      • SSL,即Secure Sockets Layer(安全套接层协议),是网络通信提供安全及数据完整性的一种安全协议。
      • TLS,即Transport Layer Security(安全传输层协议),它是SSL3.0的后续版本。

      请添加图片描述

      Https工作流程

      1. 客户端发起Https请求,连接到服务器的443端口。
      2. 服务器必须要有一套数字证书(证书内容有公钥、证书颁发机构、失效日期等)。
      3. 服务器将自己的数字证书发送给客户端(公钥在证书里面,私钥由服务器持有)。
      4. 客户端收到数字证书之后,会验证证书的合法性。如果证书验证通过,就会生成一个随机的对称密钥,用服务器证书的公钥加密。
      5. 客户端将公钥加密后的密钥发送到服务器。
      6. 服务器接收到客户端发来的密文密钥之后,用自己之前保留的私钥对其进行非对称解密,解密之后就得到客户端的密钥,然后用客户端密钥对返回数据进行对称加密,传输的数据都是密文啦。
      7. 服务器将加密后的密文返回到客户端。
      8. 客户端收到后,用自己的密钥对其进行对称解密,得到服务器返回的数据。

      13. 说说HTTP的状态码,301和302的区别?

      302和301都有重定向的含义,但是它们也是有区别的。

      • 301:(永久性转移)请求的网页已被永久移动到新位置。服务器返回此响应时,会自动将请求者转到新位置。
      • 302:(暂时性转移)服务器目前正从不同位置的网页响应请求,但请求者应继续使用原有位置来进行以后的请求。此代码与响应GET和HEAD请求的301代码类似,会自动将请求者转到不同的位置。

      网上有个很形象的例子比喻:

      当一个网站或者网页24—48小时内临时移动到一个新的位置,这时候就要进行302跳转,打个比方说,我有一套房子,但是最近走亲戚去亲戚家住了,过两天我还回来的。而使用301跳转的场景就是之前的网站因为某种原因需要移除掉,然后要到新的地址访问,是永久性的,就比如你的那套房子其实是租的,现在租期到了,你又在另一个地方找到了房子,之前租的房子不住了。

      14. 说说什么是数字签名?什么是数字证书?

      数字证书是指在互联网通讯中标志通讯各方身份信息的一个数字认证,人们可以在网上用它来识别对方的身份。它的出现,是为了避免身份被篡改冒充的。比如Https的数字证书,就是为了避免公钥被中间人冒充篡改:

      数字证书构成

      • 公钥和个人等信息,经过Hash摘要算法加密,形成消息摘要;将消息摘要拿到拥有公信力的认证中心(CA),用它的私钥对消息摘要签名,形成数字签名。
      • 公钥和个人信息、数字签名共同构成数字证书。

      15. 对称加密与非对称加密有什么区别

      对称加密:指加密和解密使用同一密钥,优点是运算速度较快,缺点是密钥分发。常见的对称加密算法有:DES、AES等。

      非对称加密:指的是加密和解密使用不同的密钥(即公钥和私钥)。公钥与私钥是成对存在的,如果用公钥对数据进行加密,只有对应的私钥才能解密。常见的非对称加密算法有RSA ECC。

      16. 说说DNS的解析过程?

      DNS,英文全称是domain name system,域名解析系统,是Internet上作为域名和IP相互映射的一个分布式数据库。它的作用很明确,就是可以根据域名查出对应的IP地址。在浏览器缓存、本地DNS服务器、根域名服务器都是怎么查找的,大家回答的时候都可以说下哈。

      DNS的解析过程如下图:

      请添加图片描述

      假设你要查询www.baidu.com的IP地址:

      • 首先会查找浏览器的缓存,看看是否能找到www.baidu.com对应的IP地址,找到就直接返回;否则进行下一步。
      • 将请求发往给本地DNS服务器,如果查找到也直接返回,否则继续进行下一步;
      • 本地DNS服务器向根域名服务器发送请求,根域名服务器返回负责.com的顶级域名服务器的IP地址的列表。
      • 本地DNS服务器再向其中一个负责.com的顶级域名服务器发送一个请求,返回负责.baidu的权威域名服务器的IP地址列表。
      • 本地DNS服务器再向其中一个权威域名服务器发送一个请求,返回www.baidu.com所对应的IP地址。

      17. 什么是CSRF攻击,如何避免

      什么是CSRF 攻击?

      CSRF,跨站请求伪造(英文全称是Cross-site request forgery),是一种挟制用户在当前已登录的Web应用程序上执行非本意的操作的攻击方法。

      CSRF是如何攻击的呢?

      来看一个来自百度百科的例子哈:

      请添加图片描述

      1. Tom 登陆银行,没有退出,浏览器包含了Tom在银行的身份认证信息。
      2. 黑客Jerry将伪造的转账请求,包含在帖子
      3. Tom在银行网站保持登陆的情况下,浏览帖子
      4. 黑客将伪造的转账请求连同身份认证信息,发送到银行网站
      5. 银行网站看到身份认证信息,以为就是Tom的合法操作,最后造成Tom资金损失。

      CSRF攻击过程的受害者用户登录网站A,输入个人信息,在本地保存服务器生成的cookie。攻击者构建一条恶意链接,例如对受害者在网站A的信息及状态进行操作,典型的例子就是转账。受害者打开了攻击者构建的网页B,浏览器发出该恶意连接的请求,浏览器发起会话的过程中发送本地保存的cookie到网址A,A网站收到cookie,以为此链接是受害者发出的操作,导致受害者的身份被盗用,完成攻击者恶意的目的。

      怎么解决CSRF攻击呢?

      对于CSRF攻击,我们可以做如下防范:

      (1) 验证码。应用程序和用户进行交互过程中,特别是账户交易这种核心步骤,强制用户输入验证码,才能完成最终请求。在通常情况下,验证码够很好地遏制CSRF攻击。但增加验证码降低了用户的体验,网站不能给所有的操作都加上验证码。所以只能将验证码作为一种辅助手段,在关键业务点设置验证码。

      (2) Referer Check。HTTP Referer是header的一部分,当浏览器向web服务器发送请求时,一般会带上Referer信息告诉服务器是从哪个页面链接过来的,服务器籍此可以获得一些信息用于处理。可以通过检查请求的来源来防御CSRF攻击。正常请求的referer具有一定规律,如在提交表单的referer必定是在该页面发起的请求。所以通过检查http包头referer的值是不是这个页面,来判断是不是CSRF攻击。**但在某些情况下如从https跳转到http,浏览器处于安全考虑,不会发送referer,服务器就无法进行check了。**若与该网站同域的其他网站有XSS漏洞,那么攻击者可以在其他网站注入恶意脚本,受害者进入了此类同域的网址,也会遭受攻击。出于以上原因,无法完全依赖Referer Check作为防御CSRF的主要手段。但是可以通过Referer Check来监控CSRF攻击的发生。

      (3) Anti CSRF Token。目前比较完善的解决方案是加入Anti-CSRF-Token,即发送请求时在HTTP 请求中以参数的形式加入一个随机产生的token,并在服务器建立一个拦截器来验证这个token。

      18. 聊聊五层计算机网络体系结构中,每一层对应的网络协议有哪些?

      请添加图片描述

      19.说说 WebSocket与socket的区别

      • Socket其实就是等于IP地址 + 端口 + 协议。 网络中的 Socket 并不是什么协议,而是为了使用 TCP,UDP 而抽象出来的一层 API,它是位于应用层和传输层之间的一个抽象层。具体来说,Socket是一套标准,它完成了对TCP/IP的高度封装,屏蔽网络细节,以方便开发者更好地进行网络编程。

      • 在这里插入图片描述在这里插入图片描述
        Socket编程:服务器端先初始化Socket,然后与端口绑定(bind),对端口进行监听(listen),调用accept阻塞,等待客户端连接。在这时如果有个客户端初始化一个Socket,然后连接服务器(connect),如果连接成功,这时客户端与服务器端的连接就建立了。客户端发送数据请求,服务器端接收请求并处理请求,然后把回应数据发送给客户端,客户端读取数据,最后关闭连接,一次交互结束。
        详见: Socket原理详解

      • WebSocket,即 Web 浏览器与 Web 服务器之间全双工通信标准。WebSocket与HTTP一样,都属于应用层协议。我们已经有了 HTTP 协议,为什么还需要另一个协议?它能带来什么好处?答案很简单,因为 HTTP 协议有一个缺陷:通信只能由客户端发起。举例来说,我们想了解今天的天气,只能是客户端向服务器发出请求,服务器返回查询结果。HTTP 协议做不到服务器主动向客户端推送信息。WebSocket的最大特点就是,服务器可以主动向客户端推送信息,客户端也可以主动向服务器发送信息,是真正的双向平等对话。**客户端与服务器之间只需完成一次握手,两者之间就可以创建持久性的连接,并进行双向数据传输。**由于是建立在 HTTP 基础上的协议,因此连接的发起方仍是客户端,而一旦确立 WebSocket 通信连接,不论服务器还是客户端,任意一方都可直接向对方发送报文。

        WebSocket 是长轮询。具体比如在一个电商场景,商品的库存可能会变化,所以需要及时反映给用户,所以客户端会不停的发请求,然后服务器端会不停的去查变化,不管变不变,都返回,这个是短轮询。而长轮询则表现为如果没有变,就不返回,而是等待变或者超时(一般是十几秒)才返回,如果没有返回,客户端也不需要一直发请求,所以减少了双方的压力。

      • Socket 是传输控制层的接口。用户可以通过 Socket 来操作底层 TCP/IP 协议族通信。 Socket一个是网编编程的标准接口,而WebSocket则是应用层通信协议。 Socket 更灵活,更底层

      20. 什么是DoS、DDoS、DRDoS攻击?

      • DOS: (Denial of Service),翻译过来就是拒绝服务,一切能引起DOS行为的攻击都被称为DOS攻击。最常见的DoS攻击就有计算机网络宽带攻击、连通性攻击。
      • DDoS: (Distributed Denial of Service),翻译过来是分布式拒绝服务。是指处于不同位置的多个攻击者同时向一个或几个目标发动攻击,或者一个攻击者控制了位于不同位置的多台机器并利用这些机器对受害者同时实施攻击。常见的DDos有SYN Flood、Ping of Death、ACK Flood、UDP Flood等。
      • DRDoS: (Distributed Reflection Denial of Service),中文是分布式反射拒绝服务,该方式靠的是发送大量带有被害者IP地址的数据包给攻击主机,然后攻击主机对IP地址源做出大量回应,从而形成拒绝服务攻击。

      21. 什么是XSS攻击,如何避免?

      XSS,叫跨站脚本攻击(Cross-Site Scripting),因此有人将跨站脚本攻击缩写为XSS。它指的是恶意攻击者往Web页面里插入恶意html代码,当用户浏览该页之时,嵌入其中Web里面的html代码会被执行,从而达到恶意攻击用户的特殊目的。导致用户安全信息泄露(获取用户的敏感信息),危害数据安全。例如盗取各类用户帐号、网站挂马、盗窃企业重要信息等。

      XSS主要分为两大类:非持久型攻击、持久型攻击。

      • 非持久型攻击(反射型XSS, DOM-based 型):经过后端,不经过数据库;
      • 持久型攻击(存储型XSS):经过后端,经过数据库。

      常见的 XSS 攻击有三种:反射型、DOM-based 型、存储型。

      持久型攻击 存储型XSS

      2.非持久型攻击

      (1)反射性XSS

      (2)DOM-based 型

      21.1 XSS是如何攻击的呢?

      拿反射型举个例子吧,流程图如下:

      请添加图片描述

      21.2 如何解决XSS攻击问题?

      xss漏洞在web站点运用中是最为常见的漏洞之一,XSS会以各种方式执行恶意的代码来破坏用户使用的站点。我们能够修补XSS漏洞,但是我们也不能100%的肯定没有人可以打破我们的过滤机制。恶意的攻击者总能够找到办法,绕过我们的过滤机制,从而进行恶意代码的执行。

      • 对输入进行过滤,过滤标签等,只允许合法值。
      • HTML转义
      • 对于链接跳转,如` 等,要校验内容,禁止以script开头的非法链接。
      • 限制输入长度

      22. Http请求的过程与原理

      HTTP是一个基于TCP/IP协议来传递数据的超文本传输协议,传输的数据类型有HTML,图片等。以访问百度为例子,看下一次Http的请求过程吧

      Http请求过程

      1. 客户端进行DNS域名解析,得到对应的IP地址
      2. 根据这个IP,找到对应的服务器建立连接(三次握手)
      3. 建立TCP连接后发起HTTP请求(一个完整的http请求报文)
      4. 服务器响应HTTP请求,客户端得到html代码
      5. 客户端解析html代码,用html代码中的资源(如js,css,图片等等)渲染页面。
      6. 服务器关闭TCP连接(四次挥手)

      23. forward和redirect的区别?

      forward是转发,redirect是重定向。

      我的答案如下:

      • 直接转发方式(Forward),客户端和浏览器只发出一次请求,Servlet、HTML、JSP或其它信息资源,由第二个信息资源响应该请求,在请求对象request中,保存的对象对于每个信息资源是共享的。 forword是服务器内部的重定向,服务器直接访问目标地址的 url网址,把里面的东西读取出来,但是客户端并不知道,因此用forward的话,客户端浏览器的网址是不会发生变化的。
      • 间接转发方式(Redirect)实际是两次HTTP请求,服务器端在响应第一次请求的时候,让浏览器再向另外一个URL发出请求,从而达到转发的目的。 redirect是服务器根据逻辑,发送一个状态码,告诉浏览器重新去请求那个地址,所以地址栏显示的是新的地址。
      • 直接转发就相当于:“A找B借钱,B说没有,B去找C借,借到借不到都会把消息传递给A”;
      • 间接转发就相当于:“A找B借钱,B说没有,让A去找C借”。

      forword 一般用于用户登录的时候,根据角色转发到相应的模块,redirect一般用于用户注销登录时返回主页面或者跳转到其他网站

      forword效率高,而redirect效率低

      forword转发是服务器上的行为,而redirect重定向是客户端的行为

      24. 聊聊SQL注入?

      SQL注入是一种代码注入技术,一般被应用于攻击web应用程序。它通过在web应用接口传入一些特殊参数字符,来欺骗应用服务器,执行恶意的SQL命令,以达到非法获取系统信息的目的。它目前是黑客对数据库进行攻击的最常用手段之一。

      24.1 SQL注入是如何攻击的?

      举个常见的业务场景:在web表单搜索框输入员工名字,然后后台查询出对应名字的员工。这种场景下,一般都是前端页面,把一个名字参数name传到后台,然后后台通过SQL把结果查询出来

      因为SQL是直接拼接的,如果我们完全信任前端传的参数的话。假如前端传这么一个参数时'' or '1'='1',SQL就变成

      这个SQL会把所有的员工信息全都查出来了,请求用户已经越权啦。请求者可以获取所有员工的信息,信息已经暴露。
      Java解决SQL注入问题

      24.2 如何预防SQL注入问题

      1). 不要暴露一些不必要的日志或者安全信息,比如避免直接响应一些sql异常信息。

      如果SQL发生异常了,不要把这些信息暴露响应给用户,可以自定义异常进行响应

      2). 不相信任何外部输入参数,过滤参数中含有的一些数据库关键词关键词

      可以加个参数校验过滤的方法,过滤union,or等数据库关键词

      3). 适当的权限控制

      在你查询信息时,先校验下当前用户是否有这个权限。比如说,实现代码的时候,可以让用户多传一个企业Id什么的,或者获取当前用户的session信息等,在查询前,先校验一下当前用户是否是这个企业下的等等,是的话才有这个查询员工的权限。

      25. Session和Cookie的区别。

      我们先来看Session和Cookie的概念吧:

      • Cookie实际上是一小段的文本信息。客户端请求服务器,如果服务器需要记录该用户状态,就使用response向客户端浏览器颁发一个Cookie。客户端浏览器会把Cookie保存起来。当浏览器再请求该网站时,浏览器把请求的网址连同该Cookie一同提交给服务器。服务器检查该Cookie,以此来辨认用户状态。服务器还可以根据需要修改Cookie的内容。
      • Session是另一种记录客户状态的机制,不同的是Cookie保存在客户端浏览器中,而Session保存在服务器上。客户端浏览器访问服务器的时候,服务器把客户端信息以某种形式记录在服务器上。这就是Session,向用户返回session id。客户端浏览器再次访问时只需要从该Session中查找该客户的状态就可以了。

      Session 和Cookie的区别主要有这些:

      请添加图片描述
      Session、Cookie、Token的联系
      来看个图吧:

      请添加图片描述

      • 用户第一次请求服务器时,服务器根据用户提交的信息,创建对应的Session,请求返回时将此Session的唯一标识信息SessionID返回给浏览器,浏览器接收到服务器返回的SessionID信息后,会将此信息存入Cookie中,同时Cookie记录此SessionID是属于哪个域名。
      • 当用户第二次访问服务器时,请求会自动判断此域名下是否存在Cookie信息,如果存在,则自动将Cookie信息也发送给服务端,服务端会从Cookie中获取SessionID,再根据 SessionID查找对应的 Session信息,如果没有找到,说明用户没有登录或者登录失效,如果找到Session证明用户已经登录可执行后面操作。

      26. IP地址有哪些分类?

      一般可以这么认为,IP地址 = 网络号+主机号。

      1. 网络号:它标志主机所连接的网络地址表示属于互联网的哪一个网络。
      2. 主机号:它标志主机地址表示其属于该网络中的哪一台主机。

      IP地址分为A,B,C,D,E五大类:

      • A类地址(1~126):以0开头,网络号占前8位,主机号占后面24位。
      • B类地址(128~191):以10开头,网络号占前16位,主机号占后面16位。
      • C类地址(192~223):以110开头,网络号占前24位,主机号占后面8位。
      • D类地址(224~239):以1110开头,保留位多播地址。
      • E类地址(240~255):以11110开头,保留位为将来使用

      请添加图片描述

      27. 说下ARP 协议的工作过程?

      ARP 协议协议,Address Resolution Protocol,地址解析协议,它是用于实现IP地址到MAC地址的映射。

      1. 首先,每台主机都会在自己的ARP缓冲区中建立一个ARP列表,以表示IP地址和MAC地址的对应关系。

        1. 当源主机需要将一个数据包要发送到目的主机时,会首先检查自己的ARP列表,是否存在该IP地址对应的MAC地址;如果有,就直接将数据包发送到这个MAC地址;如果没有,就向本地网段发起一个ARP请求的广播包,查询此目的主机对应的MAC地址。此ARP请求的数据包里,包括源主机的IP地址、硬件地址、以及目的主机的IP地址。
      2. 网络中所有的主机收到这个ARP请求后,会检查数据包中的目的IP是否和自己的IP地址一致。如果不相同,就会忽略此数据包;如果相同,该主机首先将发送端的MAC地址和IP地址添加到自己的ARP列表中,如果ARP表中已经存在该IP的信息,则将其覆盖,然后给源主机发送一个 ARP响应数据包,告诉对方自己是它需要查找的MAC地址。

        1. 源主机收到这个ARP响应数据包后,将得到的目的主机的IP地址和MAC地址添加到自己的ARP列表中,并利用此信息开始数据的传输。如果源主机一直没有收到ARP响应数据包,表示ARP查询失败。

      28. 有了IP地址,为什么还要用MAC地址?

      • 简而言之,标识网络中的一台计算机,比较常用的就是IP地址和MAC地址,但计算机的IP地址可由用户自行更改,管理起来就相对困难,而MAC地址不可更改,所以一般会把IP地址和MAC地址组合起来使用。
      • 那只使用MAC地址不用IP地址行不行呢?不行的!因为最早就是MAC地址先出现的,并且当时并不用IP地址,只用MAC地址,后来随着网络中的设备越来越多,整个路由过程越来越复杂,便出现了子网的概念。对于目的地址在其他子网的数据包,路由只需要将数据包送到那个子网即可。
      • 那为什么要用IP地址呢?是因为IP地址是和地域相关的,对于同一个子网上的设备,IP地址的前缀都是一样的,这样路由器通过IP地址的前缀就知道设备在在哪个子网上了,而只用MAC地址的话,路由器则需要记住每个MAC地址在哪个子网,这需要路由器有极大的存储空间,是无法实现的。
      • IP地址可以比作为地址,MAC地址为收件人,在一次通信过程中,两者是缺一不可的。

      29. TCP 和 UDP 分别对应的常见应用层协议有哪些?

      基于TCP的应用层协议有:HTTP、FTP、SMTP、TELNET、SSH

      • HTTP:HyperText Transfer Protocol(超文本传输协议),默认端口80
      • FTP: File Transfer Protocol (文件传输协议), 默认端口(20用于传输数据,21用于传输控制信息)
      • SMTP: Simple Mail Transfer Protocol (简单邮件传输协议) ,默认端口25
      • TELNET: Teletype over the Network (网络电传), 默认端口23
      • SSH:Secure Shell(安全外壳协议),默认端口 22

      基于UDP的应用层协议:DNS、TFTP、SNMP

      • DNS: Domain Name Service (域名服务),默认端口 53
      • TFTP: Trivial File Transfer Protocol (简单文件传输协议),默认端口69
      • SNMP:Simple Network Management Protocol(简单网络管理协议),通过UDP端口161接收,只有Trap信息采用UDP端口162。

      30. 聊聊保活计时器的作用

      除时间等待计时器外,TCP 还有一个保活计时器(keepalive timer)。设想这样的场景:客户已主动与服务器建立了TCP连接。但后来客户端的主机突然发生故障。显然,服务器以后就不能再收到客户端发来的数据。因此,应当有措施使服务器不要再白白等待下去。这就需要使用保活计时器了。

      服务器每收到一次客户的数据,就重新设置保活计时器,时间的设置通常是两个小时。若两个小时都没有收到客户端的数据,服务端就发送一个探测报文段,以后则每隔 75秒钟发送一次。若连续发送10个探测报文段后仍然无客户端的响应,服务端就认为客户端出了故障,接着就关闭这个连接。

      31. 如果服务器出现了大量CLOSE_WAIT状态如何解决。

      我们先来复习下TCP的四次挥手

      请添加图片描述

      • 服务器端收到客户端发送的FIN后,TCP协议栈就会自动发送ACK,接着进入CLOSE_WAIT状态。
      • 但是如果服务器端不执行socket的close()操作,那么就没法进入LAST_ACK,导致大量连接处于CLOSE_WAIT状态
      • 所以,如果服务器出现了大量CLOSE_WAIT状态,一般是程序Bug,或者关闭socket不及时。 大量socket的fd被占用,这个是有上限的,超过了就不能接受新的连接了。

      32. URI和URL的区别

      • URI,全称是Uniform Resource Identifier),中文翻译是统一资源标志符,主要作用是唯一标识一个资源。
      • URL,全称是Uniform Resource Location),中文翻译是统一资源定位符,主要作用是提供资源的路径。
      • 打个经典比喻吧,URI像是身份证,可以唯一标识一个人,而URL更像一个住址,可以通过URL找到这个人。

      33. ICMP协议的功能

      ICMP,(Internet Control Message Protocol) ,Internet控制消息协议。

      • ICMP协议是一种面向无连接的协议,用于传输出错报告控制信息。
      • 它是一个非常重要的协议,它对于网络安全具有极其重要的意义。它属于网络层协议,主要用于在主机与路由器之间传递控制信息,包括报告错误、交换受限控制和状态信息等。
      • 当遇到IP数据无法访问目标、IP路由器无法按当前的传输速率转发数据包等情况时,会自动发送ICMP消息。

      比如我们日常使用得比较多的ping,就是基于ICMP的。

      34. 说下ping的原理

      ping,Packet Internet Groper,是一种因特网包探索器,用于测试网络连接量的程序。Ping是工作在TCP/IP网络体系结构中应用层的一个服务命令, 主要是向特定的目的主机发送ICMP(Internet Control Message Protocol 因特网报文控制协议) 请求报文,测试目的站是否可达及了解其有关状态

      一般来说,ping可以用来检测网络通不通。它是基于ICMP协议工作的。假设机器Aping机器B,工作过程如下:

      1. ping通知系统,新建一个固定格式的ICMP请求数据包
      2. ICMP协议,将该数据包和目标机器B的IP地址打包,一起转交给IP协议层
      3. IP层协议将本机IP地址为源地址,机器B的IP地址为目标地址,加上一些其他的控制信息,构建一个IP数据包
      4. 先获取目标机器B的MAC地址。
      5. 数据链路层构建一个数据帧,目的地址是IP层传过来的MAC地址,源地址是本机的MAC地址
      6. 机器B收到后,对比目标地址,和自己本机的MAC地址是否一致,符合就处理返回,不符合就丢弃。
      7. 根据目的主机返回的ICMP回送回答报文中的时间戳,从而计算出往返时间
      8. 最终显示结果有这几项:发送到目的主机的IP地址、发送 & 收到 & 丢失的分组数、往返时间的最小、最大& 平均值

      36. 请详细介绍一下TCP 的三次握手机制

      TCP提供可靠的连接服务,连接是通过三次握手进行初始化的。三次握手的目的就是同步连接双方的序列号和确认号并交换TCP窗口大小信息。我们一起来看下流程图哈:

      请添加图片描述

      • 第一次握手(SYN=1, seq=x),发送完毕后,客户端就进入SYN_SEND状态
      • 第二次握手(SYN=1, ACK=1, seq=y, ACKnum=x+1), 发送完毕后,服务器端就进入SYN_RCV状态。
      • 第三次握手(ACK=1,ACKnum=y+1),发送完毕后,客户端进入ESTABLISHED状态,当服务器端接收到这个包时,也进入ESTABLISHED状态。

      37. TCP握手为什么是三次,为什么不能是两次?不能是四次?

      思路:TCP握手为什么不能是两次,为什么不能是四次呢?为了方便理解,我们以男孩子和女孩子谈恋爱为例子:两个人能走到一起,最重要的事情就是相爱,就是我爱你,并且我知道,你也爱我,接下来我们以此来模拟三次握手的过程:

      请添加图片描述

      为什么握手不能是两次呢?

      如果只有两次握手,女孩子可能就不知道,她的那句我也爱你,男孩子是否收到,恋爱关系就不能愉快展开。无法确认客户端的接收能力。

      为什么握手不能是四次呢?

      因为握手不能是四次呢?因为三次已经够了,三次已经能让双方都知道:你爱我,我也爱你。而四次就多余了。四次以上都可以,只不过 三次就够了

      38. 说说TCP四次挥手过程

      请添加图片描述

      1. 第一次挥手(FIN=1,seq=u),发送完毕后,客户端进入FIN_WAIT_1状态。
      2. 第二次挥手(ACK=1,ack=u+1,seq =v),发送完毕后,服务器端进入CLOSE_WAIT状态,客户端接收到这个确认包之后,进入FIN_WAIT_2状态。
      3. 第三次挥手(FIN=1,ACK1,seq=w,ack=u+1),发送完毕后,服务器端进入LAST_ACK状态,等待来自客户端的最后一个ACK。
      4. 第四次挥手(ACK=1,seq=u+1,ack=w+1),客户端接收到来自服务器端的关闭请求,发送一个确认包,并进入TIME_WAIT状态,等待了某个固定时间(两个最大段生命周期,2MSL,2 Maximum Segment Lifetime)之后,没有收到服务器端的ACK ,认为服务器端已经正常关闭连接,于是自己也关闭连接,进入CLOSED状态。服务器端接收到这个确认包之后,关闭连接,进入CLOSED状态。

      39. TCP挥手为什么需要四次呢?

      思路:TCP挥手为什么需要四次呢?为了方便大家理解,再举个生活的例子吧。

      小明和小红打电话聊天,通话差不多要结束时,小红说,“我没啥要说的了”。小明回答,“我知道了”。但是小明可能还有要说的话,小红不能要求小明跟着她自己的节奏结束通话,于是小明可能又叽叽歪歪说了一通,最后小明说,“我说完了”,小红回答,“我知道了”,这样通话才算结束。

      如果是三次的话,那么服务端的 ACK 和 FIN 合成一个挥手,那么长时间的延迟可能让 TCP 以为FIN 没有达到服务器端,然后让客户端不断的重发 FIN 。

      40. TCP四次挥手过程中,为什么需要等待2MSL,才进入CLOSED关闭状态

      2MSL,two Maximum Segment Lifetime,即两个最大段生命周期。假设主动发起挥手的是客户端,那么需要2MSL的原因是:

      • 1.为了保证客户端发送的最后一个ACK报文段能够到达服务端。这个ACK报文段有可能丢失,处在LAST-ACK状态的服务端就收不到对已发送的FIN + ACK报文段的确认。服务端会超时重传这个FIN+ACK 报文段,而客户端就能在 2MSL 时间内(超时 + 1MSL 传输)收到这个重传的 FIN+ACK 报文段。接着客户端重传一次确认,重新启动2MSL计时器。最后,客户端和服务器都正常进入到CLOSED状态。
      • 2. 防止已失效的连接请求报文段出现在本连接中。客户端在发送完最后一个ACK报文段后,再经过时间2MSL,就可以使本连接持续的时间内所产生的所有报文段都从网络中消失。这样就可以使下一个连接中不会出现这种旧的连接请求报文段。

      41. TCP的粘包和拆包

      TCP是面向流,没有界限的一串数据。TCP底层并不了解上层业务数据的具体含义,它会根据TCP缓冲区的实际情况进行包的划分,所以在业务上认为,一个完整的包可能会被TCP拆分成多个包进行发送,也有可能把多个小的包封装成一个大的数据包发送,这就是所谓的TCP粘包和拆包问题。

      请添加图片描述

      为什么会产生粘包和拆包呢?

      • 要发送的数据小于TCP发送缓冲区的大小,TCP将多次写入缓冲区的数据一次发送出去,将会发生粘包;
      • 接收数据端的应用层没有及时读取接收缓冲区中的数据,将发生粘包;
      • 要发送的数据大于TCP发送缓冲区剩余空间大小,将会发生拆包;
      • 待发送数据大于MSS(最大报文长度),TCP在传输前将进行拆包。即TCP报文长度-TCP头部长度>MSS。

      解决方案:

      • 发送端将每个数据包封装为固定长度
      • 在数据尾部增加特殊字符进行分割
      • 将数据分为两部分,一部分是头部,一部分是内容体;其中头部结构大小固定,且有一个字段声明内容体的大小。

      42. 聊聊TCP的流量控制

      TCP三次握手,发送端和接收端进入到ESTABLISHED状态,它们即可以愉快地传输数据啦。但是发送端不能疯狂地向接收端发送数据,因为接收端接收不过来的话,接收方只能把处理不过来的数据存在缓存区里。如果缓存区都满了,发送方还在疯狂发送数据的话,接收方只能把收到的数据包丢掉,这就浪费了网络资源啦。

      TCP 提供一种机制可以让发送端根据接收端的实际接收能力控制发送的数据量,这就是流量控制。

      TCP通过滑动窗口来控制流量,我们看下流量控制的简要流程吧:

      首先双方三次握手,初始化各自的窗口大小,均为 400 个字节。

      请添加图片描述

      TCP的流量控制

      1. 假如当前发送方给接收方发送了200个字节,那么,发送方的SND.NXT会右移200个字节,也就是说当前的可用窗口减少了200 个字节。
      2. 接受方收到后,放到缓冲队列里面,REV.WND =400-200=200字节,所以win=200字节返回给发送方。接收方会在 ACK 的报文首部带上缩小后的滑动窗口200字节
      3. 发送方又发送200字节过来,200字节到达,继续放到缓冲队列。不过这时候,由于大量负载的原因,接受方处理不了这么多字节,只能处理100字节,剩余的100字节继续放到缓冲队列。这时候,REV.WND = 400-200-100=100字节,即win=100返回发送方。
      4. 发送方继续干活,发送100字节过来,这时候,接受窗口win变为0。
      5. 发送方停止发送,开启一个定时任务,每隔一段时间,就去询问接受方,直到win大于0,才继续开始发送。

      43. 说说半连接队列和 SYN Flood攻击的关系

      TCP进入三次握手前,服务端会从CLOSED状态变为LISTEN状态,同时在内部创建了两个队列:半连接队列(SYN队列)和全连接队列(ACCEPT队列)。

      什么是半连接队列(SYN队列)呢? 什么是全连接队列(ACCEPT队列)呢?回忆下TCP三次握手的图:

      请添加图片描述

      • TCP三次握手时,客户端发送SYN到服务端,服务端收到之后,便回复ACK和SYN,状态由LISTEN变为SYN_RCVD,此时这个连接就被推入了SYN队列,即半连接队列。
      • 当客户端回复ACK, 服务端接收后,三次握手就完成了。这时连接会等待被具体的应用取走,在被取走之前,它被推入ACCEPT队列,即全连接队列。

      SYN Flood是一种典型的DDos攻击,它在短时间内,伪造不存在的IP地址,向服务器大量发起SYN报文。当服务器回复SYN+ACK报文后,不会收到ACK回应报文,导致服务器上建立大量的半连接半连接队列满了,这就无法处理正常的TCP请求啦。

      那么有哪些方案应对呢?主要有syn cookie和SYN Proxy防火墙等。

      • syn cookie:在收到SYN包后,服务器根据一定的方法,以数据包的源地址、端口等信息为参数计算出一个cookie值作为自己的SYN ACK包的序列号,回复SYN+ACK后,服务器并不立即分配资源进行处理,等收到发送方的ACK包后,重新根据数据包的源地址、端口计算该包中的确认序列号是否正确,如果正确则建立连接,否则丢弃该包。
      • SYN Proxy防火墙:服务器防火墙会对收到的每一个SYN报文进行代理和回应,并保持半连接。等发送方将ACK包返回后,再重新构造SYN包发到服务器,建立真正的TCP连接。

      44. 聊聊TCP的滑动窗口

      TCP报文首部有个字段win控制窗口大小的,同时也需要掌握,滑动窗口是怎么滑的。TCP 发送一个数据,如果需要收到确认应答,才会发送下一个数据。这样的话就会有个缺点:效率会比较低。

      这就好像我们面对面在聊天,你说完一句,我应答之后,你才能说下一句。那么,如果我在忙其他事情,没有能够及时回复你呢?你说完一句后,要等到我忙完回复你,你才说下句,这显然不现实,效率太低。

      为了解决这个问题,TCP引入了窗口,它是操作系统开辟的一个缓存空间。窗口大小值表示无需等待确认应答,而可以继续发送数据的最大值。

      TCP头部有个字段叫win,它告诉对方本端的TCP接收缓冲区还能容纳多少字节的数据,这样对方就可以控制发送数据的速度,从而达到流量控制的目的。

      通俗点讲,就是接受方每次收到数据包,在发送确认报文的时候,同时告诉发送方,自己的缓存区还有多少空余空间,缓冲区的空余空间,我们就称之为接受窗口大小。这就是win。

      TCP 滑动窗口分为两种: 发送窗口和接收窗口。发送端的滑动窗口包含四大部分,如下:

      • 已发送且已收到ACK确认
      • 已发送但未收到ACK确认
      • 未发送但可以发送
      • 未发送也不可以发送

      请添加图片描述

      • 虚线矩形框,就是发送窗口。
      • SND.WND: 表示发送窗口的大小,上图虚线框的格子数是14个,即发送窗口大小是14。
      • SND.NXT:下一个发送的位置,它指向未发送但可以发送的第一个字节的序列号。
      • SND.UNA: 一个绝对指针,它指向的是已发送但未确认的第一个字节的序列号。

      接收方的滑动窗口包含三大部分,如下:

      • 已成功接收并确认
      • 未收到数据但可以接收
      • 未收到数据并不可以接收的数据

      请添加图片描述

      • 虚线矩形框,就是接收窗口。
      • REV.WND: 表示接收窗口的大小,上图虚线框的格子就是9个。
      • REV.NXT:下一个接收的位置,它指向未收到但可以接收的第一个字节的序列号。

      45. TCP的拥塞控制

      思路讲解:TCP拥塞机制也是个高频考点,需要掌握它跟流量控制的区别,也需要掌握拥塞控制的这几种算法:慢启动算法、拥塞避免、拥塞发生、快速恢复算法。

      拥塞控制是作用于网络的,防止过多的数据包注入到网络中,避免出现网络负载过大的情况。它的目标主要是最大化利用网络上瓶颈链路的带宽。它跟流量控制又有什么区别呢?

      流量控制是作用于接收者的,根据接收端的实际接收能力控制发送速度,防止分组丢失的。

      我们可以把网络链路比喻成一根水管,如果我们想最大化利用网络来传输数据,那就是尽快让水管达到最佳充满状态。

      请添加图片描述

      发送方维护一个拥塞窗口cwnd(congestion window)的变量,用来估算在一段时间内这条链路(水管)可以承载和运输的数据(水)的数量。它大小代表着网络的拥塞程度,并且是动态变化的,但是为了达到最大的传输效率,我们该如何知道这条水管的运送效率是多少呢?

      一个比较简单的方法就是不断增加传输的水量,直到水管快要爆裂为止(对应到网络上就是发生丢包),用 TCP的描述就是:

      只要网络中没有出现拥塞,拥塞窗口的值就可以再增大一些,以便把更多的数据包发送出去,但只要网络出现拥塞,拥塞窗口的值就应该减小一些,以减少注入到网络中的数据包数。其实只要「发送⽅」没有在规定时间内接收到 ACK 应答报⽂,也就是发⽣了超时重传,就会认为⽹络出现了拥塞

      实际上,拥塞控制主要有这几种常用算法

      • 慢启动
      • 拥塞避免
      • 拥塞发生
      • 快速恢复

      45.1 慢启动算法

      慢启动算法,表面意思就是,别急慢慢来。它表示TCP建立连接完成后,一开始不要发送大量的数据,而是先探测一下网络的拥塞程度。由小到大逐渐增加拥塞窗口的大小,如果没有出现丢包,当发送⽅每收到⼀个 ACK,拥塞窗⼝cwnd的⼤⼩就会加1。

      • TCP连接完成,初始化cwnd = 1,表明可以传一个MSS单位大小的数据。
      • 当收到⼀个 ACK 确认应答后,cwnd 增加 1,于是⼀次能够发送 2 个 ,当收到 2 个的 ACK 确认应答后, cwnd 增加 2,于是就可以⽐之前多发2 个,所以这⼀次能够发送 4 个 ,当这 4 个的 ACK 确认到来的时候,每个确认 cwnd 增加 1, 4 个确认 cwnd 增加 4,于是就可以⽐

        本文由 在线网速测试 整理编辑,转载请注明出处。

          热门文章

          文章分类