面试官:这波HTTP究极combo,你顶得住吗?

HTTP 是超文本传输协议,也就是HyperText Transfer Protocol。

问题:能否详细解释「超文本传输协议」?

HTTP的名字「超文本协议传输」,它可以拆成三个部分:

  • 协议

针对 HTTP 协议,我们可以这么理解。

HTTP 是文个⽤在计算机世界⾥的协议。它使⽤计算机能够理解的语⾔确⽴了⼀种计算机之间交流通信

的规范(两个以上的参与者),以及相关的各种控制和错误处理方式式(为约定和规范)。

  • 传输

针对传输,我们可以进⼀步理解了 HTTP。

HTTP 是⼀个在计算机世界⾥专⻔⽤来在两点之间传输数据的约定和规范

  • 超文本

「文本」,在互联⽹早期的时候只是简单的字符⽂字,但现在「文本」的涵义已经可以扩

展为图⽚、视频、压缩包等,在 HTTP 眼⾥这些都算作「文本」。

再来理解「超文本」,它就是超越了普通文本的文本,它是文字、图文、视频等的混合体,最关键有超

链接,能从一个超文本跳转到另外一个超文本

综上,HTTP 是⼀个在计算机世界里专门在「两点」之间「传输」⽂字、图⽚、⾳频、视频等「超文本」数据

的「约定和规范」。

问题:那「HTTP 是用于从互联网服务器传输超文本到本地浏览器的协议 ,这种说法正确吗?

这种说法是不正确的。因为也可以是「服务器< – >服务器」,所以采⽤两点之间的描述会更准确。

问题:HTTP 常见的状态码,有哪些?

  • 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 Modifified」不具有跳转的含义,表示资源未修改,重定向已存在的缓冲⽂件,也称缓存重定

向,⽤于缓存控制。

  • 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」表示服务器当前很忙,暂时⽆法响应服务器,类似“网络服务正忙,请稍

后重试”的意思。

问题:OSI七层模型和TCP/IP的四/五层模型知道吗?

  • 应用层 :为特定应用程序提供数据传输服务,例如 HTTP、DNS 等协议。数据单位为报文。
  • 传输层 :为进程提供通用数据传输服务。由于应用层协议很多,定义通用的传输层协议就可以支持不断增多的应用层协议。运输层包括两种协议:传输控制协议 TCP,提供面向连接、可靠的数据传输服务,数据单位为报文段;用户数据报协议 UDP,提供无连接、尽最大努力的数据传输服务,数据单位为用户数据报。TCP 主要提供完整性服务,UDP 主要提供及时性服务。
  • 网络层 :为主机提供数据传输服务。而传输层协议是为主机中的进程提供数据传输服务。网络层把传输层传递下来的报文段或者用户数据报封装成分组。
  • 数据链路层 :网络层针对的还是主机之间的数据传输服务,而主机之间可以有很多链路,链路层协议就是为同一链路的主机提供数据传输服务。数据链路层把网络层传下来的分组封装成帧。
  • 物理层 :考虑的是怎样在传输媒体上传输数据比特流,而不是指具体的传输媒体。物理层的作用是尽可能屏蔽传输媒体和通信手段的差异,使数据链路层感觉不到这些差异

问题:数据的传输流程是怎么样的?

数据封装过程(快件打包)

  • 应用层传输

这里可以理解为翻译的过程,当然这是属于计算机的翻译过程,应用层便是将数据进行二进制编码。

  • 传输层传输(数据段) 传输层将上层数据分割成诸多数据段(方便解决传输出错问题),并且为每个分段后的数据 封装—— TCP报文头部。其中TCP报文头部有一个关键的字段信息——端口号(保证上层应用数据通信)。

  • 网络层传输 (数据包) 网络层将上层数据再度添加封装——IP头部,其头部包含一个关键的字段信息——IP地址,用于标识网络 的逻辑地址。

  • 数据链路层传输(数据帧) 数据链路层将上层数据再次添加封装——MAC头部,其包含一个关键的字段信息——MAC地址, 可以理解 为固化在硬件中的物理地址,和我们的个人银行卡号一样具有唯一性。 该封装过程中的尾部封装暂不讨论。

  • 物理层传输(比特流) 物理层将上层二进制数据转成电信号在网络中传输。

