本文分享自华为云社区《输入网址,小手一点,后面到底发生了什么?-云社区-华为云》,作者:龙哥手记。

输入网址并点回车,后台到底发生了什么。透析 HTTP 协议与 TCP 连接之间的千丝万缕的关系。掌握为何是三次握手四次挥手?time_wait 存在的意义是什么?全面图解重点问题,再也不用担心面试问这个问题。

大致流程

重点来了:

URL 解析

url 遵守的规则是这个样子

scheme://host.domain:port/path/filename

每个名词的含义如下解释:

DNS 查询

浏览器不能直接通过域名找到服务器,只能通过 IP 地址。

那浏览器是如何通过域名查询到我们输入的 url 对应的 IP 呢?

TCP 连接建立与断开

通过域名解析出 IP 地址以后就要建立 TCP/IP 连接了。

TCP/IP 分为四层,每一层都会加上一个头部再发送给下一层。到了接收方后,对应的每一层则把对应层的头部解析拆除,丢上上一层,跟发送端的过程反过来。

用手指头点击网址(当你输入网址小手一点)(1)

TCP/IP四层模型应用层:发送 HTTP 请求

浏览器从地址栏得到服务器 IP,接着构造一个 HTTP 报文,其中包括:

传输层:TCP 传输报文

在传输报文之前会先建立 TCP/IP 连接,也就是后面我们要说的三次握手。

在这一层解决了数据可靠传输、及流量控制、拥塞控制。

可靠传输

对于发送方发送的数据,接收方在接受到数据之后必须要给予确认,确认它收到了数据。如果在规定时间内,没有给予确认则意味着接收方没有接受到数据,然后发送方对数据进行重发。

TCP的可靠传输是通过确认和超时重传的机制来实现的,而确认和超时重传的具体的实现是通过以字节为单位的滑动窗口机制来完成。

TCP拥塞控制

TCP协议通过慢启动机制、拥塞避免机制、加速递减机制、快重传和快恢复机制来共同实现拥塞控制。

流量控制

采用通知窗口实现对发送端的流量控制,通知窗口大小的单位是字节。TCP通过在TCP数据段首部的窗口字段中填入当前设定的接收窗口(即通知窗口)的大小,用来告知对方 '我方当前的接收窗口大小',以实现流量控制。

通信双方的发送窗口大小由双方在连接建立的时候商定,在通信过程,双方可以动态地根据自己的情况调整对方的发送窗口大小。

网络层:IP 协议查询 MAC 地址

将数据段打包,并加入源及目标的 IP 地址,并且负责寻找传输路线。判断目标地址是否与当前地址处于同一网络中,是的话直接根据 Mac 地址发送,否则使用路由表查找下一跳地址,以及使用 ARP 协议查询它的 Mac 地址。

链路层:以太网协议

根据以太网协议将数据分为以“帧”为单位的数据包,每一帧分为两个部分:

Mac 地址

以太网规定了连入网络的所有设备都必须具备“网卡”接口,数据包都是从一块网卡传递到另一块网卡,网卡的地址就是 Mac 地址。每一个 Mac 地址都是独一无二的,具备了一对一的能力。

三次握手

在传输层传输数据之前需要建立连接,也就是三次握手创建可靠连接。

用手指头点击网址(当你输入网址小手一点)(2)

三次握手

首先建立链接前需要 Server 端先监听端口,因此 Server 端建立链接前的初始状态就是 LISTEN 状态,这时 Client 端准备建立链接,先发送一个 SYN 同步包,发送完同步包后,Client 端的链接状态变成了 SYN_SENT 状态。Server 端收到 SYN 后,同意建立链接,会向 Client 端回复一个 ACK。

由于 TCP 是双工传输,Server 端也会同时向 Client 端发送一个 SYN,申请 Server 向 Client 方向建立链接。发送完 ACK 和 SYN 后,Server 端的链接状态就变成了 SYN_RCVD。

Client 收到 Server 的 ACK 后,Client 端的链接状态就变成了 ESTABLISHED 状态,同时,Client 向 Server 端发送 ACK,回复 Server 端的 SYN 请求。

Server 端收到 Client 端的 ACK 后,Server 端的链接状态也就变成了的 ESTABLISHED 状态,此时建连完成,双方随时可以进行数据传输。

在面试时需要明白三次握手是为了建立双向的链接,需要记住 Client 端和 Server 端的链接状态变化。另外回答建连的问题时,可以提到 SYN 洪水攻击发生的原因,就是 Server 端收到 Client 端的 SYN 请求后,发送了 ACK 和 SYN,但是 Client 端不进行回复,导致 Server 端大量的链接处在 SYN_RCVD 状态,进而影响其他正常请求的建连。可以设置 tcp_synack_retries = 0 加快半链接的回收速度,或者调大 tcp_max_syn_backlog 来应对少量的 SYN 洪水攻击

四次挥手

我们只要关注 80 端口与 13743 端口建立的连接断开过程,浏览器通过 13747 端口发送 [FIN, ACK] 这里是不是跟很多网上看到的不一样?

  1. 其实是客户端在发送 [FIN] 报文的时候顺带发了一个 [ACK] 确认上次传输确认。
  2. 接着服务端通过 80 端口响应了 [ACK] ,然后立马响应 [FIN, ACK] 表示数据传输完了,可以关闭连接。
  3. 最后浏览器通过 13743 端口 发送 [ACK] 包给服务端,客服端与服务端连接就关闭了。

具体流程如下图抓包所示:

用手指头点击网址(当你输入网址小手一点)(3)

三次握手与四次挥手

用手指头点击网址(当你输入网址小手一点)(4)

TCP 连接与断开

客户端:

服务端:

TIME_WAIT 状态存在的理由:

划重点了

另外回答断链的问题时,可以提到实际应用中有可能遇到大量 Socket 处在 TIME_WAIT 或者 CLOSE_WAIT 状态的问题。一般开启 tcp_tw_reuse 和 tcp_tw_recycle 能够加快 TIME-WAIT 的 Sockets 回收;而大量 CLOSE_WAIT 可能是被动关闭的一方存在代码 bug,没有正确关闭链接导致的。

简单地说就是

  1. 保证 TCP 协议的全双工连接能够可靠关闭;
  2. 保证这次连接的重复数据段从网络中消失,防止端口被重用时可能产生数据混淆;

点击下方,第一时间了解华为云新鲜技术~

华为云博客_大数据博客_AI博客_云计算博客_开发者中心-华为云

,