计算机网络相关题目总结
- HTTP/1 与 HTTP/1.1 的区别
- 说一下 HTTP/2
- 说一下 HTTP 和 HTTPS
- 说一下 TCP 三次握手
- 说一下 TCP 四次挥手
- 说一下 TCP 与 UDP 的区别
- WebSocket 的实现与应用
- HTTP 支持的请求方法
- GET 和 POST 的区别
- 状态码 301 和 302 的区别
- TLS/SSL 中什么一定要用三个随机数来生成会话密钥?
- SSL 连接断开后如何恢复?
- DNS 为什么使用 UDP 协议作为传输层协议?
- 当你在浏览器中输入 URL 并按下回车之后发生了什么?
- 谈谈 CDN 服务?
- 什么是正向代理和反向代理?
- 负载平衡的两种实现方式?
- HTTP 请求方法 OPTIONS 方法有什么用?
- 即时通讯的实现,短轮询、长轮询、SSE 和 WebSocket 间的区别?
- 怎么实现多个网站之间共享登录状态
HTTP/1 与 HTTP/1.1 的区别
- 连接方面,HTTP/1.1 默认使用持久连接,而 HTTP/1 使用非持久连接。HTTP/1.1 通过使用持久连接,多个 HTTP 请求复用一个 TCP 连接,以此来减少每次建立连接的延迟。
- 缓存方面,HTTP/1.1 使用
Expires和Last-Modified/If-Modified-Since字段分别控制强缓存和协商缓存,HTTP/1.1 使用Cache-Control和Etag/If-None-Match字段分别控制强缓存和协商缓存。 - 资源请求方面,在 HTTP/1 中存在带宽浪费的现象,例如客户端只是需要某个对象的一部分,而服务器却将整个对象送过来了,并且不支持断点续传功能;HTTP/1.1 则在请求头引入了 range 头域,它允许只请求资源的某个部分,即返回码是 206(PartialContent),这样就方便了开发者自由的选择以便于充分利用带宽和连接。
- HTTP/1.1 新增了 Host 请求头字段,用来指定服务器的域名。HTTP/1 认为每台服务器都绑定唯一的 IP 地址,请求头不传主机名,但随着虚拟主机技术的发展,在一台物理主力上可能存在多个虚拟主机,并且它们共享一个 IP 地址。因此有了 host 字段,就可以将请求发往同一台服务器上的不同网站。
- HTTP/1.1 还新增了很多请求方法,如 PUT、HEAD、OPTIONS 等。
详细资料可以参考:
说一下 HTTP/2
HTTP/1.1 默认使用持久连接,多个请求可以复用一个 TCP 连接,但是在同一个 TCP 连接里,数据请求的通信次序是固定的。服务器只有处理完一个请求的响应后,才会进行下一个请求的处理,如果前面请求的响应特别慢的话,就会造成许多请求排队等待的情况,这种情况被称为队头堵塞。队头阻塞会导致持久连接在达到最大数量时,剩余的资源需要等待其他资源请求完成后才能发起请求。为了避免这个问题,可以减少请求量或同时打开多个持久连接。
HTTP/2 协议主要解决了 HTTP/1.1 效率不高的问题。主要特点如下:
- 二进制协议。HTTP 是基于文本解析,HTTP/2 将所有传输的消息分割为更小的消息和帧,并采用二进制编码,基于二进制能让协议有更多的拓展性。
- 多路复用。HTTP/2 仍然复用 TCP 连接,但是在一个连接里,客户端和服务器都可以同时发送多个请求或响应,而且不用按照顺序发送,这样就避免了队头堵塞的问题。
- 数据流。HTTP/2 引入了数据流的概念,由于其发送请求和响应可以不按顺序发送,这就意味着同一个连接里连续的数据包可能属于不同的请求。因此必须对数据包做标记,指出它属于哪个请求。HTTP/2 将每个请求或回应的所有数据包,称为一个数据流。每个数据流都有一个独一无二的编号。数据包发送的时候,都必须标记数据流 ID,用来区分它属于哪个数据流。
- 头消息压缩。由于 HTTP/1 是无状态协议,每次请求都要带上所有的请求头,同样的请求头每次都要携带,这会造成带宽浪费。HTTP/2 引入了头消息压缩机制,一方面,头信息使用 gzip 或 compress 压缩后再发送;另一方面,客户端和服务器同时维护一张头信息表,所有字段都会存入这个表,生成一个索引号,每次传输只发送索引号即可,这样就提高了速度。
- 服务器推送。HTTP/2 允许服务器未经请求,主动向客户端推送资源,这样就可以相对减少一些延迟时间。这与 WebSocket 推送即时数据不一样。
- 内容安全。HTTP/2 默认使用 HTTPS 协议,天然具有安全特性,通过 HTTP/2 的特性可以避免单纯使用 HTTPS 的性能下降。
说一下 HTTP 和 HTTPS
HTTP:超文本传输协议,是互联网上应用最为广泛的一种网络协议,是一个客户端和服务端请求和应答的标准(TCP),用于从服务器传输超文本到本地浏览器的传输协议。
HTTPS:是以安全为目的 HTTP 通道,即在 HTTP 的基础上加入 SSL 层,它是 HTTP 的安全版。HTTPS 协议的主要作用是:建立一个信息安全通道,来确保数据的传输安全。
HTTP 与 HTTPS 的区别:
- HTTP 是超文本传输协议,信息明文传输;HTTPS 是具有安全性的 SSL 加密传输协议。
- 使用不同的链接方式,端口也不同,一般而言,HTTP 协议的端口是 80,HTTPS 的端口是 443。
- HTTP 的连接很简单,是无状态的;HTTPS 协议是由 HTTP+SSL 协议构建的可进行加密传输、身份认证的网络协议,比 HTTP 协议安全。
HTTPS 的工作原理:客户端通过 https url 访问服务器,要求服务器建立 SSL 连接。服务器收到客户端的请求后,将包含网站公钥的证书传输给客户端;客户端与服务端协商加密方式与安全等级,建立会话密钥,然后用网站的公钥加密会话密钥,并传送到服务端;服务器通过网站的私钥解密出会话密钥。客户端与服务器通过会话密钥加密传输信息来保证数据传输安全。其中建立会话密钥的过程的非对称加密,而数据传输过程是对称加密。
说一下 TCP 三次握手
TCP 三次握手是客户端与服务器建立连接的过程。具体过程如下:
- 客户端向服务器发送连接请求。报文段中的 SYN 标志位置为 1,同时生成一个随机数
seq=x作为客户端初始序号。客户端发送后进入 SYN_SEND 状态。 - 服务器端接收到客户端发送的 SYN 连接请求报文段后,服务器首先会为该连接分配 TCP 缓存和变量,然后确认客户端的连接请求并向客户端发送连接请求。报文段中的 SYN 标志位置为 1,确认号 ACK 在客户端请求序号基础上加 1,同时生成一个随机数
seq=y作为服务端初始序号。服务端发送后进入 SYN_RECV 状态。 - 客户端接收到服务器的肯定应答后,它也会为这次 TCP 连接分配缓存和变量,然后确认服务端的连接请求。报文段中的确认号 ACK 在服务端请求序号基础上加 1。客户端发送后进入 ESTABLISHED 状态,服务端收到客户端的确认也进入 ESTABLISHED 状态。第三次握手可以在报文段中携带数据。
三次握手的作用:
- 第一次握手,客户端向服务器发起连接请求。服务器可以确认客户端有发送能力,自己有接收能力。
- 第二次握手,服务器确认连接请求并向客户端发起连接请求。客户端可以确认自己有发送能力和接收能力,服务器有接收能力和发送能力。
- 第三次握手,客户端确认连接请求。服务端确认客户端有接收能力,自己有发送能力。
说一下 TCP 四次挥手
因为 TCP 连接是全双工的,也就是说通信的双方都可以向对方发送和接收消息,所以断开连接需要双方的确认。具体过程如下:
- 客户端认为没有数据要再发送给服务器端,它就向服务器发送一个 FIN 报文段,申请断开客户端到服务器端的连接。发送后客户端进入 FIN_WAIT_1 状态。
- 服务器端接收到客户端释放连接的请求后,向客户端发送一个确认报文段,表示已经接收到了客户端释放连接的请求,以后不再接收客户端发送过来的数据。但是因为连接是全双工的,所以此时,服务器端还可以向客户端发送数据。服务器端进入 CLOSE_WAIT 状态。客户端收到确认后,进入 FIN_WAIT_2 状态。
- 服务器端发送完所有数据后,向客户端发送 FIN 报文段,申请断开服务器端到客户端的连接。发送后进入 LAST_ACK 状态。
- 客户端接收到 FIN 请求后,向服务器端发送一个确认应答,并进入 TIME_WAIT 阶段。该阶段会持续一段时间, 这个时间为报文段在网络中的最大生存时间,如果该时间内服务端没有重发请求的话,客户端进入 CLOSED 的状态。如果收到 服务器的重发请求就重新发送确认报文段。服务器端收到客户端的确认报文段后就进入 CLOSED 状态,这样全双工的连接就被释放了。
最后一次挥手中,客户端需等待 2MLS 再关闭的原因,是为了防止发送给服务器的确认报文段丢失或者出错,从而导致服务器端不能正常关闭。
说一下 TCP 与 UDP 的区别
- TCP 是面向连接的;UDP 是无连接的,即发送数据前不需要先建立连接。
- TCP 提供可靠的服务;UDP 是不可靠的,即不保证可靠的交付。
- TCP 是面向字节流;UDP 是面向报文,并且网络出现拥塞不会降低发送速率(因此会出现丢包)。
- TCP 只能是 1 对 1 的;UDP 支持 1 对 1,1 对多等。
- TCP 的首部较大为 20 字节;UDP 只有 8 字节。
WebSocket 的实现与应用
WebSocket 是 HTML5 中的协议,支持持久连续,HTTP 协议不支持持久性连接。HTTP/1 和 HTTP/1.1 都不支持持久性的连接,HTTP/1.1 中的 keep-alive,将多个 http 请求合并为 1 个。
WebSocket 的优点:
HTTP 的生命周期的通过 Request 来界定,即一个 Request 对应一个 Response,这在 HTTP/1 中本次请求就结束了。在 HTTP/1.1 中新增了 Connection: keep-alive,在一个请求中可以发送多个 Request,接收多个 Response,但每个请求和响应都是一一对应的,而且这个响应的被动的,不能主动发起。
WebSocket 是基于 HTTP 协议的,或者说借助 HTTP 建立连接。其握手协议的实现,依赖两个属性:
GET /chat HTTP/1.1
Connection: Upgrade
Host: server.example.com
Origin: http://example.com
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13
Upgrade: websocket
HTTP 支持的请求方法
OPTIONS, HEAD, GET, POST, PUT, PATCH, DELETE, TRACE, CONNECT.
GET 和 POST 的区别
- 传参形式不同,GET 请求参数通过 url 传递,而 POST 请求通过 request body 传递。
- 参数容量不同,GET 请求有长度限制,而 PSOT 请求没有。
- 安全性不同,GET 请求参数直接暴露在 url,并且会被浏览器缓存,因此避免通过 GET 请求传递敏感信息。
- 参数编码不同,GET 请求参数只能通过 url 编码,而 POST 请求参数支持多种编码形式。
- 应用场景不同,GET 是幂等请求,一般不会对服务器资源产生影响,而 POST 不是幂等请求,一般会对服务器资源产生影响。
状态码 301 和 302 的区别
字面上的区别就是:301 是永久重定向,302 是临时重定向。
301 比较常用的场景是使用域名跳转。302 用来做临时跳转,比如未登陆的用户访问用户中心重定向到登录页面。
TLS/SSL 中什么一定要用三个随机数来生成会话密钥?
客户端和服务器都需要生成随机数,以此来保证每次生成的秘钥都不相同。使用三个随机数,是因为 SSL 的协议默认不信任每个主机都能产生完全随机的数,如果只使用一个伪随机的数来生成秘钥,就很容易被破解。通过使用三个随机数的方式,增加了自由度,一个伪随机可能被破解,但是三个伪随机就很接近于随机了,因此可以使用这种方法来保持生成秘钥的随机性和安全性。
SSL 连接断开后如何恢复?
一共有两种方法来恢复断开的 SSL 连接,一种是使用 session ID,一种是 session ticket。
使用 session ID 的方式,每一次的会话都有一个编号,当对话中断后,下一次重新连接时,只要客户端给出这个编号,服务器如果有这个编号的记录,那么双方就可以继续使用以前的秘钥,而不用重新生成一把。目前所有的浏览器都支持这一种方法。但是这种方法有一个缺点是,session ID 只能够存在一台服务器上,如果我们的请求通过负载平衡被转移到了其他的服务器上,那么就无法恢复对话。
另一种方式是 session ticket 的方式,session ticket 是服务器在上一次对话中发送给客户的,这个 ticket 是加密的,只有服务器能够解密,里面包含了本次会话的信息,比如对话秘钥和加密方法等。这样不管我们的请求是否转移到其他的服务器上,当服务器将 ticket 解密以后,就能够获取上次对话的信息,就不用重新生成对话秘钥了。
DNS 为什么使用 UDP 协议作为传输层协议?
DNS 使用 UDP 协议作为传输层协议的主要原因是为了避免使用 TCP 协议时造成的连接时延。因为为了得到一个域名的 IP 地址,往往会向多个域名服务器查询,如果使用 TCP 协议,那么每次请求都会存在连接时延,这样使 DNS 服务变得很慢,因为大多数的地址查询请求,都是浏览器请求页面时发出的,这样会造成网页的等待时间过长。
使用 UDP 协议作为 DNS 协议会有一个问题,由于历史原因,物理链路的最小 MTU=576,所以为了限制报文长度不超过 576,UDP 的报文段的长度被限制在 512 个字节以内,这样一旦 DNS 的查询或者应答报文,超过了 512 字节,那么基于 UDP 的 DNS 协议就会被截断为 512 字节,那么有可能用户得到的 DNS 应答就是不完整的。这里 DNS 报文的长度一旦超过限制,并不会像 TCP 协议那样被拆分成多个报文段传输,因为 UDP 协议不会维护连接状态,所以我们没有办法确定那几个报文段属于同一个数据,UDP 只会将多余的数据给截取掉。为了解决这个问题,我们可以使用 TCP 协议去请求报文。
DNS 还存在的一个问题是安全问题,就是我们没有办法确定我们得到的应答,一定是一个安全的应答,因为应答可以被他人伪造,所以现在有了 DNS over HTTPS 来解决这个问题。
当你在浏览器中输入 URL 并按下回车之后发生了什么?
- 解析 DNS:解析输入的 URL 中的域名得到服务器主机 IP 地址。首先会判断本地是否有该域名的 IP 地址的缓存,如果有则使用,如果没有则向本地 DNS 服务器发起请求。本地 DNS 服务器也会先检查是否存在缓存,如果没有就会先向根域名服务器发起请求,获得负责的顶级域名服务器的地址后,再向顶级域名服务器请求,然后获得负责的权威域名服务器的地址后,再向权威域名服务器发起请求,最终获得域名的 IP 地址后,本地 DNS 服务器再将这个 IP 地址返回给请求的用户。用户向本地 DNS 服务器发起请求属于递归请求,本地 DNS 服务器向各级域名服务器发起请求属于迭代请求。
- 建立连接:通过 TCP 三次握手建立浏览器与服务器间的连接。第一次握手,客户端发送一个带
SYN=1,Seq=x的数据包到服务端,并进入 SYN_SEND 状态,等待服务器确认。第二次握手,服务端确认收到客户端发来的请求,发回一个带SYN=1,ACK=x+1,Seq=y的数据包到客户端,以示传达确认信息,并进入SYN_RECV状态。第三次握手,客户端确认收到服务端发来的请求,再回传一个带ACK=y+1,Seq=z的数据包到服务端,包发送完毕后,客户端与服务端都进入ESTABLISHED状态。完成 TCP 三次握手。 - 如果使用的是 HTTPS 协议,在通信前还存在 TLS 的一个四次握手的过程。第一次握手,由客户端向服务器端发送使用的协议的版本号、一个随机数和可以使用的加密方法。第二次握手,服务器端收到后,确认加密的方法,也向客户端发送一个随机数和自己的数字证书。第三次握手,客户端收到后,先检查数字证书是否有效,如果有效,则再生成一个随机数,并使用证书中的公钥对随机数加密,然后发送给服务器端,并且还会提供一个前面所有内容的 hash 值供服务器端检验。第四次握手,服务器端接收后,使用自己的私钥对数据解密,同时向客户端发送一个前面所有内容的 hash 值供客户端检验。此时双方都有了三个随机数,按照之前所约定的加密方再传输。
- 客户端发送请求到服务器端,服务器端解析请求并返回一个 html 文件作为响应。
- 解析并渲染页面:浏览器接收到响应后,对 html 文件进行解析,开始页面的渲染过程。浏览器首先会根据 html 文件构建 DOM 树,根据解析到的 css 文件构建 CSSOM 树,如果遇到 script 标签,则判端是否含有 defer 或者 async 属性,要不然 script 的加载和执行会阻塞页面渲染。当 DOM 树和 CSSOM 树建立好后,根据它们来构建渲染树。渲染树构建好后,会根据渲染树来进行布局。布局完成后,最后使用浏览器的 UI 接口对页面进行绘制。这个时候整个页面就显示出来了。
- 断开连接:当数据传送完毕,需要断开 TCP 连接,此时发起 TCP 四次挥手。
谈谈 CDN 服务?
CDN 是一个内容分发网络,通过对源网站资源的缓存,利用本身多台位于不同地域、不同运营商的服务器,向用户提供资源就近访问的功能。也就是说,用户的请求并不是直接发送给源网站,而是发送给 CDN 服务器,由 CND 服务器将请求定位到最近的含有该资源的服务器上去请求。这样有利于提高网站的访问速度,同时通过这种方式也减轻了源服务器的访问压力。
详细资料可以参考:
什么是正向代理和反向代理?
我们常说的代理也就是指正向代理,正向代理的过程,它隐藏了真实的请求客户端,服务端不知道真实的客户端是谁,客户端请求的服务都被代理服务器代替来请求。
反向代理隐藏了真实的服务端,当我们请求一个网站的时候,背后可能有成千上万台服务器为我们服务,但具体是哪一台,我们不知道,也不需要知道,我们只需要知道反向代理服务器是谁就好了,反向代理服务器会帮我们把请求转发到真实的服务器那里去。反向代理器一般用来实现负载平衡。
详细资料可以参考:
负载平衡的两种实现方式?
一种是使用反向代理的方式,用户的请求都发送到反向代理服务上,然后由反向代理服务器来转发请求到真实的服务器上,以此来实现集群的负载平衡。
另一种是 DNS 的方式,DNS 可以用于在冗余的服务器上实现负载平衡。因为现在一般的大型网站使用多台服务器提供服务,因此一个域名可能会对应多个服务器地址。当用户向网站域名请求的时候,DNS 服务器返回这个域名所对应的服务器 IP 地址的集合,但在每个回答中,会循环这些 IP 地址的顺序,用户一般会选择排在前面的地址发送请求。以此将用户的请求均衡的分配到各个不同的服务器上,这样来实现负载均衡。这种方式有一个缺点就是,由于 DNS 服务器中存在缓存,所以有可能一个服务器出现故障后,域名解析仍然返回的是那个 IP 地址,就会造成访问的问题。
详细资料可以参考:
HTTP 请求方法 OPTIONS 方法有什么用?
OPTIONS 请求与 HEAD 类似,一般也是用于客户端查看服务器的性能。这个方法会请求服务器返回该资源所支持的所有 HTTP 请求方法,该方法会用 '*' 来代替资源名称,向服务器发送 OPTIONS 请求,可以测试服务器功能是否正常。JS 的 XMLHttpRequest 对象进行 CORS 跨域资源共享时,对于复杂请求,就是使用 OPTIONS 方法发送嗅探请求,以判断是否有对指定资源的访问权限。
即时通讯的实现,短轮询、长轮询、SSE 和 WebSocket 间的区别?
短轮询和长轮询的目的都是用于实现客户端和服务器端的一个即时通讯。
短轮询的基本思路就是浏览器每隔一段时间向浏览器发送 http 请求,服务器端在收到请求后,不论是否有数据更新,都直接进行响应。这种方式实现的即时通信,本质上还是浏览器发送请求,服务器接受请求的一个过程,通过让客户端不断的进行请求,使得客户端能够模拟实时地收到服务器端的数据的变化。这种方式的优点是比较简单,易于理解。缺点是这种方式由于需要不断的建立 http 连接,严重浪费了服务器端和客户端的资源。当用户增加时,服务器端的压力就会变大,这是很不合理的。
长轮询的基本思路是,首先由客户端向服务器发起请求,当服务器收到客户端发来的请求后,服务器端不会直接进行响应,而是先将这个请求挂起,然后判断服务器端数据是否有更新。如果有更新,则进行响应,如果一直没有数据,则到达一定的时间限制才返回。
客户端 JavaScript 响应处理函数会在处理完服务器返回的信息后,再次发出请求,重新建立连接。长轮询和短轮询比起来,它的优点是明显减少了很多不必要的 http 请求次数,相比之下节约了资源。长轮询的缺点在于,连接挂起也会导致资源的浪费。
SSE 的基本思想是,服务器使用流信息向服务器推送信息。严格地说,http 协议无法做到服务器主动推送信息。但是,有一种变通方法,就是服务器向客户端声明,接下来要发送的是流信息。也就是说,发送的不是一次性的数据包,而是一个数据流,会连续不断地发送过来。这时,客户端不会关闭连接,会一直等着服务器发过来的新的数据流,视频播放就是这样的例子。SSE 就是利用这种机制,使用流信息向浏览器推送信息。它基于 http 协议,目前除了 IE/Edge,其他浏览器都支持。它相对于前面两种方式来说,不需要建立过多的 http 请求,相比之下节约了资源。
上面三种方式本质上都是基于 http 协议的,我们还可以使用 WebSocket 协议来实现。
WebSocket 是 HTML5 定义的一个新协议,与传统的 http 协议不同,该协议允许由服务器主动的向客户端推送信息。使用 WebSocket 协议的缺点是在服务器端的配置比较复杂。WebSocket 是一个全双工的协议,也就是通信双方是平等的,可以相互发送消息,而 SSE 的方式是单向通信的,只能由服务器端向客户端推送信息,如果客户端需要发送信息就是属于下一个 http 请求了。
详细资料可以参考:
怎么实现多个网站之间共享登录状态
在多个网站之间共享登录状态指的就是单点登录。
多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统。我认为单点登录可以这样来实现,首先将用户信息的验证中心独立出来,作为一个单独的认证中心,该认证中心的作用是判断客户端发送的账号密码的正确性,然后向客户端返回对应的用户信息,并且返回一个由服务器端秘钥加密的登录信息的 token 给客户端,该 token 具有一定的有效时限。当一个应用系统跳转到另一个应用系统时,通过 url 参数的方式来传递 token,然后转移到的应用站点发送给认证中心,认证中心对 token 进行解密后验证,如果用户信息没有失效,则向客户端返回对应的用户信息,如果失效了则将页面重定向会单点登录页面。
总的来说,SSO 是服务端认证后的加密 TOKEN 在多站点间传播。