计算机网络常见面试题总结

268 阅读12分钟

「这是我参与11月更文挑战的第1天,活动详情查看:2021最后一次更文挑战」。

 常见状态码

1xx

1xx 类状态码属于提示信息,是协议处理中的一种中间状态,实际用到的比较少。

2xx

2xx 类状态码表示服务器成功处理了客户端的请求。
「200 OK」是最常见的成功状态码,表示一切正常。如果是非 HEAD 请求,服务器返回的响应头都会有 body 数据。
「204 No Content」也是常见的成功状态码,与 200 OK 基本相同,但响应头没有 body 数据。
「206 Partial Content」是应用于 HTTP 分块下载或断点续传,表示响应返回的 body 数据并不是资源的全部,而是其中的一部分,也是服务器处理成功的状态。

3xx

3xx 类状态码表示客户端请求的资源发送了变动,需要客户端用新的 URL 重新发送请求获取资源,也就是重定向。

「301 Moved Permanently」表示永久重定向,说明请求的资源已经不存在了,需改用新的 URL 再次访问。

「302 Found」表示临时重定向,说明请求的资源还在,但暂时需要用另一个 URL 来访问。

301 和 302 都会在响应头里使用字段 Location ,指明后续要跳转的 URL,浏览器会自动重定向新的URL。

「304 Not Modified」不具有跳转的含义,表示资源未修改,重定向已存在的缓冲文件,也称缓存重定向,用于缓存控制。

4xx

4xx 类状态码表示客户端发送的报文有误,服务器无法处理,也就是错误码的含义。
「400 Bad Request」表示客户端请求的报文有错误,但只是个笼统的错误。
「403 Forbidden」表示服务器禁止访问资源,并不是客户端的请求出错。
「404 Not Found」表示请求的资源在服务器上不存在或未找到,所以无法提供给客户端。

5xx

5xx 类状态码表示客户端请求报文正确,但是服务器处理时内部发生了错误,属于服务器端的错误
码。

「500 Internal Server Error」与 400 类型,是个笼统通用的错误码,服务器发生了什么错误,我们并不知道。
「501 Not Implemented」表示客户端请求的功能还不支持,类似“即将开业,敬请期待”的意思。
「502 Bad Gateway」通常是服务器作为网关或代理时返回的错误码,表示服务器自身工作正常,访问后端服务器发生了错误。
「503 Service Unavailable」表示服务器当前很忙,暂时无法响应服务器,类似“网络服务正忙,请稍后重试”的意思。

HTTP常见字段

HTTP在请求头Request Headers和响应头Response Headers中的常见字段,主要有:Host、Connection、Content-Encoding、Content-Type、Cookie、Authorization、User-Agent等。

Host 字段

客户端发送请求时,通过在请求头中添加Host来指定要访问的服务器的域名。

Content-Length 字段

服务器在返回数据时,会有 Content-Length 字段,表明本次回应的数据长度。

Connection 字段

Connection 字段最常用于客户端要求服务器使用 TCP 长连接,以便其他请求复用。
HTTP/1.1 版本的默认连接都是持久连接,也叫长连接,但为了兼容老版本的 HTTP,需要指定 Connection 首部字
段的值为 Keep-Alive 。一个可以复用的 TCP 连接就建立了,直到客户端或服务器主动关闭连接。

Content-Type 字段

Content-Type 字段用于服务器响应时,在响应头中添加该字段,告诉客户端,本次数据是什么格式。

Content-Type:application/json; charset=UTF-8

上面的类型表明,服务器发送的是json格式数据,而且编码是UTF-8。

客户端请求的时候,可以使用 Accept 字段声明自己可以接受哪些数据格式。

Accept: /

上面代码中,客户端声明自己可以接受任何格式的数据。

Content-Encoding 字段

Content-Encoding 字段说明数据的压缩方法,表示服务器返回的数据使用了什么压缩格式。

GET 和 POST 的区别?

