简介

  1. HTTP 协议,是 Hyper Text Transfer Protocol(超文本传输协议)的缩写,是用于从万维网(WWW:World Wide Web )服务器传输超文本到本地浏览器的传送协议。
  1. HTTP 是一个无状态的协议。**无状态是指客户机(Web 浏览器)和服务器之间不需要建立持久的连接,这意味着当一个客户端向服务器端发出请求,然后服务器返回响应(response),连接就被关闭了,在服务器端不保留连接的有关信息。**HTTP 遵循请求(Request)/应答(Response)模型。客户机(浏览器)向服务器发送请求,服务器处理请求并返回适当的应答。所有 HTTP 连接都被构造成一套请求和应答。

主要特点如下:

  • 简单快速:客户向服务器请求服务时,只需传送请求方法和路径。请求方法常用的有 GET、HEAD、POST 等等。每种方法规定了客户与服务器联系的类型不同。由于 HTTP 协议简单,使得 HTTP 服务器的程序规模小,因而通信速度很快。
  • 数据格式灵活:HTTP 允许传输任意类型的数据对象。正在传输的类型由Content-Type 加以标记。
  • 无连接:无连接的含义是限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接。采用这种方式可以节省传输时间。

    主要指的是不使用 Keep-Alive 机制的情况下。

  • 无状态:HTTP 协议是无状态协议。无状态,是指协议对于事务处理没有记忆能力。无状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大。另一方面,在服务器不需要先前信息时它的应答就较快。

    无状态,所以更容易做服务的扩容,支撑更大的访问量。

  • 支持 B/S 及 C/S 模式。

    另外,HTTP 协议已经不仅仅使用在浏览器上。在前后端分离的架构中,又或者微服务架构的内部通信中,HTTP 因为其数据格式的通用性,和语言无关,被大规模使用。

HTTP 基本格式

详细的,可以看看 《猫哥网络编程系列:详解 BAT 面试题》 文章。

🦅 HTTP 请求格式

image.png

  • 请求行:用来说明请求类型,要访问的资源以及所使用的 HTTP 版本。
  • 请求头部:紧接着请求行(即第一行)之后的部分,用来说明服务器要使用的附加信息从第二行起为请求头部。
    • HOST ,将指出请求的目的地。
    • User-Agent ,服务器端和客户端脚本都能访问它,它是浏览器类型检测逻辑的重要基础。该信息由你的浏览器来定义,并且在每个请求中自动发送等等
  • 空行:请求头部后面的空行是必须的。
  • 请求数据:也叫主体,可以添加任意的其他数据。

    HTTP 响应格式


    image.png

  • 状态行:由 HTTP 协议版本号、状态码、状态消息三部分组成。

  • 消息报头:用来说明客户端要使用的一些附加信息。
  • 空行:消息报头后面的空行是必须的。
  • 响应正文:服务器返回给客户端的文本信息。

    URI 和 URL 的区别

    1. URI

    Web上可用的每种资源如HTML文档、图像、视频片段、程序等都是一个来URI来定位的; URI一般由三部组成:

    ①访问资源的命名机制 ②存放资源的主机名 ③资源自身的名称,由路径表示,着重强调于资源。

2. URL

URL是Internet上用来描述信息资源的字符串,主要用在各种WWW客户程序和服务器程序上,特别是著名的Mosaic。 采用URL可以用一种统一的格式来描述各种信息资源,包括文件、服务器的地址和目录等。 URL一般由三部组成

①协议(或称为服务方式) ②存有该资源的主机IP地址(有时也包括端口号) ③主机资源的具体地址。如目录和文件名等

《URI 和 URL 的区别》 文章。

