【网络】理解TCP协议的三次握手四次挥手

TCP解决以下问题

  1. 顺序问题:给包编号
  2. 丢包问题:发出去的包返回的确认序号
  3. 连接维护:三次握手四次挥手
  4. 流量控制,把握分寸:窗口大小,标识自己当前处理能力
  5. 拥塞(se)控制:拥塞控制

TCP的三次握手

在这里插入图片描述
请求–>应答–>应答之应答

目的

  1. 双方建立可靠连接
    原理:只要确保双方的消息都有去有回就可以了
  2. 沟通TCP包的序号的问题
    A告诉B:我的起始序号
    B告诉A:我的起始序号
    note:序号不能都从1开始,因为往往会产生冲突!
    原因:例如,A连上B之后,发送了1、2、3三个包,但是发送3的时候,中间丢了,或者绕路了,于是重新发送,后来A掉线了,重新连上B后,序号又从1开始,然后发送2,但是压根没想发送3,但是上次绕路的那个3又回来了,发给了B,B自然认为,这就是下一个包,于是发生了错误。
    因而,每个连接都要有不同的序号。这个序号的起始序号是随着时间变化的,可以看成一个32位的计数器,每4ms加一,如果计算一下,如果到重复,需要4个多小时,那个绕路的包早就死翘翘了,因为我们都知道IP包头里面有个TTL,也即生存时间。
  3. 维护连接
    在这里插入图片描述

TCP四次挥手

原理:A消息的有去有回+B消息的有去有回

TCP连接的断开比建立复杂一些,本质上是因为资源的申请(初始化)本身就比资源的释放简单,以c++为例,构造函数初始化对象很简单,而析构函数则要考虑所有资源安全有序的释放,TCP断连时序中除了断开这一重要动作,另外重要的潜台词是“我要断开连接了,你赶紧把收尾工作做了(等待时间)"

A:B啊,我不想玩了。(A进入FIN-WAIT-1状态)
B:哦,你不想玩了啊,我知道了。(B进入CLOSED-WAIT状态,等待处理A发送过但还为收到的数据;A收到后,进入FIN-WAIT-2状态);该阶段,A无需应答

这个时候,还只是A不想玩了,也即A不会再发送数据,但是B能不能在ACK的时候,直接关闭呢?当然不可以了,很有可能A是发完了最后的数据就准备不玩了,但是B还没做完自己的事情,还是可以发送数据的,所以称为半关闭的状态
这个时候A可以选择不再接收数据了,也可以选择最后再接收一段数据,等待B也主动关闭。

B:A啊,好吧,我也不玩了,拜拜。(B处理完结尾事情,进入LAST-ACK
A:好的,拜拜。
这样整个连接就关闭了。但是这个过程有没有异常情况呢?当然有,上面是和平分手的场面。
A开始说“不玩了”,B说“知道了”,这个回合,是没什么问题的,因为在此之前,双方还处于合作的状态,如果A说“不玩了”,没有收到回复,则A会重新发送“不玩了”。但是这个回合结束之后,就有可能出现异常情况了,因为已经有一方率先撕破脸。
一种情况是,A说完“不玩了”之后,直接跑路,是会有问题的,因为B还没有发起结束,而如果A跑路,B就算发起结束,也得不到回答,B就不知道该怎么办了。另一种情况是,A说完“不玩了”,B直接跑路,也是有问题的,因为A不知道B是还有事情要处理,还是过一会儿会发送结束。
那怎么解决这些问题呢?TCP协议专门设计了几个状态来处理这些问题。我们来看断开连接的时候的状态时序图。

在这里插入图片描述

TCP状态机

在这个图中,加黑加粗的部分,是上面说到的主要流程,其中阿拉伯数字的序号,是连接过程中的顺序,而大写中文数字的序号,是连接断开过程中的顺序。加粗的实线是客户端A的状态变迁,加粗的虚线是服务端B的状态变迁。
在这里插入图片描述

补充

  1. 既然TCP保证有序性,为什么还要在应用层写重发机制?
    应用层重发机制是解决应用层的错误,假设你调用一个进程,但是未成功,重试是给另一个进程发。

猜你喜欢

转载自blog.csdn.net/vict_wang/article/details/88693591