问题: 那么HTTP的报文结构是怎么样的?

请求报文:

响应报文:

需要注意的是,请求报文中请求方式为GET的时候,是没有body的。body只存在于POST中。

问题: HTTP都有什么请求方式?

  • GET

⽤于获取资源

对服务器数据不进⾏修改

不发送 Body

GET把参数包含在URL

GET /users/1 HTTP/1.1
Host: api.github.com

  • POST

⽤于增加或修改资源

发送给服务器的内容写在 Body ⾥⾯

POST /users HTTP/1.1
Host: api.github.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 13
name=mlx&age=10

PUT

用于修改资源

发送给服务器的内容写在 Body ⾥⾯

PUT /users/1 HTTP/1.1
Host: api.github.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 13
name=mlx

DELETE

⽤于删除资源

不发送 Body

DELETE /users/1 HTTP/1.1
Host: api.github.com

HEAD

和 GET 使⽤⽅法完全相同

和 GET 唯⼀区别在于,返回的响应中没有 Body

问题: HTTP这么多请求方法有什么区别呢?

url描述了一个网络上资源,而post、get、put、delete就是对这个资源进行增、删、改、查的操作!

需要引入新的名词:安全和幂等

安全和幂等的概念:

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

GET ⽅法就是安全且幂等的,因为它是「只读」操作,⽆论操作多少次,服务器上的数据都是安全的,且每次的结果都是相同的。

POST 因为是「新增或提交数据」的操作,会修改服务器上的资源,所以是不安全的,且多次提交数据就会创建多个资源,所以不是幂等的。

PUTDELETE操作是幂等的。

重点说一下GET和POST的区别:

  • GET在浏览器回退时是无害的,而POST会再次提交请求。(也就是上文的幂等)
  • GET产生的URL地址可以被Bookmark,而POST不可以。
  • GET请求会被浏览器主动cache,而POST不会,除非手动设置。
  • GET请求只能进行url编码,而POST支持多种编码方式。
  • GET请求参数会被完整保留在浏览器历史记录里,而POST中的参数不会被保留。
  • GET请求在URL中传送的参数是有长度限制的,而POST么有。
  • 对参数的数据类型,GET只接受ASCII字符,而POST没有限制。
  • GET比POST更不安全,因为参数直接暴露在URL上,所以不能用来传递敏感信息。
  • GET参数通过URL传递,POST放在Request body中。

但是,凡是都有但是,HTTP的底层是TCP/IP。所以GET和POST的底层也是TCP/IP,也就是说,GET/POST都是TCP链接。GET和POST能做的事情是一样一样的。只不过因为语义化以及服务器或者浏览器的限制导致出现了区别。还有一个最重要的区别:

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

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

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

问题: 创建了报文以后如何建立的连接呢?

HTTP是基于TCP/IP的,所以HTTP的请求就是TCP/IP的连接过程。

TCP是什么?

  • TCP 提供一种面向连接的、可靠的字节流服务
  • 在一个 TCP 连接中,仅有两方进行彼此通信。广播和多播不能用于 TCP
  • TCP 给数据分节进行排序,并使用累积确认保证数据的顺序不变和非重复
  • TCP 使用滑动窗口机制来实现流量控制,通过动态改变窗口的大小进行拥塞控制

TCP 并不能保证数据一定会被对方接收到,因为这是不可能的。TCP 能够做到的是,如果有可能,就把数据递送到接收方,否则就(通过放弃重传并且中断连接这一手段)通知用户。因此准确说 TCP 也不是 100% 可靠的协议,它所能提供的是数据的可靠递送或故障的可靠通知。