HTTP 协议请求方法

  • GET: 对服务器资源的简单请求。
  • POST: 用于发送包含用户提交数据的请求。
  • HEAD:类似于 GET 请求,不过返回的响应中没有具体内容,用于获取报头。
  • PUT:传说中请求文档的一个版本。
  • DELETE:发出一个删除指定文档的请求。
  • TRACE:发送一个请求副本,以跟踪其处理进程。
  • OPTIONS:返回所有可用的方法,检查服务器支持哪些方法。
  • CONNECT:用于 SSL 隧道的基于代理的请求。

    GET 和 POST 的区别

    | 请求方式 | 数据位置 | 明文密文 | 数据安全 | 长度限制 | 应用场景 | | —- | —- | —- | —- | —- | —- | | GET | HTTP 请求的 path 中 | 明文 | 不安全 | 长度较小,一般 2k | 查询数据 | | POST | HTTP 请求 body 中 | 可明可密 | 安全 | 支持较大数据传输 | 修改数据 |

  • GET在浏览器回退时是无害的,而POST会再次提交请求。

  • GET产生的URL地址可以被添加到书签,而POST不可以。
  • GET请求会被浏览器主动cache,而POST不会,除非手动设置。
  • GET请求只能进行url编码,而POST支持多种编码方式。
  • GET请求参数会被完整保留在浏览器历史记录里,而POST中的参数不会被保留。
  • GET请求在URL中传送的参数是有长度限制的,而POST没有。
  • 对参数的数据类型,GET只接受ASCII字符,而POST没有限制。
  • GET比POST更不安全,因为参数直接暴露在URL上,所以不能用来传递敏感信息。
  • GET参数通过URL传递,POST放在Request body中。
  • GET 请求可被缓存;POST 请求不会被缓存。
  • GET 请求可被收藏为书签;POST 不能被收藏为书签。
  • 参见 《99%的人理解错 HTTP 中 GET 与 POST 的区别》
    • 对于 GET 方式的请求,浏览器会把 HTTP header 和 data 一并发送出去,服务器响应 200(返回数据)。
    • 而对于 POST,浏览器先发送 header ,服务器响应 100 continue ,浏览器再发送 data ,服务器响应 200 ok(返回数据)。
    • 本质上来说:get和post本质上都是基于TCP/IP的HTTP协议的请求方式,也就是说这两者本质上TCP连接。此外,要注意:==GET产生一个TCP数据包;POST产生两个TCP数据包。==

    也就是说,GET 只需要汽车跑一趟就把货送到了,而 POS T得跑两趟,第一趟,先去和服务器打个招呼“嗨,我等下要送一批货来,你们打开门迎接我”,然后再回头把货送过去。 ps:不过要注意,POST 具体发几次,也和浏览器的实现有关系。例如:Firefox 只发一次。 ps2:据研究,在网络环境好的情况下,发一次包的时间和发两次包的时间差别基本可以无视。而在网络环境差的情况下,两次包的 TCP 在验证数据包完整性上,有非常大的优点。

HTTP相关状态码

  • 1×× : 请求处理中,请求已被接受,正在处理
  • 2×× : 请求成功,请求被成功处理
    • 200 OK // 客户端请求成功
  • 3×× : 重定向,要完成请求必须进行进一步处理
    • 301 Moved Permanently // 永久重定向,使用域名跳转
    • 302 Found // 临时重定向,未登陆的用户访问用户中心重定向到登录页面
  • 4×× : 客户端错误,请求不合法
    • 400 Bad Request // 客户端请求有语法错误,不能被服务器所理解
    • 401 Unauthorized // 请求未经授权,这个状态代码必须和 WWW-Authenticate 报头域一起使用
    • 403 Forbidden // 服务器收到请求,但是拒绝提供服务
    • 404 Not Found // 请求资源不存在,eg:输入了错误的 URL
  • 5×× : 服务器端错误,服务器不能处理合法请求
    • 500 Internal Server Error // 服务器发生不可预期的错误
    • 502 Bad Gateway //作为网关或者代理工作的服务器尝试执行请求时,从上游服务器接收到无效的响应。
    • 503 Server Unavailable // 服务器当前不能处理客户端的请求,一段时间后可能恢复正常
    • 504 Gateway Time-out //网关超时,这个有时候Nginx会抛出的异常,主要原因是请求超时,比如你想导出下载某个文件,结果文件太大,就可能请求超时了。

完整的状态码列表,可以看看 《HTTP 状态码》 文章。

forward 和 redirect 的区别

