HTTP 三次握手
前置:
1、Http请求是基于Tcp connection这个链接的
2、位码即tcp标志位,有6种标示:
SYN(synchronous建立联机) 、ACK(acknowledgement 确认)、 PSH(push传送)
FIN(finish结束)、RST(reset重置)、 URG(urgent紧急)
Sequence number(顺序号码)
Acknowledge number(确认号码)
-
SYN (同步序列编号):是 TCP/IP 建立连接时使用的握手信号。TCP 连接的第一个包,非常小的一种数据包。在客户机和服务器之间建立正常的 TCP 网络连接时,客户机首先发出一个 SYN 消息,服务器使用 SYN + ACK 应答表示接收到了这个消息,最后客户机再以 ACK 消息响应。这样在客户机和服务器之间才能建立起可靠的 TCP 连接,数据才可以在客户机和服务器之间传递。
-
Seq (序号):是 TCP 可靠传输的关键部分。序号是该报文段发送的数据组的第一个字节的序号。在 TCP 传送的流中,每一个字节都有一个序号。比如一个报文段的序号为 300,报文段数据部分共有 100 字节,则下一个报文段的序号为 400 。所以序号确保了 TCP 传输的有序性。
-
ACK (确认值):仅当 ACK = 1 时,确认号字段才有效。TCP 规定,在连接建立后所有报文的传输都必须把 ACK 置 1 。
-
Ack (确认号):指明下一个期待收到的字节序号,表明该序号之前的所有数据已经正确无误的收到。确认号只有当 ACK 标志为 1 时才有效。比如建立连接时,SYN 报文的 ACK 标志位为 0 。
状态:
- CLOSED:表示初始状态
- SYN_SENT:表示客户端已发送 SYN 报文
- SYN_RCVD:表示服务器接受到了 SYN 报文
- ESTABLISHED:表示连接已经建立
过程:
第一次握手:建立连接时,客户端发送 SYN 到服务器,并进入 SYN_SENT 状态
第二次握手:服务器收到请求后,回送 SYN + ACK 到客户端,此时服务器进入 SYN_RECV 状态;
第三次握手:客户端收到 SYN + ACK 包,向服务器发送确认 ACK 包,客户端进入 ESTABLISHED 状态,服务器收到请求后也进入 ESTABLISHED 状态,完成三次握手,此时 TCP 连接成功,客户端与服务器开始传送数据
第一次握手 (客户端向服务器发送):Client 首先发送一个连接试探,ACK = 0 表示确认号无效,SYN = 1 表示这是一个连接请求或连接接受报文,同时表示这个数据报不能携带数据,seq = x 表示 Client 自己的初始序号( seq = 0 就代表这是第 0 号帧),这时候 Client 进入 SYN_SENT 状态,表示客户端等待服务器的回复
第二次握手 (服务器回复客户端):Server 监听到连接请求报文后,如同意建立连接,则向 Client 发送确认。
TCP 报文首部中的 SYN 和 ACK 都置为 1 ,ack = x + 1表示期望收到对方下一个报文段的第一个数据字节序号是 x + 1 ,同时表明 x 为止的所有数据都已正确收到( ack = 1 其实是 ack = 0 + 1 ,也就是期望客户端的第 1 个帧),seq = y 表示 Server 自己的初始序号( seq = 0 就代表这是服务器这边发出的第 0 号帧)。这时服务器进入 SYN_RCVD 状态,表示服务器已经收到 Client 的连接请求,等待 Client 的确认
第三次握手 (客户端向服务器发送):Client 收到确认后还需再次发送确认,同时携带要发送给 Server 的数据。ACK 置 1 表示确认号 ack = y + 1 有效(代表期望收到服务器的第 1 个帧),Client 自己的序号 seq = x + 1(表示这就是我的第1个帧,相对于第0个帧来说的),一旦收到 Client 的确认之后,这个 TCP 连接就进入 ESTABLISHED 状态,就可以发起 http 请求了
为什么是三次握手
- 在第一次通信过程中,A向B发送信息之后,B收到信息后可以确认自己的收信能力和A的发信能力没有问题。
- 在第二次通信中,B向A发送信息之后,A可以确认自己的发信能力和B的收信能力没有问题,但是B不知道自己的发信能力到底如何,所以就需要第三次通信。
- 在第三次通信中,A向B发送信息之后,B就可以确认自己的发信能力没有问题。
A-->B-->A-->B这样传三次能保证A有发有收,B也有发有收。多一次浪费少一次不够。
所以为什么是三次握手:最主要是防止已过期的连接再次传到被连接的主机
那为什么非要三次呢?怎么觉得两次就可以完成了。那 TCP 为什么非要进行三次连接呢?在谢希仁的《计算机网络》中是这样说的:
为了防止已失效的连接请求报文段突然又传送到了服务端,因而产生错误。
在书中同时举了一个例子,如下:
"已失效的连接请求报文段”的产生在这样一种情况下:
Client 发出的第一个连接请求报文段并没有丢失,而是在某个网络结点长时间的滞留了,以致延误到连接释放以后的某个时间才到达 Server 。本来这是一个早已失效的报文段。但 Server 收到此失效的连接请求报文段后,就误认为是 Client 再次发出的一个新的连接请求。于是就向 Client 发出确认报文段,同意建立连接。假设不采用“三次握手”,那么只要 Server 发出确认,新的连接就建立了。由于现在 Client 并没有发出建立连接的请求,因此不会理睬 Server 的确认,也不会向 Server 发送数据。但 Server 却以为新的运输连接已经建立,并一直等待 Client 发来数据。这样,Server 的很多资源就白白浪费掉了。采用“三次握手”的办法可以防止上述现象发生。例如刚才那种情况,Client 不会向 Server 的确认发出确认。 Server 由于收不到确认,就知道 Client 并没有要求建立连接。"这就很明白了,防止了服务器端的一直等待而浪费资源。
示例分析:
192.168.1.11 为客户端 A,42.121.252.58 为服务器 B。
- 客户端请求连接发送 SYN 产生一个为 x = 0 的序号 seq 。
- 服务器接受连接,ACK = x + 1 = 1 并产生 y = 0 的序号 seq;发送 SYN ACK seq = 0 ack = 1 到客户端。
- 客户端发现服务器接受了连接请求返回了 ack,seq = x;同时接受服务器的请求 ack = y + 1 = 1。
- 因为上个传输,只传输了一个 ACK 没有数据,所以看第四条线 seq = 1,ack = 1。
收获:看 2 这个项,发送端的 seq 字段需要接收到服务器段的 ack 才会变化,这个时候 服务器 ack = 客户端 seq 。
所以我才会有下面对 seq 和 ack 的理解。
- 序号 seq :发送了多少被成功接受数据。
- 确认号 ack:接受了多少数据。