TCP链接需要经过三次握手,断开连接需要经过四次挥手

三次握手

所谓三次握手(Three-way Handshake),是指建立一个 TCP 连接时,需要客户端和服务器总共发送3个包

三次握手的目的是连接服务器指定端口,建立 TCP 连接,并同步连接双方的序列号和确认号,交换 TCP 窗口大小信息。在 socket 编程中,客户端执行 connect() 时。将触发三次握手

  • 第一次握手(SYN=1, seq=x):

客户端发送一个 TCP 的 SYN 标志位置1的包,指明客户端打算连接的服务器的端口,以及初始序号 X,保存在包头的序列号(Sequence Number)字段里。

发送完毕后,客户端进入 SYN_SEND 状态。

  • 第二次握手(SYN=1, ACK=1, seq=y, ACKnum=x+1):

服务器发回确认包(ACK)应答。即 SYN 标志位和 ACK 标志位均为1。服务器端选择自己 ISN 序列号,放到 Seq 域里,同时将确认序号(Acknowledgement Number)设置为客户的 ISN 加1,即X+1。 发送完毕后,服务器端进入 SYN_RCVD 状态。

  • 第三次握手(ACK=1,ACKnum=y+1)

客户端再次发送确认包(ACK),SYN 标志位为0,ACK 标志位为1,并且把服务器发来 ACK 的序号字段+1,放在确定字段中发送给对方,并且在数据段放写ISN的+1

发送完毕后,客户端进入 ESTABLISHED 状态,当服务器端接收到这个包时,也进入 ESTABLISHED 状态,TCP 握手结束。

四次挥手

TCP 的连接的拆除需要发送四个包,因此称为四次挥手(Four-way handshake),也叫做改进的三次握手。客户端或服务器均可主动发起挥手动作,在 socket 编程中,任何一方执行 close() 操作即可产生挥手操作

  • 第一次挥手(FIN=1,seq=x)

假设客户端想要关闭连接,客户端发送一个 FIN 标志位置为1的包,表示自己已经没有数据可以发送了,但是仍然可以接受数据。

发送完毕后,客户端进入 FIN_WAIT_1 状态。

  • 第二次挥手(ACK=1,ACKnum=x+1)

服务器端确认客户端的 FIN 包,发送一个确认包,表明自己接受到了客户端关闭连接的请求,但还没有准备好关闭连接。

发送完毕后,服务器端进入 CLOSE_WAIT 状态,客户端接收到这个确认包之后,进入 FIN_WAIT_2 状态,等待服务器端关闭连接。

  • 第三次挥手(FIN=1,seq=y)

服务器端准备好关闭连接时,向客户端发送结束连接请求,FIN 置为1。

发送完毕后,服务器端进入 LAST_ACK 状态,等待来自客户端的最后一个ACK。

  • 第四次挥手(ACK=1,ACKnum=y+1)

客户端接收到来自服务器端的关闭请求,发送一个确认包,并进入 TIME_WAIT状态,等待可能出现的要求重传的 ACK 包。

服务器端接收到这个确认包之后,关闭连接,进入 CLOSED 状态。

客户端等待了某个固定时间(两个最大段生命周期,2MSL,2 Maximum Segment Lifetime)之后,没有收到服务器端的 ACK ,认为服务器端已经正常关闭连接,于是自己也关闭连接,进入 CLOSED 状态。

三次握手的原因

  • 第一次握手:客户端发送网络包,服务端收到了。 这样服务端就能得出结论:客户端的发送能力、服务端的接收能力是正常的。
  • 第二次握手:服务端发包,客户端收到了。 这样客户端就能得出结论:服务端的接收、发送能力,客户端的接收、发送能力是正常的。不过此时服务器并不能确认客户端的接收能力是否正常。
  • 第三次握手:客户端发包,服务端收到了。 这样服务端就能得出结论:客户端的接收、发送能力正常,服务器自己的发送、接收能力也正常。

