TCP的握手与挥手

来源:互联网 发布:pc版软件下载 编辑:程序博客网 时间:2024/06/16 14:27

参考资料《计算机网络》谢希仁


这里写图片描述

建立链接: 请求发起方主动打开链接,接收方被动打开; 三次握手: 请求端发送一个SYN报文段请求链接,由CLOSE状态转为SYN_SEND状态,此时接收端被动打开,由CLOSE状态切为LISTEN状态并保持,当接收到SYN报文段之后,接收端会发送一个确认报文段,告诉发送端我收到链接请求,此报文段SYN=1,ACK=1,还有窗口大小,协商好的序号;状态切换到SYN_RCVD; 发送端 收到SYN的确认之后,会对这个SYN确认报文进行确认,发送一个ACK=1,此时SYN=0,状态切为ESTABLISED开始收发数据; 接收端 接到最后一个ACK之后才会切换状态为ESTABLISED收发数据; 此时三次握手完成!

取消链接: 可以是任意一方发起,以client(客户端)为例,当client端的数据发送完毕后,client要求取消链接,最后一个报文段置FIN为1,并状态转换为FIN_WAIT_1;当 server(服务器) 收到client端的FIN报文段后,会切换状态为CLOSE_WAIT,告诉上层应用,client关闭了链接,并且向client发送ACK确认,如果此时server的数据还没有发送完毕,依然会继续向client发送数据,client 收到server发送的ACK之后,也就是不再发送数据,状态切换为FIN_WAIT_2;当 server 数据发送完毕,发送一个FIN=1的报文段给client,告诉client数据发送完毕,可以关闭链接,等待client的确认,并且状态由CLOSE_WAIT转为LAST_ACKclient 接收到serverFIN之后,会对这个FIN做出ACK回应,状态转换为TIME_WAIT,这里有个终止等待计时器,等待2MSL的时间(MSL报文最大生存时间),然后CLOSE,如果在这个期间收到重复的FIN,则会触发ACK重传,并将终止等待计时器重置;server 收到最后一个ACK之后,CLOSE;至此,四次挥手完毕!

1、为什么要三次握手?

第一次握手: 
客户端先发送一个SYN请求(SYN=1表示该报文是一个连接请求报文),发送的序号seq=x(x是系统自己选定的大小),SYN虽然不携带数据但是会消耗一个序列号。当客户端的SYN请求发送出去之后,客户端进入SYN-SENT状态。 

第二次握手: 
服务器端收到客户端的连接请求报文,如果同意连接的话就像客户端发送一个确认报文。此确认报文的SYN和ACK的标志位都置为1,确认号a = x +1,同时服务器这边也要给自己设定一个发送序号y。此报文同样不能携带数据,但也要消耗一个序列号。 

第三次握手: 
客户端收到服务器端确认报文后,要再次向服务器端发送一个确认报文,表明我已经收到你的确认消息。此确认报文的首部ACK标志为1,确认号ACK= y+1,序号为x+1。从此报文开始,就已经开始携带数据了,若此报文不携带数据则下个报文的序号认为x+1。此后,客户端就进入了ESTABLISHED状态。

目的:防止已失效的连接请求又传到了服务器端。 
场景(A为客户,B为服务器):A向B发送一个请求连接报文,但是这个报文在网络中阻塞了,并没有传到B。所以B也无法向A发送确认报文,在A的重传计时器到达之后,A再次向B发送请求连接报文,这个报文B收到了,并且向A做出应答,建立连接,传输数据。数据传输完后,关闭连接。问题来了,就在B关闭连接之后,A第一次发送的请求连接报文到了(这个报文是已经失效的),B以为A要再次创建一个新连接,于是向A发送确认报文。 
如果采用两次握手的话,此时连接已经建立了。但是A根本没有向B发送请求连接报文,所以A并不会理会B的确认。B以为此时连接已经建立了,就会一直等待A向它发送数据。这样B的资源就白白浪费了。 
但是采用三次握手就不同了,A不会因为B的确认而向B发送确认,B收不到A的确认,就知道B没有请求连接。B的资源也就不会浪费。

谢希仁版本的注解是:(参考)


2、为什么要四次挥手?

在TCP连接的时候ACK和SYN是一起发送的,断开连接的时候却没有一起发送。原因是:TCP是全双工的,接收到FIN意味着不会收到数据,但是却还可以发送数据。 
在建立连接的时候服务器可以把SYN和ACK放在一个包中进行发送。 
关闭连接的时候,一端收到FIN包此时还有数据没有发送完,就要向对方回复FIN包的ACK。将数据发送完之后再向对方发送FIN,所以分开发送。 
因为是各自互相发送FIN报文,以及发送对对方FIN报文的确认报文,所以要进行四次挥手。

第一次挥手: 
数据传输完成后要释放连接的时候,客户端的上层应用会向客户端发送连接释放的报文。并停止发送数据主动的关闭连接。客户端会向服务器发送连接释放的报文,报文的首部终止位FIN的值为1,之后客户端的进入FIN-WAIT-1的状态。 

第二次挥手: 
服务器端对客户端的终止终止请求报文进行应答并确认服务器端报文段的序号,发送完之后服务器端进入CLOSE-WAIT状态。此时连接处于半连接的状态,客户端已经没有向服务器端要发送的数据了,但是此时服务器端还可以向客户端发送数据。 

第三次挥手: 
如果服务器端没有向客户端再发送的数据,则服务器端的应用进程就会释放TCP连接。服务器端也会向客户端发送终止请求报文,发送完成之后服务器端就进入LAST-ACK状态。(最后确认状态) 

第四次挥手: 
客户端在收到服务器端的连接释放报文之后,再次向服务器端发送确认报文。是对第三次挥手的应答,此后客户端进入TIME-WAIT状态。客户端在发送确认报文之后不会立即结束,而是等待2MSL之后才会结束。 
MSL:最大报文段寿命。 
服务器端在收到客户端的确认报文之后就结束了此次连接进入closed状态。


原创粉丝点击