TCP三次握手四次挥手

一、三次握手

三次握手是指建立一个TCP连接时,需要客户端和服务器总共发送3个包,进行三次握手的主要作用是为了确认双方的接收能力是否正常,指定自己的初始化序列号为后面的可靠性传送做准备,实质上其实就是连接服务器指定端口,建立TCP连接,并同步连接双方的序列号和确认号,交换TCP窗口大小信息

刚开始客户端处于closed的状态,服务端处于Listen状态

第一次握手:

客户端给服务端发送一个SYN报文,并指明客户端的初始化序列号ISNC,此时客户端处于SYN_SEND状态.

首部的同步位SYN=1,初始化序列号seq=x,SYN=1的报文段不能携带数据,但要消耗掉一个序号

第二次握手:

服务器收到客户端的SYN报文后,会以自己的SYN报文作为应答,并且也是指定了自己的初始化序列号ISN(s),同时会把客户端的ISN+1 作为ACK的值,表示自己已经收到了客户端的SYN,此时服务器处于SYN_REVD的状态

在确认报文段中SYN=1,ACK=1,确认号ack=x+1,初始序号seq=y

第二次握手:

服务器收到客户端的SYN报文后,会以自己的SYN报文作为应答,并且也是指定了自己的初始化序列号ISN(s),同时会把客户端的ISN+1 作为ACK的值,表示自己已经收到了客户端的SYN,此时服务器处于SYN_REVD的状态

在确认报文段中SYN=1,ACK=1,确认号ack=x+1,初始序号seq=y

第三次握手:客户端收到SYN报文后,会发送一个ACK报文,也是一样的把服务器的ISN+1作为ACK的值,表示已经收到了服务端的SYN报文,此时客户端处于ESTABLISHED状态,服务器收到ACK报文后,也处于ESTABLISHED状态,此时双方已经建立了连接

确认报文段ACK=1,确认号ack=y+x,序号seq=x+q(初始化seq=x,第二报文段所以要+1)ACK报文段可以携带数据,不携带数据则不消耗序号

发送第一个SYN的一端将执行主动打开(active open),接收这个SYN并发回下一个SYN的另一端执行被动打开(passive open)

在socket编程中,客户端执行connect()时,将触发三次握手

关于三次握手的问题:

问:为什么进行三次握手?可以两次么?

答:三次握手的目的是确认客户端和服务端的接收、发送能力正常

第一次握手:客户端发包,服务端收到了

这样服务端就能得出结论,客户端的发送能力正常,服务端的接收能力正常

第二次握手:服务端发包,客户端收到了

这样客户端就能得出结论:服务端的接收、发送能力,客户端的接收、发送能力是正常的,不过此时服务端并不能确认客户端的接收能力是否正常

第三次握手:客户端发包,服务端收到了

这样服务端就能得出结论:客户端的接收、发送能力正常,服务端自己的接收、发送能力正常

所以需要三次握手才能确认服务器端和客户端的的接收、发送能力是否正常

二、四次挥手

建立一个连接需要三次握手,而终止一个连接要经过四次挥手(也有将四次挥手叫做四次握手的)。这由TCP的半关闭(half-close)造成的,所谓的半关闭,其实就是TCP提供了连接的一端在结束它的发送后还能接收来自另一端数据的能力

TCP连接的拆除需要发送四个包,因此称为四次握手(Four-way handshake)客户端或服务器均可主动发起挥手动作

刚开始双方都处于ESTABLISHED状态,但是如果是客户端先发起关闭请求,四次挥手的过程如下:

第一次挥手:

客户端发送一个FIN报文,报文中会指定一个序列号,此时客户端处于FIN_WAITI状态

即发出连接释放报文段,(FIN=1,序号seq=u),并停止再发送数据,主动关闭TCP连接,进入FIN_WAIT1(终止等待1)状态,等待服务端的确认

第二次挥手:

服务端收到FIN之后,会发送ACK报文,并把客户端的序列号值+1作为ACK报文的序列号值,表明已经收到客户端的报文了,此时服务端处于CLOSE_WAIT状态。

即服务端收到连接释放报文段后即发出确认报文段(ACK=1,确认号ACK=1,序号seq=w,确认号ack=u+1),服务端进入CLOSE_WAIT2(终止等待2)状态,等待服务端发出的连接释放报文段

