计算机网络中TCP的三次握手与四次挥手一直都不是很清楚,今天认真的学习了一下,在此记录下来:
三次握手:
这里A代表TCP客户端程序(Client),B代表TCP服务器程序,最初两者都是处于CLOAE(关闭)状态。现在A先打开连接,B被动打开连接 ,B的TCP服务器进程先创建传输控制块TCB,准备接收客户端进程的连接,并处于LISTEN(收听状态):
(1)第一次握手:A的TCP客户进程也先创建传输控制块TCB,然后A首次发送同步位(SYN=1),序列号随机数字x(seq=x)的报文段,SYN报文段不携带数据,但是要消耗一个序列号。同时A进入SYN-SENT(同步发送)状态;
(2)第二次握手:B接收到A的报文段请求后,如果同意连接,着发出确认:SYN和ACK都设置为1,序列号选择另一个随机数seq=y,确认号为ack=x+1。此报文也是不能携带数据,同样消耗了一个序号。这时B处于SYN-RCVD(同步接收状态)
(3)第三次握手:A收到收到B的确认后,还要给B发送确认。确认报文段的ACK=1,确认号ack=y+1,自己的序号seq=x+1,ACK报文段可以携带数据,如果不携带则不消耗序号。这时A和B的TCP连接已经建立,A进入ESTABLISHED(已建立连接)状态。
B收到A的确认后也进入ESTABLISHED(已建立连接)状态。
注意:ACK和ack的区别:一个是确认值(Acknowledgement),为1便是确认连接;另一个是确认编号(Acknowledgement Number),即接收到的上一次远端主机传来的seq然后+1,再发送给远端主机。提示远端主机已经成功接收上一次所有数据。
问题:为什么A还要发送一次确认?
为了防止已失效的报文又传到了B。考虑这样一种情况:假设A发送了连接请求报文,丢失了没有收到确认。再次发送一个请求,收到确认并建立了TCP连接,数据传输结束后又释放了TCP连接。但是第一次发送的那个请求是在某个网络结点长期滞留了,但是在连接释放以后的某个结点到达了B,B误认为是A的一次新的连接请求,所以同意连接。并向A发送确认,但是A并没有发送建立连接请求,所以不会理睬B,B却一直等待A的数据,白白浪费了资源。
四次挥手:
TCP释放过程要复杂一些,现在A和B都处在建立连接的状态:
(1)第一次挥手:A首先向B发出释放报文,并停止发送数据,释放报文的首部控制位FIN置1,序号seq=u(等于前面已经传送过来的数据的最后一个字节的序号加1).这时A进入FIN-WAIT-1(终止等待1)状态,等待B的确认。
(2)第二次挥手:B收到释放报文段后发送确认,ACK=1,确认号ack=u+1,序号seq=v(等于前面已经传送过来的数据的最后一个字节的序号加1),然后B进入CLOSEWAIT(关闭)状态。A到B的这个方向的连接就释放了。这时TCP处于半关闭状态,A已经没有数据要发送了,但是如果B还有数据要发送,A仍然要接收。
(3)第三次挥手:A收到B的确认后就处于FIN-WAIT-2(终止等待2)状态,等待B发出释放报文。当B的数据传输完了,就像A发送释放报文:FIN=1,ACK=1,seq=w(等于前面已经传送过来的数据的最后一个字节的序号加1),B还必须重复上次已经发送过的确认号:ack=u+1.这时A就进入到了LAST-ACK(最后确认)状态。等待A的确认。
(4)第四次挥手:A收到B的报文后,必须再发送确认:ACK=1,seq=u+1(FIN报文要消耗一个序号),ack=w+1。然后进入到TIME-WAIT(时间等待)状态。此时连接还没有被释放掉,还需要经过一个时间等待计时器(TIME-WAIT timer)设置成两个最长报文寿命及2MSL(Maximum Segment Lifetime),时间到了A进入CLOSED状态。
B收到确认后也进入CLOSED状态。
问题:连接的时候是三次握手,为什么释放的时候需要四次挥手?
以为连接的时候同步SYN和确认ACK可以同时发送。但是挥手时,因为B有可能数据没有传输完,终止FIN和ACK不能同时发送。这样就多出了一次挥手。
TCP释放连接时为什么time_wait状态必须等待2MSL时间
因为有可能A最后ACK报文没有发送到B,B等待了一定时间会超时重传,会再此发送FIN信息,在2MSL时间内,A可以收到FIN做出响应。确保B可以正常进入CLOSE
参考文章: