TCP三次握手和四次挥手

TCP传输连接的三个阶段:1)连接建立2)数据传送3)连接释放
TCP建立连接之前会进行三次沟通,称为“三次握手”;传输完数据会断开连接要进行四次沟通,称为“四次挥手”。
TCP传输中两个序号和三个标志位:
1) 序号:seq序号,占32位,用来标识从TCP源端向目的端发送的字节流,发起方发送数据时对此进行标记
2) 确认序号:ack序号,占32位,只有ACK标志位为1时,确认序号字段才有效,ack = seq + 1
3) 标志位:共6个,即URG、ACK、PSH、RST、SYN、FIN,具体含义如下:
URG:紧急指针(urgent pointer)有效
ACK:确认序号有效
PSH:接收方应该尽快将这个报文交给应用层
RST:重置连接
SYN:发起一个新连接
FIN:释放一个连接
注意:1)不要将确认序号ack和标志位中的ACK搞混
2)确认方ack = 发起方seq + 1,两端配对
一、三次握手
TCP三次握手和四次挥手_第1张图片
三次握手步骤:
1) 最初客户端和服务器的TCP都处于CLOSED(关闭)状态
2) 服务器进程创建传输控制块(Transmission Control Block,TCB),服务器进程进入LISTEN(收听)状态,等待客户端的连接请求
3) 客户端进程创建传输控制块TCB,向服务器发出连接请求包SYN,初始序号seq=x。此时客户端进程进入SYN-SENT(同步已发送)状态 第一次握手
4) 服务器收到数据包后由标识位SYN=1知道客户端请求建立连接,服务器将标识位SYN和ACK都置为1,ack = x+1,随机产生一个seq=y,并将该数据包发送给客户端以确认连接建立。此时服务器进程进入SYN-RCVD(同步已接收)状态 第二次握手
注:第二次握手时,服务器需要发送两个包给客户端
(i)发送确认自己收到其连接请求包ACK(ack=x+1),向客户端表明已知道了其连接请求
(ii)发送连接询问请求包SYN,询问客户端是否已经准备好建立连接,进行数据通信
5) 客户端收到服务器的ACK和SYN包后,知道服务器同意建立连接,发送连接建立的ACK包,回应服务器的SYN告诉服务器,我们已经建立了连接,可以进行数据通信。此时客户端进入ESTABLISHEN(已连接)状态 第三次握手
6) 服务器收到客户端的确认,也进入ESTABLISHEN(连接)状态


问题1:客户端A收到服务器B的确认,为什么还要再次向B发送确认?
1)A向B发出连接请求报文段,如果此报文段在网络中长时间滞留,A误以为本文段丢失,会再次向B发送连接请求报文段(假设第二次请求连接建立成功)。当数据传输完成并释放连接后,B又收到A第一次发送的连接请求,B误以为A发起了一次新的连接。所以,A有必要让B知道是否发起了新的连接请求。
2)如果只有俩次握手连接,在这种情况下,如果发送网络阻塞,由于TCP/IP协议的定时重传机制,服务器A向客户端B发送了俩次SYN请求,分别是x1和x2,且因为阻塞原因,导致x1连接请求和x2连接请求的TCP窗口大小和数据报文长度不一致,如果最终x1到达,x2丢失,此时A同B建立了x1的连接,但A无法知道是请求x1还是请求x2,此时会导致数据传输错误。
问题2:为什么不能俩次握手进行连接?
三次握手完成两个重要的功能,既要双方做好发送数据的准备工作(双方都知道彼此已准备好),也要允许双方就初始序列号进行协商,这个序号在握手过程中被发送和确认。
如果改为俩次握手,可能发生死锁。例如,考虑Client和Server之间的通信,假定Client向Server发送一个连接请求,Server收到这个请求并发送了应答ACK包,此时连接已经成功建立,可以开始数据传输。如果Server的应答ACK在传输中丢失,Client将不知道Server是否已经准备好,不知道Server建立什么样的序列号,甚至不确定Server是否收到自己的连接请求。此时,Client认为连接还未建立成功,将忽略Server发来的任何数据,只等待连接确认应答;而Server在发出的分组超时后,重复发送同样的分组,这样就形成了死锁。
二、四次挥手
指的是断开一个TCP连接,需要客户端和服务器总共发送4个包以确认连接的断开。这一过程由客户端或服务端任意一方执行close()来触发。由于TCP连接是全双工的,因此每个方向都必须单独进行关闭,这一原则是当一方完成数据发送任务后,发送一个FIN包来终止这一方向的连接,收到一个FIN意味着这一方向上没有数据流动了,即不会再收到数据了,但在这个TCP连接上仍然可以发送数据,知道这一方向也发送了FIN包。首先进行关闭的一方将执行主动关闭,而另一方则执行被动关闭。
注:FIN报文段即使不携带数据,也要消耗一个序号
TCP三次握手和四次挥手_第2张图片
(1) 第一次挥手:Client发送一个FIN,用来关闭Client到Server的数据传送,Client进入FIN_WAIT_1(终止等待1)状态
(2) 第二次挥手:Server收到FIN后,发送一个ACK给Client,确认序号ack = u+1,Server自己的序号是v,Server进入CLOSE_WAIT状态;Client收到Server的确认进入FIN_WAIT_2(终止等待2)状态,等到Server发出连接释放报文段
(3) 第三次挥手:Server发送一个FIN,用来关闭Server到Client的数据传送,Server进入LAST_ACK状态
(4) 第四次挥手:Client收到FIN后,Client进入TIME_WAIT状态,接着发送一个ACK给Server,确认序号ack = w+1,Server进入CLOSED状态;经过时间等待计时器设置的时间2MSL后,Client进入CLOSED状态,完成四次挥手
注:MSL即Maximum Segment Lifetime,报文最大生存时间。


问题1:Client为什么在TIME_WAIT状态等到2MSL时间?
1) 保证Client发送的最后一个ACK报文段能够到达Server。如果此报文段丢失,处在LAST_ACK状态的Server收不到FIN+ACK报文段的确认,Server将超时重传FIN+ACK报文段。Client重传ACK报文段,重新启动2MSL的计时器。保证Client和Server都能顺利进入CLOSED状态
2) 防止“已失效的连接请求报文段”。Client等待2MSL,可使本连接持续时间内所产生的所有报文段全部从网络中消失。
问题2:为什么建立连接协议是三次握手,而关闭连接确实四次挥手?
因为服务器Server在LISTEN状态下,收到建立连接请求的SYN报文后,把ACK和SYN放到一个报文里发送给Client。而关闭连接时,当收到对方的FIN报文时,仅表示对方不再发送数据了但还是能接收数据,己方也未必全部数据发送给对方,所以己方可以立即关闭,也可以发送一些数据给对方后,再发送FIN报文给对方表示同意现在关闭连接,因此,己方ACK和FIN一般都分开发送。

你可能感兴趣的:(计算机网络,TCP,网络协议)