第三次挥手:

如果服务端也想断开连接了,和客户端的第一次挥手一样,发送FIN报文,并指定一个序列号,此时服务端处于LAST_ACK的状态

即服务端没有要向客户端发出的数据,服务端发出连接释放报文段(FIN=1,ACK=1,序号seq=w,确认号ack=u+1)服务端进入LAST_ACK(最后确认)状态,等待客户端的确认

第四次挥手:

客户端收到FIN之后,一样发送一个ACK报文作为应答,并且把服务端的序列号值+1作为自己ACK报文的序列号值,此时客户端处于TIME_WAIT状态,需要经过一阵子以确保服务端收到自己的ACK报文之后才会进入CLOSED状态,服务端收到ACK报文后,就处于关闭连接了,处于CLOSED状态

即客户端收到服务端的连接释放报文段后,对此发出确认报文段(ACK=1,seq=u+1,ack=w+1),客户端进入TIME_WAIT(时间等待)状态,此时TCP未释放掉,需要经过时间等待计时器设置的时间2MSL后,客户端才进入CLOSED状态

收到一个FIN意味着在这一个方向上没有数据流动,客户端执行主动关闭并进入TIME_WAIT是正常的服务端通常执行被动关闭,不会进入TIME_WAIT状态

在socket编程中,任何一方执行close()操作即可产生回收操作

关于四次挥手的问题
1、挥手为什么需要四次

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

2、2MSL等待状态

TIME_WAIT状态也称为2MSL等待状态,每个具体TCP实现必须选择一个报文段最大生存时间MSL(Maximun Segment Lifetime),他是任何报文段被丢弃前在网络内的最长时间,这个时间是有限的,因为TCP报文段以IP数据包在网络内传输,而IP数据包则有限制其生存时间的TTL字段

对一个具体实现所给定的MSL值,处理的原则是:当TCP执行一个主动关闭,并发送最后一个ACK,该连接必须在TIME_WAIT状态,停留的时间为2倍的MSL,这样可让TCP再次发送最后的ACK以防这个ACK丢失(另一端超时并发送最后的FIN)

这种2MSL等待的另一个结果是这个TCP连接在2MSL等待期间,定义这个连接的插口(客户的IP地址和端口号,服务器的IP地址和端口号)不能被再次使用,这个连接只能在2MSL结束后才能被再次使用

3、四次挥手释放连接时,等待2MSL的意义

为了保证客户端发送的最后一个ACK报文段能够到达服务器,因为这个ACK有可能丢失,从而导致处在LAST_ACK状态的服务器收不到对FIN_ACK的确认报文,服务器会超时重传这个FIN_ACK,解这客户端再重传一次确认,重新启动时间等待计时器,最后客户端和服务器都能正常的关闭,假设客户端不等待2MSL,而是在发送完ACK之后直接释放关闭,一旦这个ACK丢失的话,服务器就无法正常的进入关闭连接状态

两个理由:

1、保证客户端发送的最后一个ACK报文段能够发送服务端

这个ACK报文段很可能会丢失,使得处于LAST_ACK状态的的B收不到对已发送的FIN+ACK报文段的确认,服务端超时重传FIN+ACK报文段,而客户端能在2MSL时间内收到这个重传的FIN+ACK报文段,接着客户端重传一次确认,重新启动2MSL计时器,最后客户端和服务端都进入到CLOSED状态,若客户端在TIME_WAIT状态不等待一段时间,而是发送完ACK报文段后立即释放连接,则无法收到服务端红船的FIN+ACK报文段,所以不会再发送一次确认报文段,则服务端无法正常进入到CLOSED状态

2、防止 已失效的连接请求报文段出现在本连接中

客户端再发送完最后一个ACK报文后,在经过2MSL,就可以使本连接持续的时间内所产生的所有报文段都从网络中消失,使下一个新的连接中不会出现这种旧的连接请求报文段

4、为什么TIME_WAIT状态需要经过2MSL才能返回到CLOSE状态?

理论上,四个报文都发送完毕,就可以直接进入CLOSED状态了,但是可能网络是不可靠的,有可能最后一个ACK丢失,所以TIME_WAIT状态就是用来重发可能丢失的ACK报文

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值