1、TCP三次握手、四次挥手的过程及原理

一、TCP协议简述

TCP提供面向有连接的通信传输。面向有连接是指在传输数据之前必须先建立连接,数据传输完成之后要释放连接。

在TCP/IP协议中,TCP协议提供的是可靠的连接服务,连接是通过3次握手进行初始化的。

TCP是全双工模式,在关闭连接时需要进行4次挥手

二、TCP报文的格式

1、TCP报文格式

1.1、在TCP报头中的源端口号和目的端口号以及IP数据报中的源IP和目的IP可用于唯一的确定一条TCP连接;

1.2、32位序号seq(4字节 = 32位,Sequence number):用于标识TCP发端向TCP收端发送的数据字节流,通过该序列来确认发送的数据是否有序;

1.3、32位确认序号ack(4字节 = 32位):用于对上一次seq序号做出确认,用于响应TCP的报文段,给收到的TCP报文段的seq加1;

1.4、TCP的标志位

SYN(1位) 同步标志位,用于请求建立会话连接
ACK(1位) 确认标志位,对已接收的数据包进行确认
FIN(1位) 完成标志位,表示已没有数据可发送,即将关闭连接

三、TCP三次握手

1、(客户端:我要建立连接)首先由Client发送连接请求(SYN包),即SYN=1,seq=x(随机数),Client进入SYN_SENT(同步已发送)状态,等待Server的确认;

2、(服务端:你的请求以获知,可以建立连接)Server收到SYN包后进行回复确认,即SYN=1,ack=x+1,ACK=1,seq=y(随机数),此时Server进入SYN_RCVD(同步收到)状态;  --  此时服务端无法确定客户端是否可以收到自己的回复,因此还需要进行一次招手动作

3、(客户端:进行连接)Client收到Server回复的数据,再进行一次确认,向Server发送ACK确认包,即ACK=1,ack=y+1,seq=x+1。此包发送完毕,Client和Server进入ESTABLISHED(TCP连接成功)状态。

四、TCP四次挥手

1、(客户端:我数据已传输完,需要下线了)Client发出连接释放报文,即FIN=1,seq=u(之前已传数据的最后一个字节的序号加1),并停止发送数据,Client进入FIN-WAIT-1(终止等待1)状态;

2、(服务器:知道了,我还有点数据,需要你等一段时间)Server收到连接释放报文,发出确定报文,即ACK=1,ack=u+1,seq=v,Server进入CLOSE-WAIT(关闭等待)状态,Client收到Server回复后,进入FIN-WAIT-2(终止等待2)状态。此时是半关闭状态,即Client不再发送,但是Server若发送数据,Client依然要接收;

3、(服务器:我数据已发送完,你可以下线了)Server将最后的数据发送完毕,向Client发送连接释放报文,即FIN=1,ACK=1,seq=w,ack=u+1,Server进入LAST-ACK(最后确认)状态,等待Client的确认;

4、(客户端:好的)Client收到Server的连接释放报文,必须发出确认报文,即ACK=1,ack=w+1,seq=u+1,Client进入TIME-WAIT(时间等待)状态。但是Client连接没有释放,必须经过2MSL的时间之后,才进入CLOSED状态。Server收到Client的确认报文,立即进入CLOSED状态。Server结束TCP连接的时间要比Client早一些。

五、面试相关

  • TCP/IP 协议是传输层的一个面向连接的安全可靠的一个传输协议;
  • 三次握手的机制是为了保证能建立一个安全可靠的连接,那么第一次握手是由客户端发起,客户端会向服务端发送一个报文,在报文里面:SYN标志位置为1,表示发起新的连接。当服务端收到这个报文之后就知道客户端要和我建立一个新的连接,于是服务端就向客户端发送一个确认消息包,在这个消息包里面:ACK标志位置为1,表示确认客户端发起的第一次连接请求。以上两次握手之后,对于客户端而言:已经明确了我既能给服务端成功发消息,也能成功收到服务端的响应。但是对于服务端而言:两次握手是不够的,因为到目前为止,服务端只知道一件事,客户端发给我的消息我能收到,但是我响应给客户端的消息,客户端能不能收到我是不知道的。所以,还需要进行第三次握手,第三次握手就是当客户端收到服务端发送的确认响应报文之后,还要继续去给服务端进行回应,也是一个ACK标志位置1的确认消息。通过以上三次连接,不管是客户端还是服务端,都知道我既能给对方发送消息,也能收到对方的响应。那么,这个连接就被安全的建立了;
  • 四次挥手机制也是由客户端首先发起的,客户端会发送一个报文,在报文里面:FIN标志位置1。当服务端收到这个报文之后,就知道了客户端想要和我断开连接。但是此时服务端不一定能做好准备,因为客户端发起断开连接的消息的时候,对于服务端而言,它极可能有未发送完的消息,它还要继续发送。所以此时对于服务端只能进行一个消息确认,就是告诉客户端我知道你要跟我断开连接了,但是我还没有做好准备,你需要等我一会。稍过片刻,服务端会继续发送一个断开连接的报文,FIN标志位置1。这个报文表示服务端已经做好了要断开连接的准备。客户端收到后继续发送一个消息确认的报文。通过以上四次连接,不管是客户端还是服务端,都已经做好了要断开连接的准备,连接就可以被断开了。

六、扩展问法

1、为什么连接的时候是三次握手,关闭的时候却是四次握手?

答:因为当Server端收到Client端的SYN连接请求报文后,可以直接发送SYN+ACK报文。其中ACK报文是用来应答的,SYN报文是用来同步的。但是关闭连接时,当Server端收到FIN报文时,很可能并不会立即关闭SOCKET,所以只能先回复一个ACK报文,告诉Client端,"你发的FIN报文我收到了"。只有等到我Server端所有的报文都发送完了,我才能发送FIN报文,因此不能一起发送。故需要四步握手。

2、如果已经建立了连接,但是客户端突然出现故障了怎么办?

答:TCP还设有一个保活计时器,显然,客户端如果出现故障,服务器不能一直等下去,白白浪费资源。服务器每收到一次客户端的请求后都会重新复位这个计时器,时间通常是设置为2小时,若两小时还没有收到客户端的任何数据,服务器就会发送一个探测报文段,以后每隔75秒钟发送一次。若一连发送10个探测报文仍然没反应,服务器就认为客户端出了故障,接着就关闭连接。

【参考资料】

1.https://www.cnblogs.com/yuanqiu/p/14674764.html

2.https://www.bilibili.com/video/BV1bi4y1x7m5?from=search&seid=9748668031772048075

原文地址:https://www.cnblogs.com/yif930916/p/14809170.html