这篇文章想跟大家聊聊TCP协议建立连接("三次握手")和断开连接("四次挥手")的过程;这里先提出几个问题,后面我们针对这些问题展开;

  • 你知道什么是三次握手?为什么需要三次握手?

  • 你知道什么是四次挥手?为什么需要四次挥手?

  • 为什么建立连接是三次握手,而断开连接却需要四次挥手

认识TCP报文格式

首先,我们先来一起认识一下TCP的报文格式:

image.png

这里有几个概念跟大家强调一下:

序号:seq序号,占32位,用来标识从TCP源端向目的端发送的字节流,发起方发送数据时对此进行标记

确认序号:ack序号,32位,只有ACK标志位为1时,确认序号字段才有效,ack=seq+1

标志位:

标志位含义
SYN发起一个新连接
FIN释放一个链接
RST重置一个链接
PSH接收方应尽快将报文交给应用层
ACK确认序号有效
URG紧急指针有效

TIPS:

标志位的ACK表示确认需要有效,请不要与ack( 确认序号)混淆。

确认方的 ack = 发送方 seq +1,两端配对用于确认请求

建立连接三次握手详解

什么是三次握手呢?其实就是建立TCP连接,就是指建立TCP连接时,需要客户端和服务端总共发送3个包以确认连接的建立。

image.png

第一次握手:Client端将标志位 SYN 设置为1,并生成一个序号 seq=J 发送给Server端,Client 进入 SYN_SENT状态,等待Server端确认。

第二次握手:Server端发现SYN=1了解到Client需要建立连接,Server端将SYN 和 ACK 都设置为1,并将ack设置为J+1,并生成自己的序号 seq=K,发送给Client端以确认连接请求,Server端进入SYN_RCVD状态。

第三次握手:Client收到请求后发现ACK是否为1,确认ack是否等于J+1;验证通过后,设置ack为K+1,将标志位ACK设置为1,并将数据包发送给Server端;Server端验证通过后ACK标志位以及ack正确后,Server端和Client端都进入ESTABLISHED状态。

TIPS:整个三次握手的过程就是确认Client与Server端收发能力的过程

image.png

断开连接四次挥手详解

三次握手的过程,想必大家都耳熟能详;但是四次挥手的过程,少人却有能说的头头是道;所谓四次挥手就是断开连接,就是指断开连接时,需要客户端和服务端送过发送4个包已确认连接的断开。

image.png

由于TCP是全双工的,因此,每个方向都需要单独进行关闭;这一原则是当一方完成数据发送任务后,发送一个FIN来终止这一方向的连接,收到一个FIN只是意味着这一方向上没有数据流动了,即不会再收到数据了,但是在这个TCP连接上仍然能够发送数据,直到这一方向也发送了FIN。首先进行关闭的一方将执行主动关闭,而另一方则执行被动关闭,上图描述的即是如此。

第一次挥手:Client端发送一个FIN标志,用来关闭Client端到Server端的数据传送,Client进入FIN_WAIT_1状态。

第二次挥手:Server端收到FIN后,发送一个ACK给Client,确认序号为收到序号+1(与SYN相同,一个FIN占用一个序号),Server进入CLOSE_WAIT状态。

第三次挥手:Server端发送一个FIN,用来关闭Server端到Client端的数据传送,Server端进入LAST_ACK状态。

第四次挥手:Client端收到FIN后,Client端进入TIME_WAIT状态,接着发送一个ACK给Server端,确认序号为收到序号+1,Server端进入CLOSED状态,完成四次挥手。

上面是一方主动关闭,另一方被动关闭的情况,实际中还会出现同时发起主动关闭的情况,具体流程如下图:

image.png

以上过程,基本与四次挥手类似,可以参考四次挥手的流程,解读同时发起关闭的过程。

TIPS:为什么建立连接是三次握手,而关闭连接却是四次挥手呢?

这是因为服务端在LISTEN状态下,收到建立连接请求的SYN报文后,把ACK和SYN放在一个报文里发送给客户端。而关闭连接时,当收到对方的FIN报文时,仅仅表示对方不再发送数据了但是还能接收数据,己方也未必全部数据都发送给对方了,所以己方可以立即close,也可以发送一些数据给对方后,再发送FIN报文给对方来表示同意现在关闭连接,因此,己方ACK和FIN一般都会分开发送。

最后分享一个学习了解网络编程很不错的网站:http://www.52im.net

image.png图片