前言
本文主要说的是HTTP1.0,一次 HTTP 请求的整个过程包括:
- DNS 解析。
- 建立 TCP 连接。
- HTTP的请求和响应。
- 断开 TCP 连接。
本文主要从以上几个方面来讲解一次完整的 HTTP 请求。
流程示列
- 对www.baidu.com这个网址进行DNS域名解析,得到对应的IP地址
- 根据这个IP,找到对应的服务器,发起TCP的三次握手
- 建立TCP连接后发起HTTP请求
- 服务器响应HTTP请求,浏览器得到html代码 浏览器解析html代码
- 浏览器对页面进行渲染呈现给用户
- 服务器关闭关闭TCP连接
DNS解析
DNS 是应用层协议,端口号53,事实上他是为其他应用层协议工作的,URL中的域名需要解析成IP地址才能与远程主机建立连接,如何将域名解析成IP地址就属于DNS解析的工作。
DNS域名结构层次
我们经常听到有人说「顶级域名」、「一级域名」、「二级域名」等概念,域名级别究竟是怎么划分的呢?
- 根域名
比如:www.baidu.com 真正的域名是 www.baidu.com.root,简写为www.baidu.com.,又因为根域名.root对于所有域名都是一样的,所以平时是省略的,最终就变成了我们常见的样子。
- 顶级域名
根域名的下一级叫做顶级域名(缩写为 TLD),也叫做一级域名,常见的如 .com / .net / .org / .cn 等等,用来指示某个国家/地区或组织使用的名称的类型名称。
- 二级域名
个人或组织在Internet上使用的名称的类型名称,比如 baidu.com。这是我们能够购买和注册的最高级域名。
- 主机名(host)
次级域名之下,就是主机名(host),也可以称为三级域名,比如 www.baidu.com,由此往下,基本上 N 级域名就是在 N-1 级域名前追加一级
主机名.次级域名.顶级域名.根域名
www.baidu.com.root
DNS域名服务器类型
- 根域名服务器:
最高层次的域名服务器,也是最重要的域名服务器。所有的根域名服务器都知道所有的顶级域名服务器的域名和IP地址。在很多情况下,根域名服务器并不直接把待查询域名直接解析成IP地址,而是告诉本地域名服务器下一步应当找哪一个顶级域名服务器进行查询
- 顶级域名服务器
负责管理在该顶级域名服务器注册的二级域名。
- 权限域名服务器:
负责一个“区”的域名服务。一个服务器所负责管辖的(或有权限的)范围叫做区.每一个区设置相应的权限域名服务器
- 本地域名服务器(LDNS):
它不属于域名服务器的层次结构,但是它对域名系统非常重要。当一个主机发出DNS查询请求时,这个查询请求报文首先是发送给本地域名服务器,比如学校的网
DNS解析流程
这里我分为2个大的步骤
- 本地解析:主机www.baidu.com先向本地域名服务器dns.baidu.com进行【递归查询】
- 远程解析:本地域名服务器LDNS采用【迭代查询】。它向一个根域名服务器进行迭代查询
DNS解析=本地解析+远程解析
- 本地解析详细步骤:
- 【浏览器缓存】:浏览器会检查缓存中有没有域名对应的ip地址,这个缓存是有过期时长的,一般是几分钟到几小时不等。
- 【系统缓存】:如果浏览器缓存没有,那么就检查操作系统的hosts文件。
- 【LDNS缓存】向本地域名服务器LDNS发起域名解析的请求。如果你是通过学校连接互联网的一般是你学校的DNS服务器,如果你是在小区连接互联网的一般是网络提供商比如电信,联通的DNS服务器,DNS服务器通常不会太远。
- 远程解析详细步骤
- 【根域名解析服务器】:如果LDNS也不能解析,向根域名解析服务器发起域名解析请求。全球仅有13台根域名服务器
- 【顶级域名服务器】:根域名服务器会给本地域名服务器LDNS一个所查询的主域名服务器(gTLD)地址,gTLD是国际顶级域名服务器,比如.com,.cn,.org等
- 本地域名服务器LDNS再向上一步返回的gLTD服务器发送请求
- 【权限域名服务器】:gTLD服务器接收请求并返回权限服务器(Name Sever),gTLD服务器接收本地域名服务器发起的请求,并根据需要解析的域名,找到该域名对应的权限域名服务器
- 【域名和IP映射查询】:权限域名服务器会查询存储的域名和ip的映射关系表,将ip连同一个TTL值返回给DNS Server域名服务器(LDNS)。
- 【LDNS缓存】:LDNS拿到ip和TTL会缓存起来,缓存时间由TTL值控制。
- 【返回结果和本地缓存】:同时将该结果反馈给客户端,客户端通过这个IP地址与web服务器建立链接,同时用户根据TTL值缓存在本地系统缓存中。
递归查询和迭代查询的区别
- 递归查询
如果主机所询问的本地域名服务器不知道被查询的域名的IP地址,那么本地域名服务器就以DNS客户的身份,向其它根域名服务器继续发出查询请求报文(即替主机继续查询),而不是让主机自己进行下一步查询
- 迭代查询
当根域名服务器收到本地域名服务器发出的迭代查询请求报文时,要么给出所要查询的IP地址,要么告诉本地服务器:“你下一步应当向哪一个域名服务器进行查询”。然后让本地服务器进行后续的查询
总结:
- 主机向本地域名服务器的查询一般都是采用递归查询。
- 本地域名服务器向根域名服务器的查询通常是采用迭代查询
建立 TCP 连接
TCP/IP的模型
TCP 报文包 = TCP 头信息 + TCP 数据体,而在 TCP 头信息中包含了 6 种控制位,这六种标志位就代表着 TCP 连接的状态:
- SYN:表示请求建立一个连接(同步序号)
- URG:紧急数据(urgent data)—这是一条紧急信息
- ACK:确认已收到(确认序号)
- PSH:尽可能快地将数据送往接收进程
- RST:表示要求对方重新建立连接
- FIN:表示通知对方本端已经完成数据发送,要关闭连接了
TCP/IP 四层模型如下:
TCP连接之3次握手
HTTP 是一个基于 TCP/IP 协议簇来传递数据。TCP/IP 协议在进行连接的时候都需要进行三次握手,所以 HTTP 在连接服务器的时候也需要进行三次握手
- 握手流程
-
客服端向服务端发出 连接请求报文段(也就是SYN报文段,其SYN标志被置位) 设置首部中的同步位 SYN = 1 ,同时随机选择一个初始序号 seq = x。TCP规定,SYN 报文段(即 SYN = 1 的报文段) 不能携带数据,但要消耗掉一个序号,
-
服务器收到连接请求报文段后,如同意建立连接,则向客户端发送确认,在确认报文段(SYN+ACK段)中应把 SYN 位和 ACK 位都置1,确认号是 ack = x + 1,表示服务端希望从客户端这边接收数据的序列号。同时也为自己随机选择一个初始序号 seq = y。这个报文段也不能携带数据,但同样要消耗掉一个序号
-
客户端收到服务器发送的确认后,还要再次向服务端给出确认。确认报文段的ACK置1,确认号 ack = y + 1.而自己的序号 seq = x + 1,TCP的标准规定,ACK报文段可以携带数据,但如果不携带数据则不消息序号,在这种情况下,下一个数据报文段的序号仍是seq = x + 1。这是TCP连接已经建立,客户端进入ESTABLISHED(已建立连接)状态,服务端收到确认后,也进入 ESTABLISHED 状态。
- ❓❓❓为什么是3次握手
知乎上这个列子比较接地气
三次握手这个说法不好,其实是双方各一次握手,各一次确认,其中一次握手和确认合并在一起,是为了确认双方都有收发数据的能力,二次握手达不到目的,四次多余。
HTTP请求和响应
三次握手之后,客户端和服务端的连接就已经建立好了,客户端就可以向服务器端发送 HTTP 请求。
报文结构
HTTP的请求报文与响应报文结构一样,都是分为报文首部和报文主体部分,请求报文中的主体部分主要发送给服务端的数据,而响应报文中的主体则是客户端需要的响应数据
【TCP 数据体 = HTTP 请求报文】
- 请求报文和响应报文的首部内容又由以下内容组成:
- 请求行:包含用于请求的方法,请求URI和HTTP版本
- 状态行: 包含表明响应结果的状态码,原因短语和HTTP版本
- 首部字段: 包含表示请求和响应的各种条件和属性的各类首部。
- 其他: 包含HTTP的RFC里未定义的首部(Cookie)等
HTTP请求响应实列
断开TCP连接
TCP连接之四次挥手
- 挥手流程
- 客户端认为数据发送完成,则它需要向服务端发送连接释放请求。该请求只有报文头,头中携带的主要参数为:
FIN=1,seq=u。此时,客户将进入FIN-WAIT-1状态。 - 服务端收到连接释放报文段后即发出确认,此时服务端进入CLOSE-WAIT状态,并向客户端发送连接释放的应答。客户端收到该应答,进入FIN-WAIT-2状态,等待服务端发送连接释放请求
- 服务端已经没有向客户端发送的数据了,向客户端发送连接释放请求,请求头:FIN=1,ACK=1,seq=w,ack=u+1。服务端便进入LAST-ACK状态。
- 客户端收到服务端的连接释放报文后,向服务端发送确认应答,此时A进入TIME-WAIT状态。然后进入TIME-WAIT(时间等待)状态。这时,TCP连接还没有释放掉,等待时间计数器设置的时间 2MSL后,客户端才进入到CLOSED状态
- ❓❓❓为什么客户端要先进入TIME-WAIT状态,等待2MSL时间后才进入CLOSED状态
为了保证服务端能收到客户端的确认应答。 若客户端发完确认应答后直接进入CLOSED状态,那么如果该应答丢失,服务端等待超时后就会重新发送连接释放请求,但此时客户端已经关闭了,不会作出任何响应,因此服务端永远无法正常关闭
- ❓❓❓为什么是4次挥手
客户端先向服务端发送关闭请求,表示客户端不再发送数据了,服务端确认,但是,此时服务端还可以接着向客户端发送消息,待服务端没有数据传送时,此时服务端也向客户端发送关闭请求,然后客户端确认。
长链接和短链接
- HTTP/1.0 版本的时候,客户端与服务器完成一个请求/响应之后,会将之前建立的 TCP 连接断开,下次请求的时候又要重新建立 TCP 连接, 这也就是短连接。
- 在 HTTP1.0 发布仅半年后(1997年1月) ,HTTP/1.1 版本发布并带来一个新的功能:在客户端与服务器完成一次请求/响应之后,允许不断开 TCP 连接, 这意味着下次请求就直接使用这个 TCP 连接而不需要重新握手建立新连接,这也被称为长连接
长连接是指一次TCP连接允许多次HTTP会话,HTTP永远都是一次请求/响应,会话结束,HTTP本身不存在长连接之说.
总结
思考:在服务器响应完毕后,一次会话就结束了,这时候连接会断开么?
是否断开,我们需要根据 HTTP 版本来确定,目前在浏览器在请求时请求头中都会携带一个参数:Connection:keep-alive,这表示浏览器要求与服务器建立长连接, 而服务器也可以设置是否愿意建立长连接
参考: