计算机网络(TCP协议)

1.面向连接的传输协议 TCP

TCP被称为面向连接的传输层控制协议,这是因为在一个应用程序给另一个应用程序发送数据之前这两个进程需要相互先"握手"。
TCP是全双工通信服务,如果一台主机上的进程A与另一台主机上的进程B存在一条TCP连接,那么应用层数据可以从A->B,也可以C->A,并且这可以是同时发生的;
TCP是点对点通信的,在一个TCP连接中是点对点的通信,所谓的"多播"模式,TCP是不支持的。

1.1 TCP通信的简易过程

客户端首先要发送一个特殊的TCP报文段,服务器用另一个特殊的TCP报文段来响应,最后客户在用第三个特殊TCP报文段最为应答,前两个报文段不承载真实数据或叫有效载荷,第三个报文段可以承载数据,这几个过程总体叫三次握手
一旦握手成功,进程间就可以通信了。客户端系统将TCP传输的数据保存到发送缓存中,发送缓存是发起三次握手期间设置的缓存之一,然后TCP协议服务就会不时地从发送缓存里取出一块数据,并将这块数据传递到操作系统网络层服务。

** TCP可从缓存里取出并放入报文段中的数据量受限于****最大报文长度 MSS**。MSS通常根据最初确定的有本地发送主机发送的最大链路层帧长度(**最大传输单元 MTU**)来设置。这个设置要保证一个TCP报文段加上TCP/IP首部长度(40字节)适合数据链路帧,以太网和PPP链路层协议都具有1500字节的MTU,因此MSS一般值为**1460字节**

TCP为每块客户数据配上一个TCP首部数据,从而形成多个TCP报文段(TCP Segment),这些报文段被传递到网络层,网络层将其封装在网络层的数据报中,添加IP数据首部等操作,随后继续下沉协议层,最后被发送到网络中。
当服务端接收到TCP的报文段后,该报文段数据会被放入服务端这个TCP连接的接收缓存中,应用程序随后读取数据流。
在这里插入图片描述

2.TCP报文结构

这里我就盗用图灵课堂老师的图吧!
在这里插入图片描述

序列号:TCP建立连接时由操作系统生成的随机数作为初始值,通过SYN包传递给接受端,每发送一 次数据,值就会累加一次数据字节大小这么多值,目的是解决包乱序问题。
确认应答号:指下一次期望收到数据的序列化,发送端收到这个确认号后可以认为在这个序号以前 的数据都正常被接受。目的是解决丢包问题。
首部长度:描述TCP首部总长度,常规情况下TCP首部的典型长度是20字节。
接受窗口:作用于TCP流量控制
选项:用于发送方和接收方协商最大报文长度MSS时,或在高速网络情况下用作窗口调节因子使用。
紧急数据指针:当紧急数据存在并给出指向紧急数据尾指针的时候,TCP必须通知接受层的上层。
控制标志位

     - `ACK`:值为1时,确认应答字段生效,TCP规定除了最初简历连接时的SYN包之外,这个值必须设置为1。
     - `RST`:值为1时,标识TCP连接中出现异常必须强制断开连接。
     - `SYN`:值为1时,标识希望建立连接,并在序列化中设定初始值。
     - `FIN`:值为1时,标识以后不会再有数据发送,希望断开连接。

3.TCP连接管理

3.1 TCP的三次握手

TCP协议是面向连接的,它的连接一共分为3步,我们一般叫它三次握手,如图大概所示:
在这里插入图片描述