四次挥手的原因

客户端发送了 FIN 连接释放报文之后,服务器收到了这个报文,就进入了 CLOSE-WAIT 状态。这个状态是为了让服务器端发送还未传送完毕的数据。

问题: 能通俗的讲一下吗?

计算机通讯与人的通讯本质上没什么区别。我们日常发微信也是通讯,理解了你自己是如何发微信的你就理解了TCP三次握手。

如上图,小明欠我钱,我在微信上找小明要钱,这是步骤

  1. 我发出:小明,你在吗?我是Mlx。(第一次握手,确认对方在不在,并且发送序号Seq为Mlx)
  2. 小明回复:我是小明,我在,干啥?(第二次握手,接收方确认对方在,并且知道对方能找到自己了,收到了这个Seq的序号,并且发送自己的发送序号为小明)
  3. 我回复:在就行,接下来聊还钱的事!(第三次握手,确认对方在,并且确认对方能收到自己消息这个时候就可以谈还钱的事了。并且第三次握手就可以携带数据了)

两次握手可以吗?

显然不行。为啥?

还是上面的例子,你发微信的最后一句话 在就行,聊聊还钱的事一直转圈圈发不出去,你等了很久也没发出去,你想,啊这不对啊, 你又发送了一次。小明看到以后开始和你聊还钱的事情了,正当你们因为关系要好而决定小明过几日在还钱的时候,这句话又发出来了,你说小明这时候看见是啥心理?肯定是觉得刚才不还谈的好好的么,怎么又催一次,决定还钱,和你这个朋友绝交。

四次挥手

你和女朋友聊天,已经晚上十一点了, 你想睡觉了,于是你想停止聊天。

  1. 你: 亲爱的,我想睡觉了(第一次挥手,发送FIN,进入等待女朋友批复的过程也就是FIN_WAIT_1)
  2. 女朋友:知道了,等我把这部剧玩看就睡(第二次挥手,回复ACK),女朋友也知道快睡觉了,倍速播放(进入CLOSE_WAIT状态),收到消息的你此时处于等待女朋友看剧结束的状态(FIN_WAIT_2 )
  3. 过了一会女朋友看完剧了: 亲爱的我看完了,可以睡觉了,晚安哦(第三次挥手,服务器进入等待你说晚安就可以睡觉的阶段)
  4. 你: 好的亲爱的,晚安(第四次挥手,女朋友收到消息知道你也要睡了,然后两个人进入梦乡)

上文说到,客户端等待了某个固定时间(两个最大段生命周期,2MSL,2 Maximum Segment Lifetime)之后,没有收到服务器端的 ACK ,认为服务器端已经正常关闭连接,于是自己也关闭连接,进入 CLOSED 状态。那么什么是等待2MSL呢?

对应于上面的第四步,你发送了晚安以后,有两个情况

  1. 你发送的晚安没发出去,这个时候女朋友见你迟迟不发消息会在通知你一次她可以睡觉了
  2. 你发送的晚安发出去了,女朋友看到以后也不回你了直接就去睡了。

面对上面这两种情况,你都得需要等待,等多久呢?假设微信发消息五分钟发不出去就不发了

那么对于第一种情况,你发送的消息是最迟5分钟会送达对方,否则就送不到,女朋友给你发消息也是5分钟,那么你最长只需要等10分钟就能确认消息是发送成功还是失败了。10分钟正好是最长消息的两倍,即MSL*2 ,2MSL。

问题: 你说TCP是可靠传输,是如何保证可靠的呢?

TCP 使用超时重传来实现可靠传输:如果一个已经发送的报文段在超时时间内没有收到确认,那么就重传这个报文段。

问题: 你用的HTTP是什么版本的?有什么区别吗?

