简述TCP三次握手和四次挥手流程

前言

关于TCP的连接过程,很多从事程序开发的小伙伴应该都听过三次握手,可这三次握手的细节还是有很多人不太清楚的,特别是有些参数记不清楚,我也经常弄错,所以我根据自己的理解画了两张图,将TCP连接和断开的流程简单记录一下,以方便后续查找复习之用。

三次握手


tcp_connect

初始状态:客户端A和服务器B均处于CLOSED状态,然后服务器B创建socket,调用监听接口使得服务器处于LISTEN状态,等待客户端连接。(后续内容用A,B简称代替)

  1. A首先向B发起连接,这时TCP头部中的SYN标识位值为1,然后选定一个初始序号seq=x(一般是随机的),消息发送后,A进入SYN_SENT状态,SYN=1的报文段不能携带数据,但要消耗一个序号。

  2. B收到A的连接请求后,同意建立连接,向A发送确认数据,这时TCP头部中的SYN和ACK标识位值均为1,确认序号为ack=x+1,然后选定自己的初始序号seq=y(一般是随机的),确认消息发送后,B进入SYN_RCVD状态,与连接消息一样,这条消息也不能携带数据,同时消耗一个序号。

  3. A收到B的确认消息后,需要给B回复确认数据,这时TCP头部中的ACK标识位值为1,确认序号是ack=y+1,自己的序号在连接请求的序号上加1,也就是seq=x+1,此时A进入ESTABLISHED状态,当B收到A的确认回复后,B也进入ESTABLISHED状态,至此TCP成功建立连接,A和B之间就可以通过这个连接互相发送数据了。

四次挥手


tcp_disconnect

初始状态:客户端A和服务器B之间已经建立了TCP连接,并且数据发送完成,打算断开连接,此时客户端A和服务器B是等价的,双方都可以发送断开请求,下面以客户端A主动发起断开请求为例。(后续内容用A,B简称代替)

  1. A首先向B发送断开连接消息,这时TCP头部中的FIN标识位值为1,序号是seq=m,m为A前面正常发送数据最后一个字节序号加1得到的,消息发送后A进入FNI_WAIT_1状态,FIN=1的报文段不能携带数据,但要消耗一个序号。

  2. B收到A的断开连接请求需要发出确认消息,这时TCP头部中的ACK标识位值为1,确认号为ack=m+1,而自己的序号为seq=n,n为B前面正常发送数据最后一个字节序号加1得到的,然后B进入CLOSE_WAIT状态,此时就关闭了A到B的连接,A无法再给B发数据,但是B仍然可以给A发数据(此处存疑),同时B端通知上方应用层,处理完成后被动关闭连接。然后A收到B的确认信息后,就进入了FIN_WAIT_2状态。

  3. B端应用层处理完数据后,通知关闭连接,B向A发送关闭连接的消息,这时TCP头部中的FIN和ACK标识位值均为1,确认号ack=m+1,自己的序号为seq=k,(B发出确认消息后有发送了一段数据,此处存疑),消息发送后B进入LACK_ACK状态。

  4. A收到B的断开连接的消息后,需要发送确认消息,这是这时TCP头部中的ACK标识位值为1,确认号ack=k+1,序号为m+1(因为A向B发送断开连接的消息时消耗了一个消息号),然后A进入TIME_WAIT状态,若等待时间经过2MSL后,没有收到B的重传请求,则表明B收到了自己的确认,A进入CLOSED状态,B收到A的确认消息后则直接进入CLOSED状态。至此TCP成功断开连接。

总结

  1. 关于三次握手,参考了很多资料说服务器是被动打开连接,对此有些不解,希望知道的朋友给出提示和建议。

  2. 关于四次挥手,在我的叙述中有两处存疑,就是B收到的A的主动断开请求后,进入CLOSE_WAIT状态,是否还能发送数据到A,参考了一些资料说A不能发数据给B,但是B能发数据给A,并且A也可以接收,但是无论我在Windows环境测试还是Linux环境下测试这种状态A都无法收到B的数据,不知道我是不是理解错了,希望明白原理的小伙伴能解答一下。

  3. 在四次挥手的最后阶段,有一个等待时间2MSL,这个不是一个时间单位,而是一个表明时间段的名词,这段等待时间就是为了在B没收到确认消息时,接收B的重传请求的,如果不等待这一段时间直接进入CLOSED状态,那么B未收到A的确认消息就会发送重传请求,而此时A已经关闭,就不会再给B重传了,其中MSL的是Maximum Segment Lifetime英文的缩写,可简单译为“报文最大生存时间”,也就是说如果B没有收到确认信息,那么在2MSL这段时间内很大概率就会发送重传请求,并且被A收到,RFC 793中规定MSL为2分钟,实际应用中常用的是30秒,1分钟和2分钟等。

  4. 在连接和断开的过程都有提到ACKack,这一点要注意区分,大写的ACK代表TCP头部中6个标识位之一,是表明这是个确认报文,而小写的ack拜师确认序号,表明对方发来的数据到ack这个序号前的都已经收到了。

Albert Shi wechat
欢迎您扫一扫上面的微信公众号,订阅我的博客