详解HTTP协议

HTTP 协议,几乎是每个人上网用的第一个协议,同时也是很容易被人忽略的协议。

根据TCP/IP模型,网络分层分为四层,应用层、传输层、网络层、网络接口层(数据链路层,物理层)。HTTP协议属于应用层的一种协议。

http://www.baidu.com这个网址我相信大家都很熟悉,这是个URL,叫作统一资源定位符。之所以叫统一,是因为他格式是固定的,http协议标识,www.baidu.com是一个域名由于IP地址具有不方便记忆并且不能显示地址组织的名称和性质等缺点,人们设计出了域名,并通过网域名称系统(DNS,Domain Name System)来将域名和IP地址相互映射,使人更方便地访问互联网,而不用去记住能够被机器直接读取的IP地址数串),表示互联网中的某一个位置。正因为这个东西是统一的,所以当你在浏览器的输入框中输入这样一个字符串的时候,浏览器就知道如何处理。就像秦始皇统一中国后颁布了书同文、车同轨、统一度量衡,走到哪规格都是一样的,大家都认。

当我们输入网址按下Enter键后,接下来就是发送http请求吗?非也,上面说了域名仅仅只是为了能明确的显示地址的名称与性质,实际上在互联网中还是要把它解析成IP地址的,浏览器会将域名发送给DNS服务器,让它帮忙解析成IP地址,HTTP又是基于TCP协议的,所以发送请求前当然要先建立TCP连接了,经历三次握手后成功建立了TCP连接(关于TCP的三次握手有兴趣的同学可以去查找相关资料)。建立起连接后,浏览器就准备发送HTTP请求了。

目前HTTP协议常用的版本有俩个,HTTP1.1与HTTP2.0。

在1.1版本里面,默认开启Keep_Alive的,这样建立起来的TCP连接可以在多次请求中复用,为什么要保活呢,因为建立TCP连接还是挺费劲的,他要经历三次握手,断开TCP连接也挺费劲的,要经历四次挥手,要是好不容易建立起来的连接,干一丁点儿事情就断开了,岂不是很浪费资源。

构建HTTP请求

请求格式:

sp(空格)  cr(回车)  lf(换行)

 HTTP 的报文大概分为三大部分。第一部分是请求行,第二部分是请求的首部,第三部分才是请求的正文实体

第一部分:请求行

在请求行中,URL 就是 http://www.baidu.com ,版本为 HTTP 1.1。这里要说一下的,就是方法。方法有几种类型,GET、POST、PUT、DELETE。下面介绍比较常用的俩种,GET和POST。

GET:

对于访问网页来讲,最常用的类型就是 GET。顾名思义,GET 就是去服务器获取一些资源。对于访问网页来讲,要获取的资源往往是一个页面。其实也有很多其他的格式,比如说返回一个 JSON 字符串,到底要返回什么,是由服务器端的实现决定的。GET请求也可以传参,参数跟在URL后面,用"?"隔开,如http://www.baidu.com?param=1。

POST:

POST请求往往需要告诉服务器一些比较重要的信息,不想暴露在外面(GET请求的参数是跟在URL后面的),这些信息一般放在正文实体里面,格式多种多样,JSON是比较常见的格式。

第二部分:首部字段

首部是 key value,通过冒号分隔。这里面,往往保存了一些非常重要的字段。如字符集Accept-Charset,防止接收方出现乱码,还有正文格式Content-Type,如果是JSON格式,那这个值就设置成JSON,还可以设置一些关于缓存的东西。

第三部分:正文实体

正文实体就没什么好说的了,就是一些携带的数据。

到目前为止,我们就把HTTP报文格式拼凑起来了,接下来我们要把这个报文交给传输层。

HTTP 请求的发送

由于HTTP是基于TCP协议的,所以它是面向连接的请求,通过二进制流的方式传输。TCP会把二进制流换成一个个报文段的形式发送出去。在发送给每个报文段的时候,都需要对方有一个回应 ACK,来保证报文可靠地到达了对方。如果没有回应,那么 TCP 这一层会进行重新传输,直到可以到达。同一个包有可能被传了好多次,但是 HTTP 这一层不需要知道这一点,因为是 TCP 这一层在埋头苦干。

