总体分为以下几个过程:
-
DNS解析
-
TCP连接:三次握手
-
发送HTTP请求
-
服务器处理请求并返回HTTP报文
-
浏览器解析渲染页面
-
连接结束:四次挥手
DNS解析
在浏览器输入网址后,首先要经过域名解析,因为浏览器并不能直接通过域名找到对应的服务器,而是要通过 IP 地址。互联网上每一台机器的唯一标识就是它的 IP 地址,但 IP 地址是一个32位的2进制数,并不方便人类去记忆,相对于 IP 地址这样的一组纯数字,用字母配合数字的表示形式更符合人类的记忆习惯。DNS解析就是把网址到 IP 地址的转换。
上述图片是查找www.google.com的IP地址过程。首先在本地域名服务器中查询IP地址,如果没有找到的情况下,本地域名服务器会向根域名服务器发送一个请求,如果根域名服务器也不存在该域名时,本地域名会向com顶级域名服务器发送一个请求,依次类推下去。直到最后本地域名服务器得到google的IP地址并把它缓存到本地,供下次查询使用。
DNS优化
DNS缓存
- DNS存在多级缓存,从离浏览器的距离排序的话,有以下几种
- 浏览器缓存
- 系统缓存
- 路由器缓存
- IPS服务器缓存
- 根域名服务器缓存
- 顶级域名服务器缓存
- 主域名服务器缓存
DNS负载均衡
DNS可以返回一个合适的机器的IP给用户,例如可以根据每台机器的负载量,该机器离用户地理位置的距离等等,这种过程就是DNS负载均衡,又叫做DNS重定向。是不是很耳熟?没错,就是CDN(Content Delivery NetWork)
TCP三次握手
过程如下:
- 客户端发送连接请求报文段,首部中同步位 SYN = 1,选择一个初始序号 seq = x(SYN报文段,即SYN = 1 的报文段中不能携带数据,但要消耗一个序号)。客户端进入 SYN-SENT(同步已发送)状态。
- 服务器收到请求报文段后,向客户端发送确认。在确认报文段中,SYN、ACK都为1,确认号是ack = x + 1,同时选择一个初始序号 seq = y,进入 SYN-RCVD(同步收到)状态。
- 客户端收到服务器的确认后,再给服务器发出确认。确认报文段的 ACK = 1,确认号 ack = y + 1,序号 seq = x + 1(ACK 报文段可以携带数据,如果不携带数据则不消耗序号)。这时,TCP连接建立,A进入 ESTABLISHED(已建立连接)状态。服务器收到客户端的确认后,也进入ESTABLISHED 状态。
为什么需要三次握手
- 三次握手才可以阻止重复历史连接的初始化(主要原因)
- 三次握手才可以同步双方的初始序列号
- 三次握手才可以避免资源浪费
发送 HTTP 请求
三次握手结束后,开始发送 HTTP 请求报文。
请求行包含请求方法、URL、协议版本
- 请求方法包含 8 种:GET、POST、PUT、DELETE、PATCH、HEAD、OPTIONS、TRACE。
- URL 即请求地址,由 <协议>://<主机>:<端口>/<路径>?<参数> 组成
- 协议版本即 http 版本号
请求头包含请求的附加信息,由键值对组成,每行一对,用英文冒号分隔
服务器处理请求并返回HTTP报文
响应行包含:协议版本,状态码,状态码描述
状态码规则如下:
1xx:指示信息--表示请求已接收,继续处理。
2xx:成功--表示请求已被成功接收、理解、接受。
3xx:重定向--要完成请求必须进行更进一步的操作。
4xx:客户端错误--请求有语法错误或请求无法实现。
5xx:服务器端错误--服务器未能实现合法的请求。
响应头部包含响应报文的附加信息,由键值对组成
响应主体包含回车符、换行符和响应返回数据,并不是所有响应报文都有响应数据
浏览器解析渲染页面
断开连接
当数据传送完毕,需要断开 tcp 连接,此时发起 tcp 四次挥手。
- 数据传输结束后,通信的双方都可释放连接。现在客户端的应用进程先向其 TCP 发出连接释放报文段,并停止再发送数据,主动关闭 TCP 连接。客户端把连接释放报文段首部的 FIN = 1,其序号seq = u,等待服务器的确认。此时客户端进入 FIN-WAIT-1(终止等待1)状态。
- 服务器发出确认,确认号 ack = u + 1,而这个报文段自己的序号 seq = v(等于服务器前面已船传送过的数据的最后一个字节的序号 + 1)。服务器进入CLOSE-WAIT(关闭等待)状态。TCP 服务器进程通知高层应用进程,从客户端到服务器这个方向的连接就释放了,TCP 连接处于半关闭状态。服务器若发送数据,客户端仍要接收。
- 客户端收到来自服务器的确认后,进入 FIN-WAIT-2(终止等待2)状态,等待服务器发出的连接释放报文段。
- 若服务器已经没有要向客户端发送的数据,其应用进程就通知 TCP 释放连接。这时服务器发出的连接释放报文段必须使 FIN = 1。服务器还必须重复上次已发送过的确认号 ack = u + 1。这时服务器就进入 LAST-ACK(最后确认)状态,等待客户端的确认。
- 客户端收到连接释放报文段后,必须发出确认。在确认报文段中 ACK = 1,确认号 ack = w + 1,自己的序号 seq = u + 1。进入到TIME-WAIT(时间等待)状态。
注意:TCP 连接必须经过时间 2MSL(最长报文段寿命,RFC 793建议设为2分钟,2MSL即为4分钟) 后才真正释放掉。其理由如下:
- 为了保证服务器发送的最后一个ACK报文能够到达客户端。这个ACK报文段有可能丢失,因而使处在LAST-ACK状态的客户端收不到对已发送的FIN+ACK报文段的确认。客户端会超时重传这个FIN+ACK报文段,而服务器就能在2MSL时间内收到这个重传的FIN+ACK报文段。如果服务器在TIME-WAIT状态不等待一段时间,而是在发送完ACK报文段后就立即释放连接,就无法收到客户端重传的FIN+ACK报文段,因而也不会再发送一次确认报文段。这样,客户端就无法按照正常的步骤进入CLOSED状态。
- 服务器在发送完ACK报文段后,再经过2MSL时间,就可以使本连接持续的时间所产生的所有报文段都从网络中消失。这样就可以使下一个新的连接中不会出现这种旧的连接请求的报文段。