三次握手
:::tip 🔔 浅显理解
a—>b:第一次握手,a问b你能听到吗(a发起,b等待)
b—>a:第二次握手,b回答能听到,并反问a能听到吗
a—>b:第三次握手,a回答b,能听到,连接建立
:::
动图
目的:保证收发双方都在线。
三次握手的主要过程
最开始时,客户端和服务器都在CLOSED可用状态,开始建立TCP连接之前,服务器端的一个端口已经被被动打开(Passive open),用于监听来自客户端的请求。客户端的端口可以主动打开(Active open),用于发起TCP连接。
:::tip 🔔 第一次握手
客户端向服务器端发送SYN报文段,不携带任何数据,SYN标志位(Flag)置1,包的序号为客户端的ISN(Initial Sequence Number),包发出后,客户端进入SYN_SEND状态,客户端知晓客户端的发包能力正常;
:::
:::tip 🔔 第二次握手
第二次握手服务端接收客户端发来的连接请求,以SYN+ACK报文段做出回应,包的SYN标志位置1,ACK标志位置1,序号为服务端的ISN(与客户端的ISN不同),确认码为客户端的ISN加1,包发出后,服务端进入SYN_RCVD状态,服务端知晓客户端的发包能力正常、服务端的发包能力正常,服务器的收包能力正常;
:::
:::tip 🔔 第三次握手
第三次握手客户端接收服务端发来的响应,以ACK报文段做出回应,这个报文段里可能包含数据,包的ACK置1,序号为客户端的ISN+1,确认码为服务端的ISN+1,此包发出后,客户端转为ESTABLISHED状态,客户端知晓服务端的发包能力正常,服务端的收包能力正常、客户端的收包能力正常。服务器接收到这个包后,也进入ESTABLISHED状态,服务端知晓客户端的收包能力正常,至此TCP连接被成功建立,可以进行数据传输。
:::
:::caution ⚠ 为什么使用三次握手
为了实现可靠传输,发送方和接收方始终需要同步( SYNchronize )序号。需要注意的是,序号并不是从 0 开始的,而是由发送方随机选择的初始序列号 ( Initial Sequence Number, ISN )开始 。由于 TCP 是一个双向通信协议, 通信双方都有能力发送信息, 并接收响应。因此,通信双方都需要随机产生一个初始的序列号,并且把这个起始值告诉对方。在这个过程中需要三次握手。
:::
四次挥手过程
:::caution ⚠
客户端和服务器均可以发起挥手,但是一般是客户端发起。
:::
STEP1:客户端向服务器发送TCP FIN控制报文段(segment)
STEP2:服务器接收到客户端的FIN报文段,确认并发送ACK报文段,关闭连接发送FIN
STEP3:客户端接收到服务器的FIN报文段,确认并发送ACK报文段
进入等待状态,如果再收到FIN则重新发送ACK,确保能够正常关闭连接。
STEP4:服务器接收到客户端的ACK报文段,关闭连接
:::tip 🔔 第四次挥手浅显理解
把客户端比作男孩,服务器比作女孩。通过他们的分手来说明“四次挥手”过程(举例而已)。
“第一次挥手”:日久见人心,男孩发现女孩变成了自己讨厌的样子,忍无可忍,于是决定分手,随即写了一封信告诉女孩。
“第二次挥手”:女孩收到信之后,知道了男孩要和自己分手,怒火中烧,心中暗骂:你算什么东西,当初你可不是这个样子的!于是立马给男孩写了一封回信:分手就分手,给我点时间,我要把你的东西整理好,全部还给你!
男孩收到女孩的第一封信之后,明白了女孩知道自己要和她分手。随后等待女孩把自己的东西收拾好。
“第三次挥手”:过了几天,女孩把男孩送的东西都整理好了,于是再次写信给男孩:你的东西我整理好了,快把它们拿走,从此你我恩断义绝!
“第四次挥手”:男孩收到女孩第二封信之后,知道了女孩收拾好东西了,可以正式分手了,于是再次写信告诉女孩:我知道了,这就去拿回来!
这里双方都有各自的坚持。
女孩自发出第二封信开始,限定一天内收不到男孩回信,就会再发一封信催促男孩来取东西!
男孩自发出第二封信开始,限定两天内没有再次收到女孩的信就认为,女孩收到了自己的第二封信;
若两天内再次收到女孩的来信,就认为自己的第二封信女孩没收到,需要再写一封信,再等两天。
:::
来自:https://blog.csdn.net/spade_Kwo/article/details/119464901 (opens in a new tab)
TCP拥塞(Congestion)控制
拥塞:对某一资源的需求超过了该资源所能提供的部分。太多主机发送了太多数据或者发送速度太快了。
表现:分组丢失(路由器缓存溢出)、分组延迟过大(在路由器缓存中排队)
当输入的负载到达一定程度 吞吐量不会增加,即一部分网络资源会丢失掉,网络的吞吐量维持在其所能控制的最大值,转发节点的缓存不够大这造成分组的丢失是拥塞的征兆。
做以下假设: 数据是单方向输入传送的,而另一个方向只传送确认。
接收方总是有足够大的缓存空间,因此发送方只需要考虑网络的拥塞程度。
以TCP最大报文段的个数为讨论的单位,而不是字节。
湖南科技大学MOOC拥塞控制详解
湖南科技大学MOOC拥塞控制详解 (opens in a new tab)
:::tip 🔔 示例如下 传输轮次:发送方给接收方发送数据报文段后,接收方给发送方发回相应的确认报文段,一个传输轮次所经历的时间就是往返时间RTT(RTT并非是恒定的数值),使用传输轮次是为了强调,把拥塞窗口cwnd所允许发送的报文段都连续发送出去,并收到了对已发送的最后一个报文段的确认,拥塞窗口cwnd会随着网络拥塞程度以及所使用的拥塞控制算法动态变化。
在tcp双方建立逻辑链接关系时, 拥塞窗口cwnd的值被设置为1,还需设置慢开始门限ssthresh,在执行慢开始算法时,发送方每收到一个对新报文段的确认时,就把拥塞窗口cwnd的值加一,然后开始下一轮的传输,当拥塞窗口cwnd增长到慢开始门限值时,就使用拥塞避免算法。
:::
:::tip 🔔 慢开始 假设当前发送方拥塞窗口cwnd的值为1,而发送窗口swnd等于拥塞窗口cwnd,因此发送方当前只能发送一个数据报文段(拥塞窗口cwnd的值是几,就能发送几个数据报文段),接收方收到该数据报文段后,给发送方回复一个确认报文段,发送方收到该确认报文后,将拥塞窗口的值变为2.
发送方此时可以连续发送两个数据报文段,接收方收到该数据报文段后,给发送方一次发回2个确认报文段,发送方收到这两个确认报文后,将拥塞窗口的值加2变为4,发送方此时可连续发送4个报文段,接收方收到4个报文段后,给发送方依次回复4个确认报文,发送方收到确认报文后,将拥塞窗口加4,置为8,发送方此时可以连续发送8个数据报文段,接收方收到该8个数据报文段后,给发送方一次发回8个确认报文段,发送方收到这8个确认报文后,将拥塞窗口的值加8变为16.
当前的拥塞窗口cwnd的值已经等于慢开始门限值,之后改用拥塞避免算法。 :::
:::tip 🔔 拥塞避免算法
也就是每个传输轮次,拥塞窗口cwnd只能线性加一,而不是像慢开始算法时,每个传输轮次,拥塞窗口cwnd按指数增长。同理,16+1……直至到达24,假设24个报文段在传输过程中丢失4个,接收方只收到20个报文段,给发送方依次回复20个确认报文段,一段时间后,丢失的4个报文段的重传计时器超时了,发送发判断可能出现拥塞,更改cwnd和ssthresh.并重新开始慢开始算法,如图所示:
:::
:::tip 🔔 快速重传 发送方发送1号数据报文段,接收方收到1号报文段后给发送方发回对1号报文段的确认,在1号报文段到达发送方之前,发送方还可以将发送窗口内的2号数据报文段发送出去,接收方收到2号报文段后给发送方发回对2号报文段的确认,在2号报文段到达发送方之前,发送方还可以将发送窗口内的3号数据报文段发送出去,
假设该报文丢失,发送方便不会发送针对该报文的确认报文给发送方,发送方还可以将发送窗口内的4号数据报文段发送出去,接收方收到后,发现这不是按序到达的报文段,因此给发送方发送针对2号报文段的重复确认,表明我现在希望收到的是3号报文段,但是我没有收到3号报文段,而收到了未按序到达的报文段,发送方还可以将发送窗口中的5号报文段发送出去,接收方收到后,发现这不是按序到达的报文段,因此给发送方发送针对2号报文段的重复确认,表明我现在希望收到的是3号报文段,但是我没有收到3号报文段,而收到了未按序到达的报文段,,发送方还可以将发送窗口内的最后一个数据段即6号数据报文段发送出去,接收方收到后,发现这不是按序到达的报文段,因此给发送方发送针对2号报文段的重复确认,表明我现在希望收到的是3号报文段,但是我没有收到3号报文段,而收到了未按序到达的报文段,
此时,发送方收到了累计3个连续的针对2号报文段的重复确认,立即重传3号报文段,接收方收到后,给发送方发回针对6号报文的确认,表明,序号到6为至的报文都收到了,这样就不会造成发送方对3号报文的超时重传,而是提早收到了重传。
:::
:::caution ⚠ 拥塞控制部分搬运来自 CSDN博主「程序媛_婷」,原文链接:https://blog.csdn.net/qq_41431406/article/details/97926927 (opens in a new tab) :::
:::tip TCP拥塞控制推荐好文 https://www.cnblogs.com/tuyang1129/p/12439862.html (opens in a new tab) :::