HTTP有这么几个重要的版本 HTTP1.0 HTTP1.1 HTTP2.0

目前HTTP1.1用的比较多,2.0则用的比较少。

http1.0特性
  • 无状态:服务器不跟踪不记录请求过的状态
  • 无连接:浏览器每次请求都需要建立tcp连接
无状态

对于无状态的特性可以借助cookie/session机制来做身份认证和状态记录

无连接

无连接导致的性能缺陷有两种:

1. 无法复用连接

每次发送请求,都需要进行一次tcp连接(即3次握手4次挥手),使得网络的利用率非常低

2. 队头阻塞

http1.0规定在前一个请求响应到达之后下一个请求才能发送,如果前一个阻塞,后面的请求也给阻塞的

http1.1特性

为了解决http1.0的性能缺陷,http1.1出现了

http1.1特性:
  • 长连接:新增Connection字段,可以设置keep-alive值保持连接不断开
  • 管道化:基于上面长连接的基础,管道化可以不等第一个请求响应继续发送后面的请求,但响应的顺序还是按照请求的顺序返回
  • 缓存处理:新增字段cache-control
  • 断点传输
长连接

http1.1默认保持长连接,数据传输完成保持tcp连接不断开,继续用这个通道传输数据

管道化

基于长连接的基础,我们先看没有管道化请求响应:

tcp没有断开,用的同一个通道

请求1 > 响应1 --> 请求2 > 响应2 --> 请求3 > 响应3

管道化的请求响应:

请求1 --> 请求2 --> 请求3 > 响应1 --> 响应2 --> 响应3

即使服务器先准备好响应2,也是按照请求顺序先返回响应1

虽然管道化,可以一次发送多个请求,但是响应仍是顺序返回,仍然无法解决队头阻塞的问题

缓存处理

当浏览器请求资源时,先看是否有缓存的资源,如果有缓存,直接取,不会再发请求,如果没有缓存,则发送请求

通过设置字段cache-control来控制

断点传输

在上传/下载资源时,如果资源过大,将其分割为多个部分,分别上传/下载,如果遇到网络故障,可以从已经上传/下载好的地方继续请求,不用从头开始,提高效率

在 Header 里两个参数实现的,客户端发请求时对应的是 Range 服务器端响应时对应的是 Content-Range

host域

HTTP1.0 不支持,因为之前觉得一台服务器只有一个地址 HTTP2.0 支持,请求消息和响应消息都支持

http2.0特性
  • 二进制分帧
  • 多路复用: 在共享TCP链接的基础上同时发送请求和响应
  • 头部压缩
  • 服务器推送:服务器可以额外的向客户端推送资源,而无需客户端明确的请求
二进制分帧

将所有传输的信息分割为更小的消息和帧,并对它们采用二进制格式的编码

多路复用

基于二进制分帧,在同一域名下所有访问都是从同一个tcp连接中走,http消息被分解为独立的帧,乱序发送,服务端根据标识符和首部将消息重新组装起来

区别

推荐学习资料


  • 脑图
    360°全方位性能调优


    《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》点击传送门,即可获取!
    发送请求和响应
  • 头部压缩
  • 服务器推送:服务器可以额外的向客户端推送资源,而无需客户端明确的请求
二进制分帧

将所有传输的信息分割为更小的消息和帧,并对它们采用二进制格式的编码

多路复用

基于二进制分帧,在同一域名下所有访问都是从同一个tcp连接中走,http消息被分解为独立的帧,乱序发送,服务端根据标识符和首部将消息重新组装起来

区别

推荐学习资料


  • 脑图
    [外链图片转存中…(img-aierJ8VC-1715430020203)]
    [外链图片转存中…(img-5aiIG0I0-1715430020203)]
    [外链图片转存中…(img-C5DiGbS8-1715430020204)]
    《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》点击传送门,即可获取!
  • 14
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值