每一个TCP报文都需要加上自己的地址和目标地址,将这俩个信息放在IP头里,接下来就交给IP层发挥了。IP层首先看看目标地址是不是和自己在同一个局域网内,如果在,就用ARP协议获取目标地址的MAC地址,然后将自己的MAC地址和目标MAC地址放入MAC头里,发送出去就可以了;如果不在同一个局域网,这时候就要发送去网关,想要发送到网关,那么就要用ARP协议获取网关的MAC地址,然后将自己的MAC地址和网关的MAC地址放入MAC头里,就可以发送出去了。

网关收到包发现 MAC 符合,取出目标 IP 地址,根据路由协议找到下一跳的路由器,获取下一跳路由器的 MAC 地址,将包发给下一跳路由器。就这样一跳一跳的最终来到了目标地址的局域网,这个时候,最后一跳的路由器能够发现,目标地址就在自己的某一个出口的局域网上。于是,在这个局域网上发送 ARP,获得这个目标地址的 MAC 地址,将包发出去。目标的机器发现 MAC 地址符合,就将包收起来;发现 IP 地址符合,根据 IP 头中协议项,知道自己上一层是 TCP 协议,于是解析 TCP 的头,里面有序列号,需要看一看这个序列包是不是我要的,如果是就放入缓存中然后返回一个 ACK,如果不是就丢弃。

TCP 头里面还有端口号,HTTP 的服务器正在监听这个端口号。于是,目标机器自然知道是 HTTP 服务器这个进程想要这个包,于是将包发给 HTTP 服务器。HTTP 服务器的进程看到,原来这个请求是要访问一个网页,于是就把这个网页发给客户端。

到这里,请求的过程就结束了。

HTTP 返回的构建

看结构图会发现结构跟请求的结构差不多,请求行换成了状态行,状态码会反映 HTTP 请求的结果。“200”意味着大吉大利今晚吃鸡;而我们最不想见的,可能就是“404”,也就是“服务端无法响应这个请求”。然后,短语会大概说一下原因。

HTTP 2.0

当然 HTTP 协议也在不断的进化过程中,在 HTTP1.1 基础上便有了 HTTP 2.0。

HTTP 1.1 在应用层以纯文本的形式进行通信。每次通信都要带完整的 HTTP 的头,而且不考虑 pipeline 模式的话,每次的过程总是像上面描述的那样一去一回。这样在实时性、并发性上都存在问题。为了解决这些问题,HTTP 2.0 会对 HTTP 的头进行一定的压缩,将原来每次都要携带的大量 key value 在两端建立一个索引表,对相同的头只发送索引表中的索引。

另外,HTTP 2.0 协议将一个 TCP 的连接中,切分成多个流,每个流都有自己的 ID,而且流可以是客户端发往服务端,也可以是服务端发往客户端。它其实只是一个虚拟的通道。流是有优先级的。HTTP 2.0 还将所有的传输信息分割为更小的消息和帧,并对它们采用二进制格式编码。常见的帧有 Header 帧,用于传输 Header 内容,并且会开启一个新的流。再就是 Data 帧,用来传输正文实体。多个 Data 帧属于同一个流。通过这两种机制,HTTP 2.0 的客户端可以将多个请求分到不同的流中,然后将请求内容拆成帧,进行二进制传输。这些帧可以打散乱序发送, 然后根据每个帧首部的流标识符重新组装,并且可以根据优先级,决定优先处理哪个流的数据。

我们来举一个例子。假设我们的一个页面要发送三个独立的请求,一个获取 css,一个获取 js,一个获取图片 jpg。如果使用 HTTP 1.1 就是串行的,但是如果使用 HTTP 2.0,就可以在一个连接里,客户端和服务端都可以同时发送多个请求或回应,而且不用按照顺序一对一对应。

HTTP 2.0 其实是将三个请求变成三个流,将数据分成帧,乱序发送到一个 TCP 连接中。

HTTP 2.0 成功解决了 HTTP 1.1 的队首阻塞问题,同时,也不需要通过 HTTP 1.x 的 pipeline 机制用多条 TCP 连接来实现并行请求与响应;减少了 TCP 连接数对服务器性能的影响,同时将页面的多个数据 css、js、 jpg 等通过一个数据链接进行传输,能够加快页面组件的传输速度。

HTTP 3.0

HTTP3.0的核心是QUIC协议,Google在2015年提出,传统的HTTP协议是基于TCP进行传输的,而QUIC是基于UDP进行传输的。可以理解为HTTP3.0基于UDP的安全可靠的HTTP2.0协议。由于用的还不广泛,这里不作过多介绍,有兴趣的朋友可以自行查找相关资料进行了解。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

·码上修·

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值