TCP三次握手

TCP三次握手和TCP四次挥手

 

标志位

SYN: 表示连接请求 ACK: 表示确认 FIN: 表示关闭连接 seq:表示报文序号 ack: 表示确认序号

  1. 第一次握手:Client将标志位SYN置为1,随机产生一个值seq=J,并将该数据包发送给Server,Client进入SYN_SENT状态,等待Server确认。

  2. 第二次握手:Server收到数据包后由标志位SYN=1知道Client请求建立连接,Server将标志位SYN和ACK都置为1,ack (number )=J+1,随机产生一个值seq=K,并将该数据包发送给Client以确认连接请求,Server进入SYN_RCVD状态。

  3. 第三次握手:Client收到确认后,检查ack是否为J+1,ACK是否为1,如果正确则将标志位ACK置为1,ack=K+1,并将该数据包发送给Server,Server检查ack是否为K+1,ACK是否为1,如果正确则连接建立成功,Client和Server进入ESTABLISHED状态,完成三次握手,随后Client与Server之间可以开始传输数据了。

为什么是三次握手而不是两次
第一次连接请求报文由于网络节点长时间滞留了,导致延误到连接释放后的某个时间才到达 Server。这时 Server 会再次给 Client 发送确认报文(第二次握手),但是 Client 进程程序并不会理睬确认报文,因为 Client 没有发送连接请求。

现在假如没有第三次握手就会建立连接,那么这次滞后的连接请求报文就会导致 TCP 误建立连接,而 Client 却不知已经建立连接,并不会发送数据给 Server,这样 Server 就会一直处于等待状态,这样就白白浪费了 Server 的很多资源。但有了第三次握手就会避免这种问题的发生,虽然延迟的连接请求发送到了 Server,但 Client 不会处理 Server 的确认报文,也不会再次发送确认请求报文,这样 Server 就知道了 Client 并没有真正想建立连接。

TCP四次挥手

TCP三次握手和TCP四次挥手

由于TCP连接时全双工的,因此,每个方向都必须要单独进行关闭,这一原则是当一方完成数据发送任务后,发送一个FIN来终止这一方向的连接,收到一个FIN只是意味着这一方向上没有数据流动了,即不会再收到数据了,但是在这个TCP连接上仍然能够发送数据,直到这一方向也发送了FIN。首先进行关闭的一方将执行主动关闭,而另一方则执行被动关闭:

第一次挥手:Client发送一个FIN,用来关闭Client到Server的数据传送,Client进入FIN_WAIT_1状态

第二次挥手:Server收到FIN后,发送一个ACK给Client,确认序号为收到序号 1(与SYN相同,一个FIN占用一个序号),Server进入CLOSE_WAIT状态。

第三次挥手:Server发送一个FIN,用来关闭Server到Client的数据传送,Server进入LAST_ACK状态。

第四次挥手:Client收到FIN后, Client 进入 TIME-WAIT状态,此时连接还没释放,必须经过时间等待计时器设置的时间 2MSL 后,Client 才进入 CLOSED 状态。时间 MSL 叫做最长报文段寿命,RFC 793建议设为 2 分钟。也就是说 Client 需要等待2*MSL=2*2=4分钟后才可以真正关闭连接然后再去建立下一个连接,接着发送一个ACK给Server,确认序号为收到序号 1,Server进入CLOSED状态,完成四次挥手。

为什么 Client 需要等待 2MSL?
先说第一点,如果Client直接CLOSED了,那么由于IP协议的不可靠性或者是其它网络原因,导致Server没有收到Client最后回复的ACK。那么Server就会在超时之后继续发送FIN,此时由于Client已经CLOSED了,就找不到与重发的FIN对应的连接,最后Server就会收到RST而不是ACK,Server就会以为是连接错误把问题报告给高层。这样的情况虽然不会造成数据丢失,但是却导致TCP协议不符合可靠连接的要求。所以,Client不是直接进入CLOSED,而是要保持TIME_WAIT,当再次收到FIN的时候,能够保证对方收到ACK,最后正确的关闭连接。

再说第二点,如果Client直接CLOSED,然后又再向Server发起一个新连接,我们不能保证这个新连接与刚关闭的连接的端口号是不同的。也就是说有可能新连接和老连接的端口号是相同的。一般来说不会发生什么问题,但是还是有特殊情况出现:假设新连接和已经关闭的老连接端口号是一样的,如果前一次连接的某些数据仍然滞留在网络中,这些延迟数据在建立新连接之后才到达Server,由于新连接和老连接的端口号是一样的,又因为TCP协议判断不同连接的依据是socket pair,于是,TCP协议就认为那个延迟的数据是属于新连接的,这样就和真正的新连接的数据包发生混淆了。所以TCP连接还要在TIME_WAIT状态等待2倍MSL,这样可以保证本次连接的所有数据都从网络中消失。

为什么连接时时三次,断开时是四次
这是因为服务端在LISTEN状态下,收到建立连接请求的SYN报文后,把ACK和SYN放在一个报文里发送给客户端。而关闭连接时,当收到对方的FIN报文时,仅仅表示对方不再发送数据了但是还能接收数据,己方也未必全部数据都发送给对方了,所以己方可以立即close,也可以发送一些数据给对方后,再发送FIN报文给对方来表示同意现在关闭连接,因此,己方ACK和FIN一般都会分开发送。

 

相关文章:

猜你喜欢
相关资源
相似解决方案