forward(转发): 是服务器请求资源,服务器直接访问目标地址的URL,把那个URL的响应内容读取过来,然后把这些内容再发给浏览器。浏览器根本不知道服务器发送的内容从哪里来的,因为这个跳转过程实在服务器实现的,并不是在客户端实现的所以客户端并不知道这个跳转动作,所以它的地址栏还是原来的地址. redirect(重定向)是服务端根据逻辑,发送一个状态码,告诉浏览器重新去请求那个地址.所以地址栏显示的是新的URL.

==转发是服务器行为,重定向是客户端行为。==

区别

  1. 从地址栏显示来说 forward是服务器请求资源,服务器直接访问目标地址的URL,把那个URL的响应内容读取过来,然后把这些内容再发给浏览器,浏览器根本不知道服务器发送的内容从哪里来的,所以它的地址栏还是原来的地址.
    redirect是服务端根据逻辑,发送一个状态码,告诉浏览器重新去请求那个地址.所以地址栏显示的是新的URL.
  2. 从数据共享来说forward:转发页面和转发到的页面可以共享request里面的数据.redirect:不能共享数据.
  3. 从运用地方来说forward:一般用于用户登陆的时候,根据角色转发到相应的模块.redirect:一般用于用户注销登陆时返回主页面和跳转到其它的网站等
  4. 从效率来说 forward:高. redirect:低.

    本质区别

    转发过程:

    客户浏览器发送http请求——》web服务器接受此请求—》调用内部的一个方法在容器内部完成请求处理和转发动作——》将目标资源发送给客户;在这里,转发的路径必须是同一个web容器下的url,其不能转向到其他的web路径上去,中间传递的是自己的容器内的request。在客户浏览器路径栏显示的仍然是其第一次访问的路径,也就是说客户是感觉不到服务器做了转发的。转发行为是浏览器只做了一次访问请求。

    重定向过程:

    客户浏览器发送http请求——》web服务器接受后发送302状态码响应及对应新的location给客户浏览器—》客户浏览器发现是302响应,则自动再发送一个新的http请求,请求url是新的location地址——》服务器根据此请求寻找资源并发送给客户。在这里 location可以重定向到任意URL,既然是浏览器重新发出了请求,则就没有什么request传递的概念了。在客户浏览器路径栏显示的是其重定向的路径,客户可以观察到地址的变化的。重定向行为是浏览器做了至少两次的访问请求的。

    重定向,其实是两次request: ==第一次,客户端request A,服务器响应,并response回来,告诉浏览器,你应该去B。这个时候IE可以看到地址变了,而且历史的回退按钮也亮了。重定向可以访问自己web应用以外的资源。在重定向的过程中,传输的信息会被丢失==。

详细的,请看 《请求转发(Forward)和重定向(Redirect)的区别》

状态码301 与 302 的区别

301,302 都是 HTTP 状态的编码,都代表着某个 URL 发生了转移,不同之处在于:

  • 301 redirect: 301 代表永久性转移(Permanently Moved)。
  • 302 redirect: 302 代表暂时性转移(Temporarily Moved)。

详细的,请看 《HTTP 返回码中 301 与 302 的区别》 文章。

HTTP、TCP、Socket 的关系

  • TCP/IP 代表传输控制协议/网际协议,指的是一系列协议族。
  • HTTP 本身就是一个协议,是从 Web 服务器传输超文本到本地浏览器的传送协议。
  • Socket 是 TCP/IP 网络的 API ,其实就是一个门面模式,它把复杂的 TCP/IP 协议族隐藏在 Socket 接口后面。对用户来说,一组简单的接口就是全部,让 Socket 去组织数据,以符合指定的协议。

综上所述:

  • 需要 IP 协议来连接网络
  • TCP 是一种允许我们安全传输数据的机制,使用 TCP 协议来传输数据的 HTTP 是 Web 服务器和客户端使用的特殊协议。
  • HTTP 基于 TCP 协议,所以可以使用 Socket 去建立一个 TCP 连接。

    Cookies 和 Session 的区别

  • Session 在服务器端,Cookie 在客户端(浏览器)。

    ==Session 默认被存在在服务器的一个文件里(不是内存)。==

  • Session 的运行依赖 sessionid ,而 sessionid 是存在 Cookie 中的,也就是说,如果浏览器禁用了 Cookie ,同时 session 也会失效。但是,可以通过其它方式实现,比如在 url 参数中传递 sessionid 。

  • Session 可以放在文件、数据库、或内存中都可以。
  • 【关键】用户验证这种场合一般会用 Session