我们对TCP三次握手细节进行梳理:

     1. 一开始,客户端和服务端的TCP控制服务处于`close关闭`状态,服务端进程启动时主动监听指定端口,服务端介时处于`listen监听`状态。
     1. 客户端随机设置初始化序列化字段,将SYN标志位置为1,以标识这是一个SYN请求建立连接的报文,随后客户端TCP处于`syn-sent连接发送`状态,如下图所示:![](https://img-blog.csdnimg.cn/img_convert/22295f102c092fc5b18b5fe5e51351ce.webp?x-oss-process=image/format,png#crop=0&crop=0&crop=1&crop=1&from=url&id=J7Qrm&margin=[object Object]&originHeight=453&originWidth=750&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&title=)
     1. 服务端系统接收到客户端的SYN请求连接报文后,服务端自己也随机初始化自己TCP的序列化,然后将客户端发送过来的`序列号+1`,然后将自己TCP报文的SYN和ACK值置为1,然后将此报文发送给客户端,此后服务端处于`syn-rcvd`状态,如下图所示:![](https://img-blog.csdnimg.cn/img_convert/085356f89e49af31302217991a2b9dd4.webp?x-oss-process=image/format,png#crop=0&crop=0&crop=1&crop=1&from=url&id=NG55J&margin=[object Object]&originHeight=447&originWidth=750&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&title=)
     1. 客户端收到服务端应答的报文后,将自己的TCP首部ACK置为1,将确认应答号置为刚收到服务端应答的`序列号+1`,然后将报文发送给服务端。`这一次报文可以携带真实数据了`,随后客户端处于`established 确立`状态,如下图所示:![](https://img-blog.csdnimg.cn/img_convert/f637de2cb10d23dacc7e2262fce6538b.webp?x-oss-process=image/format,png#crop=0&crop=0&crop=1&crop=1&from=url&id=OfJ8v&margin=[object Object]&originHeight=447&originWidth=750&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&title=)
     1. 服务端收到客户端的报文后,检查标志位和确认应答号等信息无误后,服务端自身处于`established 确立`状态;此后,TCP三次握手宣告完成,接下来就可以互发数据了。

3.1.1 为什么是三次握手?两次不行吗?四次不好吗?

           - 避免连接错位或历史连接:客户端连续发送多个SYN连接请求,很有可能旧的SYN报文先到达服务端,服务端照常返回ACK,那么如果只是这两次连接设计,那么旧的TCP请求其实是一个历史连接、过期的连接,服务端无法判断,所以至少要3次。
           - 同步双发初始序列号:序列号非常重要,客户端和服务端互相发送报文同步序列号至少就是2步操作,但是因为服务端应答客户端的ACK和传递自己的序列号可以融合为一步,所以没必要4次握手,3次足矣。
           - 避免资源浪费:如果是2次握手,客户端在网络阻塞情况下会频繁发送SYN报文,造成服务端大量接受无效无用的TCP连接请求,占用网络带宽和服务器文件资源。

3.2 TCP的四次挥手

有了TCP三次握手流程的熟悉,TCP断开连接采用的是4次挥手,理解起来更加容易一点
在这里插入图片描述

     1. 如果客户端准备关闭连接,此时会发送一个TCP首部`FIN`标志位,并置为1,随后客户端TCP进入`fin-wait-1`状态。
     1. 服务端接收到报文后,向客户端发送ACK应答,这是ACK标志位为1,确认号和SYN类似+1操作,随后服务端进入`closed-wait`状态。
     1. 客户端收到服务端的ACK应答报文后,进入`fin-wait-2`状态。
     1. 服务端随后又主动给客户端发送FIN报文,自身进入`last-ack`状态。
     1. 客户端收到服务端的FIN报文后,应答服务端ACK消息,之后进入`time-wait`状态
     1. 服务端收到客户端的ACK报文后,进入`close`状态,服务端TCP断开。
     1. 客户端在经过一段时间后,自动进入`close`状态,TCP连接宣告结束。

3.2.1 为什么是四次挥手,三次不行吗?

因为服务端的ACK和FIN过程之间需要处理和等待TCP数据,这两个过程不能融合到一个步骤,所以需要4次握手。

3.2.2 定时等待 time_wait是多久?MSL是什么?为什么要等待?

MSL:报文最大生存时间,它是任何报文在网络上存在的最大时间,超过这个时间的报文将被丢弃。因为TCP是基于IP协议的,IP协议首部字段中有一个TTL过期时间字段,这个数是数据报文经过过最大路由数量,没经过一个路由点就减1,当值为0时,数据包则丢弃。time_wait一般是2倍MSL,因为发送方从发送数据到接受响应都是RTT往返时间。而这个MSL不同的操作系统有不同的值,一般是30秒,不过也有1分钟、2分钟的系统。
之所以发起断开连接方需要进入time_wait状态,原因有两个:

              - 防止旧连接的数据报:如果客户端早早进入close状态,此时如果有相同端口的TCP连接被占用,此时收到服务端旧的响应数据,可能造成数据报的错乱,有了2MSL以后,发起断开方有足够的的时间容错,因为2MSL还未达到的数据会被在IP层抛弃掉。
              - 保证连接被正确的关闭:如果客户端早早进入close状态,恰好此时客户端发起的ack响应由于网络原因未到达服务端,那么服务端会卡在last-ack状态中,此时如果有另外SYN请求建立连接,那么就会被服务端应答RST强制关闭连接。有了time_wait,即使客户端的ACK没有到达,服务端一段时间后会重发FIN,客户端有足够的时间响应,保证安全。

4.TCP的可靠性传输机制

4.1 流控(流量控制机制)

试想,如果TCP没有流量控制,客户端发了疯似的一直给服务端发数据报文,会怎样?TCP提供了一种机制可以让客户端和服务端根据实际接收情况进行发送的力度,称之为流量控制
TCP是通过一个名叫接收窗口的变量来控制流量情况,接收窗口会给发送方一个指示,指示接收端还有多少可用的接收缓存。发送端TCP会定期发送一个窗口探测包进行窗口空闲量的探测。但是,窗口探测包有可能丢失,一旦丢失,发送端将不会发送数据,所以窗口探测包会随机发送。
TCP规范规定,主机A探测到主机B接收缓存为0时,不能继续发送数据,但是主机B开始有了空闲缓存时,A是不知道的,所以规范规定当主机B的接收窗口为0时,主机A继续发送只有1个字节数据的报文段,这些报文段将会被接收方确认,然后主机B有了空闲缓存后,在确认报文里将包含一个非0的接受窗口值。

4.2 拥塞控制

计算机网络是一个共享的环境,不同主机之间的通信可能会干扰通信的链路是的网络拥堵,TCP的流控只是处理了接收方和发送方的缓存不足的问题,但是网络链路无法控制。在出现网络拥堵的时候,如果TCP发送端还在发送数据报文,可能导致数据报文时延、丢失的情况,这时TCP发送端会重发消息,一旦重发,又会加剧整个网络链路的拥堵问题,如此恶性循环。
为了解决上述问题,TCP提供了拥塞控制,目的是避免发送方的数据填满整个网络,TCP定义了一个叫拥塞窗口的概念来解决。
拥塞窗口 cwnd:是TCP发送方维护的一个状态变量,它会根据网络的拥塞程度动态变换。当网络流畅时,cwnd值会增大,反之减小。拥塞控制的算法如下:

4.2.1 慢启动 slow-start

TCP开始建立连接时,cwnd会设置很小,例如为1MSS,在第一个报文确认后,cwnd值就会成倍增加,1->2->4->8以此类推
但是发送速度不可能一直增加下去,有如下三种情况会抑制:
1.如果慢启动的发送过程出现丢包的情况,那么TCP将发送发的cwnd置为1并重启 慢过程。
2.如果出现拥塞,TCP会维护一个慢启动阈值 ssthresh,它等于cwnd的一 半,当发送拥塞时,cwnd就是ssthresh/2
3.如果检测到3个冗余的ACK,这时TCP执行快速重传,并进入恢复状态。

4.2.2 拥塞避免

当TCP进入拥塞控制状态后,cwnd的值就等于拥塞时候的一半,所以无法每次报文到达后都将cwnd值翻倍,而是将cwnd值增加一个MSS。

4.2.3 快速恢复

对于使得TCP进入快速恢复状态缺失的报文段,对于每个收到的冗余ACK,cwnd的值都会增加一个MSS,当对丢失报⽂段的⼀个 ACK 到达时,TCP 在降低 cwnd 后进⼊拥塞避免状态。如果在拥塞控制状态后出现超时,那么就会迁移到慢启动状态,cwnd 的值被设置为 1 个 MSS,ssthresh 的值设置为 cwnd 的⼀半。

4.3 重传

TCP的重传机制是实现可靠传输的保证之一,TCP针对丢包问题设计了重传机制来解决,重传机制有常见的4种:

4.3.1 超时重传

发送方在发送数据时,设定一个计时器,当超过指定时间后,没有收到对方的ACK响应,就会重发报文。但是,如果重发的数据再超时,那么TCP的策略是超时时间加倍,这种方式实现简单,但是极端情况下超时周期很长。

4.3.2 快速重传

快速重传不以时间为准绳,如图:
在这里插入图片描述

当发送发接收到3个冗余的ACK应答报文时,将会进行快速重传丢失的报文,但是重传seq2还是seq2后面的全部,不同系统都有不同实现。为了解决这个问题,引入了SACK方法。

4.3.3 SACK 选择性确认

这种模式需要在TCP请求首部的选项字段里设置一个SACK的状态值,这样发送方就知道接受方缓存的数据有哪些,进而选择性重传。

4.3.4 Duplicate SACK

D-SACK基于SACK来高速发送方有哪些数据被重复接收。
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Minor王智

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值