前言
本章想通过一次http请求过程,分析总结下相关的知识点。
请求过程
先概括一下整个请求过程:
- 当输入一个网址后,浏览器会进行域名解析,找到对应的IP地址
- 浏览器通过IP找到对应服务器请求建立连接
- 建立连接后就会发送请求给服务器
- 服务器返回响应结果
- 断开连接
DNS解析
DNS解析会把输入的域名映射到对应的IP地址上,然后通过IP地址找到服务器。
其目的就是为了方便大众使用,有规律的域名更方便用户记忆。
域名系统(英文:Domain Name System,缩写:DNS)是互联网的一项服务。
它作为将域名和IP地址相互映射的一个分布式数据库,能够使人更方便地访问互联网。
DNS使用UDP端口53。当前,对于每一级域名长度的限制是63个字符,域名总长度则不能超过253个字符。
— 摘自百度百科
TCP三次握手
在得到服务器IP地址后,客户端就需要发起请求连接,通过TCP三次握手与服务器建立连接。
第一次握手:客户端发送请求,
标志位SYN=1,seq=seqC(随机数)
第二次握手:服务端响应新建连接请求,
标志位SYN=1,标志位ACK=1,ack=seqC+1,seq=seqS(随机数)
第三次握手:客户端确认报文(检查ack是否正确),确认无误后,响应请求
标志位ACK=1,ack=seqS+1,seq=seqC+1
服务端接收到报文后,同样会检查ack是否正确,无误后建立连接
示意图
为何要三次握手
如果只依赖两次握手建立连接,那么会有以下几个问题:
- 客户端延迟的连接请求发送到服务端,导致重复建立连接
- 如果客户端没有收到服务端的确认,此时进入连接状态的服务端会一直等待客户端传输数据,浪费资源
而三次握手能实现以下目的:
- 第一次握手请求连接
此时,服务端确认自己接收消息的功能完好 - 第二次握手服务端响应第一次握手
此时,客户端可以确认自己发送消息和接收消息的功能完好 - 第三次客户端响应第二次握手
此时,服务端确认自己发送消息的功能完好
至此,双发互相确认了发送,接收功能的完好,可以创建连接开始通信
TCP四次挥手
在请求完成后,需要断开客户端与服务端建立的连接。类似于三次握手创立连接,此时需要经过四次挥手去完成断开连接的过程(因为可能还有数据没传送完,所以多一次确认请求)。
第一次挥手:发起方发起断开请求,
标志位FIN=1,seq=seqC(随机数)
第二次挥手:接收方返回确认,
标志位ACK=1,ack=seqC+1,seq=seqS1(随机数)
第三次挥手:待接收方完成传输处理,会向发起方发送确认断开的请求
标志位FIN=1,ACK=1,ack=seqC+1,seq=seqS2(随机数)
第四次挥手:发起方确认报文无误后响应接收方的断开请求,
标志位ACK=1,ack=seqS2+1,seq=seqC+1
第四次挥手后,接收方收到发起方的确认请求后就会进入CLOSED状态,而发起方会等待2MSL的时间后进入CLOSED状态
示意图
何时断开
在了解TCP四次挥手后,有两个疑问:
何时去断开连接?
在确认数据传输完毕后就可以断开连接
(但为了防止频繁的握手和挥手,客户端可以在请求头中指定Connection: Keep-Alive保持连接)由哪一方发起断开请求?
这个视具体情况而定,也就是哪一方能够确认数据传输完毕。
举个例子:这里访问搜索引擎首页,一般来说这种首页静态资源是固定的。
所以可以看到服务端响应头信息中content-length指定了具体数据,那么客户端会根据这个大小判断是否完成数据传输然后发起断开请求。另一种情况就是如果服务端无法确认传输数据的大小,那么会采用块传输的方式或者短连接(也就是服务端判断数据传输完了就直接断开连接)
为何发起方最后要等待2MSL
主要考虑到第四次握手,也就是响应接收方的二次确认请求失败的情况。如果此时发起方直接关闭,那么就收不到接收方因重试发送的请求。
MSL: Maximum Segment Lifetime 即报文最大生存时间,超过这个时间的报文将被丢弃
TCP标志位
标志位代表TCP连接的状态,有以下六种:
SYN:表示请求建立一个连接)
URG:紧急标志
ACK:确认数据包的接收
PSH:推送标志,提高数据传输的优先级
RST:要求对方重新建立连接
FIN:表示要断开连接