参照:https://blog.csdn.net/striveb/article/details/82469253#Session%E4%B8%8ECookie%E5%8C%BA%E5%88%AB

【重要】一次完整的 HTTP 请求所经历的步骤

这里的客户端,更多指的是浏览器。

  • 1、DNS 解析(通过访问的域名找出其 IP 地址,递归搜索)。

    如用客户端浏览器请求这个页面:http://localhost.com:8080/index.htm 从中分解出协议名、主机名、 端口、对象路径等部分,对于我们的这个地址,解析得到的结果如下: 协议名:http 主机名:localhost.com 端口:8080 对象路径:/index.htm 在这一步,需要域名系统 DNS 解析域名 localhost.com,得主机的 IP 地址。

  • 2、HTTP 请求,当输入一个请求时,建立一个 Socket 连接发起 TCP的 3 次握手。

    把以上部分结合本机自己的信息,封装成一个 HTTP 请求数据包。 如果是 HTTPS 请求,会略微有不同。

  • 3、客户端发送请求

    • 3.1 客户端向服务器发送请求命令(一般是 GET 或 POST 请求)。

      客户端的网络层不用关心应用层或者传输层的东西,主要做的是通过查找路由表确定如何到达服务器,期间可能经过多个路由器,这些都是由路由器来完成的工作,无非就是通过查找路由表决定通过那个路径到达服务器。 ==客户端的链路层,包通过链路层发送到路由器,通过邻居协议查找给定 IP 地址的 MAC 地址,然后发送 ARP 请求查找目的地址,如果得到回应后就可以使用 ARP 的请求应答交换的 IP 数据包现在就可以传输了,然后发送 IP 数据包到达服务器的地址。== 客户机发送请求命令:建立连接后,客户机发送一个请求给服务器,请求方式的格式为:统一资源标识符(URL)、协议版本号,后边是 MIME 信息包括请求修饰符、客户机信息和可内容。

    • 3.2客户端发送请求头信息和数据。

  • 4.1、服务器发送应答头信息。

    服务器接到请求后,给予相应的响应信息,其格式为一个状态行,包括信息的协议版本号、一个成功或错误的代码,后边是 MIME 信息包括服务器信息、实体信息和可能的内容。

  • 4.2、服务器向客户端发送数据。

  • 5、服务器关闭 TCP 连接(4次挥手)。

    这里是否关闭 TCP 连接,也根据 HTTP Keep-Alive 机制有关。同时,客户端也可以主动发起关闭 TCP 连接。 ==如果浏览器或者服务器在其头信息加入了这行代码 Connection:keep-alive,TCP 连接在发送后将仍然保持打开状态,于是,浏览器可以继续通过相同的连接发送请求。保持连接节省了为每个请求建立新连接所需的时间,还节约了网络带宽。==

Http - 图3

  • 6、客户端根据返回的 HTML、CSS、JS 进行渲染。

如下是《图解HTTP》提供的图片:

image.png

HTTP1.0 和 HTTP1.1的区别