1.从参数方面来说
GET方法的含义是请求从服务器获取资源,这个资源可以是静态的文本、页面、图片视频等,请求数据通常放在url中。
而 POST 方法,它向 URI 指定的资源提交数据,数据一般放在报文的 请求body 中。

2.从数据安全性与幂等性来说

GET 方法是安全且幂等的,因为它是「只读」操作,无论操作多少次,服务器上的数据都是安全的,且每次的结果都是相同的。
POST 因为是「新增或提交数据」的操作,会修改服务器上的资源,所以是不安全的,且多次提交数据就会创建多个资源,所以不是幂等的。

在 HTTP 协议里,所谓的「安全」是指请求方法不会「破坏」服务器上的资源。
所谓的「幂等」,意思是多次执行相同的操作,结果都是「相同」的。

3.从发送请求次数来说

GET方法通常发送一次请求,POST方法发送两次请求。

在使用POST方法时,客户端可以利用HTTP的Continued协议来这样做:客户端总是先发送所有请求头给服务器,让服务器校验请求头中的参数。如果请求头参数校验通过,服务器回复“100 - Continue”,客户端再把剩下的数据发给服务器。如果请求被拒了,服务器就回复个400之类的错误。这样,就可以避免浪费带宽传请求体。但是代价就是会多发送一次Round Trip。如果刚好请求体的数据也不多,那么一次性全部发给服务器可能反而更好。

HTTP1.1的优缺点

优点

HTTP 最凸出的优点是:简单、灵活和易于扩展、应用广泛和跨平台」。

1. 简单

HTTP 基本的报文格式就是 header + body ,头部信息也是 key-value 简单文本的形式,易于理解,
降低了学习和使用的门槛。

2. 灵活和易于扩展

HTTP协议里的各类请求方法、URI/URL、状态码、头字段等每个组成要求都没有被固定死,都允许开发人员自定义和扩充。
同时 HTTP 由于是工作在应用层( OSI 第七层),在它下层可以随意变化。HTTPS 就是在 HTTP 与 TCP 层之间增加了 SSL/TLS 安全传输层,HTTP/3 甚至把 TCP 层换成了基于 UDP 的 QUIC。

3. 应用广泛和跨平台

HTTP 的应用范围非常的广泛,同时天然具有跨平台的优越性。

缺点

HTTP 协议的缺点是:无状态、明文传输、不安全。

1. 无状态

无状态的好处,因为服务器不会去记忆 HTTP 的状态,所以不需要额外的资源来记录状态信息,这能减轻服务器的负担,能够把更多的 CPU 和内存用来对外提供服务。
无状态的坏处,既然服务器没有记忆能力,它在完成有关联性的操作时会非常麻烦。
例如登录->添加购物车->下单->结算->支付,这系列操作都要知道用户的身份才行。但服务器不知道这些请求是有关联的,每次都要问一遍身份信息。这样每操作一次,都要验证信息,这样的购物体验还能愉快吗?
对于无状态的问题,解法方案有很多种,其中比较简单的方式用 Cookie 技术。
Cookie 通过在请求和响应报文中写入 Cookie 信息来控制客户端的状态。相当于,在客户端第一次请求后,服务器会下发一个装有客户信息的「小贴纸」,后续客户端请求服务器的时候,带上「小贴纸」,服务器就能认得了。

2. 明文传输

明文意味着在传输过程中的信息,是可方便阅读的,为调试工作带了极大的便利性。但是,传递信息的内容回裸露出来,很容易被窃取。

3. 不安全

HTTP 比较严重的缺点就是不安全:

通信使用明文(不加密),内容可能会被窃听。
不验证通信方的身份,因此有可能遭遇伪装。
无法证明报文的完整性,所以有可能已遭篡改。

HTTP 的安全问题,可以用 HTTPS 的方式解决,也就是通过引入 SSL/TLS 层,使得在安全上达到了极
致。

HTTP/1.1 的特点与性能

