TCP连接的建立与关闭

TCP

TCP是面向连接的协议,所以TCP运输连接的建立和释放是每次TCP通信中必不可少的过程;

在整个TCP运输连接中存在三个阶段:连接建立、传输数据、连接释放,而计算机系统需要一个管理机制来保证TCP运输连接的建立和释放都能正常的进行,这个管理过程就是通过通信双方在知晓对方存在的情况下,通过一些参数进行协商,运输实体资源;

“三次/四次握手”-TCP连接的建立

假设A是TCP客户,B是TCP服务器

  1. 双方先都处于CLOSED状态;

  2. 当系统启动后,B作为服务器端开启连接,创建传输控制块TCB,进入并保持LISTEN状态,等待客户端连接请求(此时会对客户端发来的请求做出响应);

  3. 在服务端进入LISTEN状态之后,A作为客户端开始它的连接流程,首先同样是创建TCB,此时要向B发送连接请求报文段(SYN);SYN报文段按照TCP规定不包含数据部分,最主要的信息就是其中的两个字段“SYN=1,seq=x(某一个序号值)”;此时A进入SYN-SENT(同步请求已经发送)状态;

    这里插一句,在TCP连接不管是建立还是释放的过程中,所发送的报文都要消耗一个序号;唯有一个例外,就是ACK报文段,ACK报文段是允许携带数据的,如果携带数据则消耗序号,如果不携带数据则不消耗

  4. 正在LISTEN状态的B接收到A发来的SYN报文之后,需要作出响应,回传一个SYN=1,ACK=1,seq=y(某一个序号值),ack=x+1的请求确认报文(ACK),发送完毕之后B进入SYN-RCVD(received)状态;

    SYN=1表示该报文是同步报文,ACK=1表示该报文是对收到报文的确认报文,ack=x+1是因为要回复的报文的seq=x

    为什么TCP连接的建立过程又可以叫三次握手又可以叫四次握手呢?因为这一步骤B发送的报文发挥了两个作用,一是确认A发来的连接请求,二是发送从B到A的连接请求;可以说TCP连接全双工的特点在这里体现,一定是AB的双向连接都建立完毕之后整个连接过程才算成功;

    但其实我们知道当B回传了SYN之后,A其实已经可以认为反向连接已经建立了,为什么还要再向B发送ACK报文呢?这里引出一个问题

  5. 由于B在回复A的连接请求的同时,也发送了从B到A的连接请求,所以A先进入ESTABLISHED(A到B的单向连接已经建立)状态,之后也必须像上一步一样向B发送ACK=1,seq=x+1,ack=y+1的确认报文;

    seq=x+1是因为A第一次发送请求报文时seq=x,而TCP连接建立和释放的过程中每发送一个报文都要消耗一个序号;

  6. 当B收到A的确认报文之后,说明B到A的单向连接也已经建立完成,此时B也进入ESTABLISHED状态,至此宣告AB之间的TCP连接建立完成;

第三/四次握手的意义

这是为了防止存在A到B的超时的SYN报文,如果它来的很晚,此时A因为长时间没收到B的ACK报文已经进入连接超时异常了,这时B突然又收到了该超时报文并向A发送了SYN+ACK报文,这时B会认为由A到B的连接已经建立了;这就导致了双方的不同步,B会一直等待A,知道B通过重复确认之后主动结束连接才会回到正常流程,这样会导致B浪费了太多的资源;

“四次挥手”-TCP连接的释放

  1. 双方都先处于ESTABLISHED状态

    上面说到TCP连接是双向全双工的,如果要释放连接的话同样也是先关闭主动方到被动方的连接,然后再关闭反向的连接;

  2. 首先A的某个应用请求关闭已经建立的TCP连接,此时A会发送结束报文段(FIN)(同样不携带数据)主要信息有两个字段“FIN=1,seq=u(某一个序号值)”,发送完毕后A就进入到FIN-WAIT-1(主动-被动连接终止等待)状态;

  3. 当B受到A的FIN请求之后,则会通知对应应用即将关闭连接,同时向A发送对A的FIN请求确认的ACK报文,其中“ACK=1,seq=v(某一个序号值),ack=u+1”,B此时进入CLOSE-WAIT(关闭等待)状态,此时B仍然可以向A发送数据

    CLOSE-WAIT阶段存在的意义就是给B一个上层协议处理时间,将扫尾工作做完,该发的发,该设置的设置;

    这里多说一句,在笔者通过查阅资料得知(欢迎大家补充),有两种情况可能会导致一个CLOSE-WAIT时间变得非常长:当服务器端同时响应了过多的连接关闭请求,或者因为其他一些事情导致没来得及响应请求时,这个CLOSE-WAIT的时间就会变长;后一种一般都是程序代码编写问题,要不是服务器端程序未做好close处理,或者程序响应速度太慢;前一种就是没有做好分布处理,响应队列阻塞导致严重超时

  4. 当A接收到B的ACK报文之后,A即进入FIN-WAIT-2,此时A到B的连接已经被释放了,并且继续等待B发来的FIN报文;

  5. 当B的CLOSE-WAIT阶段结束之后,随即向A发送FIN报文,包含“FIN=1,ACK=1,seq=w,ack=u+1”,告知A:从B到A的连接也即将关闭了,此时B进入LAST-ACK状态,等待A回传最终的确认;

    为什么B到A的FIN报文也包含了ACK信息呢?这是因为在这一阶段B仍然可以向A发送数据,所以在数据传输阶段之后,需要通过设置ACK状态值告知A:“连接关闭流程继续”;即seq=w是因为前面还可能发送了其他报文所以才不是v+1,ack=u+1说明该报文仍是对上面步骤2中A发送的FIN报文进行确认;

  6. A接收到B发来的FIN报文之后,即向B发送ACK报文,包含信息“ACK=1,seq=u+1,ack=w+1”,进入TIME-WAIT状态,在这之后A仍需等待2MSL时间才会将传输控制块TCB销毁,进入CLOSED状态,完全结束连接;

    这里引出一个问题,为什么要存在TIME-WAIT这个时间段?直接结束连接不好吗?

  7. 当B收到最后的ACK报文之后,就会进入进入CLOSED状态,完全结束连接;

TIME-WAIT的意义

首先说明MST一般设置为2m,虽然对现在的网络来说比较长了;

有两个原因:

防止报文丢失

如果LAST-ACK阶段A发出的ACK报文最终并没有传到B,那么B在等待超时之后即会向A发送超时重传上一阶段FIN

+ACK的报文段,同样的以上所提到过的每一阶段如果出现超时问题,都有对应的检测和恢复手段;

当A接收到B的重传之后,会重置2MST计时,并再次发送最后的ACK报文,通过这样的机制保证B能正确进入CLOSED状态;

防止存在超时报文

2MST的时间能保证网络中不再存在超时的连接报文,以避免上述第三/四次握手中出现的问题;

保活计时器

正常进行流程时,每一次成功执行当前步骤都会刷新保活计时器,这个机制有点像嵌入式设计中的watchdog计时器,意义就是保证程序正常执行而不超时,通常设定为2h;

当某一个阶段有客户端出现错误时,整个流程不能再进行下去,一旦计时器归零(2h内都没有收到客户端的消息),服务器端即会每隔75s发送一次探测报文,十次后仍没有回应则会强制终止连接

参考:

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值