主要是如下 8 点:

  • 1、可扩展性
  • 2、缓存
  • 3、带宽优化

    带来了分块传输 HTTP/1.1中在请求消息中引入了range头域,它允许只请求资源的某个部分。在响应消息中Content-Range头域声明了返回的这部分对象的偏移值和长度。如果服务器相应地返回了对象所请求范围的内容,则响应码为206(Partial Content),它可以防止Cache将响应误以为是完整的一个对象。 HTTP/1.1加入了一个新的状态码100(Continue)。客户端事先发送一个只带头域的请求,如果服务器因为权限拒绝了请求,就回送响应码401(Unauthorized);如果服务器接收此请求就回送响应码100,客户端就可以继续发送带实体的完整请求了。注意,HTTP/1.0的客户端不支持100响应码。但可以让客户端在请求消息中加入Expect头域,并将它的值设置为100-continue。

  • 【最重要】4、长连接

    1. HTTP 1.1支持长连接(PersistentConnection)和请求的流水线(Pipelining)处理,**在一个TCP连接上可以传送多个HTTP请求和响应,减少了建立和关闭连接的消耗和延迟。**例如:一个包含有许多图像的网页文件的多个请求和应答可以在一个连接中传输,但每个单独的网页文件的请求和应答仍然需要使用各自的连接。
    2. ==HTTP 1.1还允许客户端不用等待上一次请求结果返回,就可以发出下一次请求,但服务器端必须按照接收到客户端请求的先后顺序依次回送响应结果,以保证客户端能够区分出每次请求的响应内容,这样也显著地减少了整个下载过程所需要的时间。==
    3. HTTP/1.0中,要建立长连接,可以在请求消息中包含Connection: Keep-Alive头域,**如果服务器愿意维持这条连接,在响应消息中也会包含一个Connection: Keep-Alive的头域。**同时,可以加入一些指令描述该长连接的属性,如maxtimeout等。
  • 5、消息传递

  • 6、Host 头域
  • 7、错误提示
  • 8、内容协商

详细的每一点的说明,可以看 《HTTP1.0 与 HTTP1.1 的区别》 文章,特别是第 4 点【长连接】。

HTTP1.1 支持长连接(PersistentConnection)和请求的流水线(Pipelining)。

  • 长连接(PersistentConnection):处理在一个 TCP 连接上可以传送多个 HTTP 请求和响应,减少了建立和关闭连接的消耗和延迟。==在 HTTP1.1中 默认开启Connection:keep-alive ,一定程度上弥补了 HTTP1.0 每次请求都要创建连接的缺点。==
  • 请求的流水线(Pipelining):==HTTP1.1 还允许客户端不用等待上一次请求结果返回,就可以发出下一次请求,但服务器端必须按照接收到客户端请求的先后顺序依次回送响应结果,以保证客户端能够区分出每次请求的响应内容,这样也显著地减少了整个下载过程所需要的时间。==

推荐,在看看 《HTTP Keep-Alive 是什么?如何工作?》 文章。 关于这一点,可能演变的问题有:

  • HTTP 的长连接是什么意思?
  • HTTP Keep-Alive 机制是什么?
  • HTTP Keep-Alive 机制和 TCP Keep-Alive 有什么区别?

SPDY 是什么?

HTTP Working-Group 最终决定以 SPDY/2 为基础,开发 HTTP/2 。

2012 年,Google 如一声惊雷提出了 SPDY 的方案,优化了 HTTP1.X 的请求延迟,解决了 HTTP1.X 的安全性,具体如下:

  • 1、降低延迟

    针对 HTTP 高延迟的问题,SPDY 优雅的采取了多路复用(multiplexing)。多路复用通过多个请求 Stream 共享一个 Tcp连 接的方式,解决了 HOL blocking 的问题,降低了延迟同时提高了带宽的利用率。

  • 2、请求优先级(request prioritization)

    多路复用带来一个新的问题是,在连接共享的基础之上有可能会导致关键请求被阻塞。SPDY 允许给每个 request 设置优先级,这样重要的请求就会优先得到响应。 比如浏览器加载首页,首页的 html 内容应该优先展示,之后才是各种静态资源文件,脚本文件等加载,这样可以保证用户能第一时间看到网页内容。

  • 3、header 压缩

    前面提到 HTTP1.x 的 header 很多时候都是重复多余的。选择合适的压缩算法可以减小包的大小和数量。

  • 4、基于 HTTPS 的加密协议传输

    大大提高了传输数据的安全性。

  • 5、服务端推送(server push)

    采用了 SPDY 的网页,例如我的网页有一个 sytle.css 的请求,在客户端收到 sytle.css 数据的同时,服务端会将 sytle.js 的文件推送给客户端。当客户端再次尝试获取 sytle.js 时就可以直接从缓存中获取到,不用再发请求了。 和我们理解的服务端推送,有点(非常)不一样哈。

SPDY 构成图如下:

image.png

  • SPDY 位于 HTTP 之下,TCP 和 SSL 之上,这样可以轻松兼容老版本的 HTTP 协议(将 HTTP1.x 的内容封装成一种新的 frame 格式),同时可以使用已有的 SSL 功能。