HTTP 协议是基于 TCP/IP,并且使用了「请求 - 应答」的通信模式,其主要特点就是采用长连接、管道传输,会发生对头阻塞。

1. 长连接

早期 HTTP/1.0 性能上的一个很大的问题,就是每发起一个请求,都要新建一次 TCP 连接(三次握手),而且是串行请求,做了无谓的 TCP 连接建立和断开,增加了通信开销。
为了解决上述 TCP 连接问题,HTTP/1.1 提出了长连接的通信方式,也叫持久连接。这种方式的好处在于减少了 TCP 连接的重复建立和断开所造成的额外开销,减轻了服务器端的负载。
持久连接的特点是,只要任意一端没有明确提出断开连接,则保持 TCP 连接状态。

2. 管道网络传输

HTTP/1.1 采用了长连接的方式,这使得管道(pipeline)网络传输成为了可能。即可在同一个 TCP 连接里面,客户端可以发起多个请求,只要第一个请求发出去了,不必等其回来,就可以发第二个请求出去,可以减少整体的响应时间。
举例来说,客户端需要请求两个资源。以前的做法是,在同一个TCP连接里面,先发送 A 请求,然后等待服务器做出回应,收到后再发出 B 请求。管道机制则是允许浏览器同时发出 A 请求和 B 请求。
但是服务器还是按照顺序,先回应 A 请求,完成后再回应 B 请求。要是前面的回应特别慢,后面就会有许多请求排队等着。这称为「队头堵塞」。

3. 队头阻塞

「请求 - 应答」的模式加剧了 HTTP 的性能问题。
因为当顺序发送的请求序列中的一个请求因为某种原因被阻塞时,在后面排队的所有请求也一同被阻塞,会招致客户端一直请求不到数据,这也就是「队头阻塞」。

Cookie、Session、Token、Authetication和Authorization

浏览器和服务器之间的交互校验一般有四种方式:Cookie、Session、Token和Authorization。它们的交互方式可以用下面的图来表示:

Cookie与Session是常用的会话跟踪技术,都是用来跟踪用户身份的会话方式,但是两者的应用场景不太一样。简单来说,Cookie通过在客户端记录信息确定用户身份,由于用户信息存放在客户端不太安全Session通过在服务器端记录信息确定用户身份,安全性更高

Authentication,是用来认证用户身份的;Authorization,是授权用户访问系统的权限。

Cookie

Cookies是某些网站为了辨别用户身份而储存在用户本地终端上的数据(通常经过加密)。简单来说: Cookie 存放在客户端,一般用来保存用户信息。

下面是 Cookie 的一些应用案例:

  1. 我们在 Cookie 中保存已经登录过的用户信息,下次访问网站的时候页面可以自动帮你登录的一些基本信息给填了。除此之外,Cookie 还能保存用户首选项,主题和其他设置信息。\
  2. 使用Cookie 保存 session 或者 token ,向后端发送请求的时候带上 Cookie,这样后端就能取到session或者token了。这样就能记录用户当前的状态了,因为 HTTP 协议是无状态的。\
  3. Cookie 还可以用来记录和分析用户行为。举个简单的例子你在网上购物的时候,因为HTTP协议是没有状态的,如果服务器想要获取你在某个页面的停留状态或者看了哪些商品,一种常用的实现方式就是将这些信息存放在Cookie

Session

Session,英文意思为“会话”, 是Web程序中常用的一种会话跟踪技术,用来跟踪用户的整个会话

Session 的主要作用是通过服务端记录用户的状态。 典型的场景是购物车,当你要添加商品到购物车的时候,系统不知道是哪个用户操作的,因为 HTTP 协议是无状态的。服务端给特定的用户创建特定的 Session 之后就可以标识这个用户并且跟踪这个用户了。

Cookie 数据保存在客户端(浏览器端),Session 数据保存在服务器端。相对来说 Session 安全性更高。如果使用 Cookie 的一些敏感信息不要写入 Cookie 中,最好能将 Cookie 信息加密然后使用到的时候再去服务器端解密。

那么,如何使用Session进行身份验证?

很多时候我们都是通过 SessionID 来实现特定用户的身份验证,SessionID 一般会选择存放在 Redis 中。举个例子:用户成功登陆系统,然后返回给客户端具有 SessionID 的 Cookie,当用户向后端发起请求的时候会把 SessionID 带上,这样后端就知道你的身份状态了。关于这种认证方式更详细的过程如下:

  1. 用户向服务器发送用户名和密码用于登陆系统。\
  2. 服务器验证通过后,服务器为用户创建一个 Session,并将 Session信息存储 起来。\
  3. 服务器向用户返回一个 SessionID,写入用户的 Cookie。\
  4. 当用户保持登录状态时,Cookie 将与每个后续请求一起被发送出去。\
  5. 服务器可以将存储在 Cookie 上的 Session ID 与存储在内存中或者数据库中的 Session 信息进行比较,以验证用户的身份,返回给用户客户端响应信息的时候会附带用户当前的状态。

Session数据结构:

Token

由于Session 信息需要保存一份在服务器端,这种方式会带来一些麻烦,比如需要保证保存 Session 信息的服务器的可用性、不适合移动端(依赖Cookie)等等。

有没有一种不需要自己存放 Session 信息就能实现身份验证的方式呢?使用 Token 即可!JWT (JSON Web Token) 就是这种方式的实现,通过这种方式服务器端就不需要保存 Session 数据了,只用在客户端保存服务端返回给客户的 Token 就可以了,扩展性得到提升。

JWT 本质上是一段签名的 JSON 格式的数据。由于它是带有签名的,因此接收者便可以验证它的真实性。

JWT 由 3 部分构成:

Header :描述 JWT 的元数据。定义了生成签名的算法以及 Token 的类型。
Payload(负载):用来存放实际需要传递的数据
Signature(签名):服务器通过Payload、Header和一个密钥(secret)使用 Header 里面指定的签名算法(默认是 HMAC SHA256)生成。

在基于 Token 进行身份验证的的应用程序中,服务器通过Payload、Header和一个密钥(secret)创建令牌(Token)并将 Token 发送给客户端,客户端将 Token 保存在 Cookie 或者 localStorage 里面,以后客户端发出的所有请求都会携带这个令牌。你可以把它放在 Cookie 里面自动发送,但是这样不能跨域,所以更好的做法是放在 HTTP Header 的 Authorization字段中: Authorization: Bearer Token。

  1. 用户向服务器发送用户名和密码用于登陆系统。
  2. 身份验证服务响应并返回了签名的 JWT,上面包含了用户是谁的内容。
  3. 用户以后每次向后端发请求都在Header中带上 JWT。
  4. 服务端检查 JWT 并从中获取用户相关信息。

Authentication

Authentication,英文意思是“认证”,是验证身份的凭据(例如用户名/用户ID和密码),通过这个凭据,系统得以知道你就是你,也就是说验证你是否是该系统的用户。所以,Authentication 被称为身份/用户验证。

Authorization

Authorization,英文字面意思是“授权”,发生在 Authentication(认证) 之后。它主要负责授予用户访问系统的响应权限。比如有些特定资源只能具有特定权限的人才能访问,如admin,有些对系统资源操作比如删除、添加、更新只能特定人才具有。

OAuth

OAuth 是一个行业的标准授权协议,主要用来授权第三方应用获取响应的权限。实际上它就是一种授权机制,它的最终目的是为第三方应用颁发一个有时效性的令牌 token,使得第三方应用能够通过该令牌获取相关的资源。

OAuth 2.0 比较常用的场景就是第三方登录,当你的网站接入了第三方登录的时候一般就是使用的 OAuth 2.0 协议。

参考

GET 和 POST 到底有什么区别?

cookie和session的详解与区别

权限认证基础:区分Authentication,Authorization以及Cookie、Session、Token