(五)比老干妈还香的TCP酱油

什么是TCP协议

一.概要

 在网络层有Ip协议解决了网络区域的划分,不同网络位置定位等问题,但这无法保证数据是否是完整的,列举几个原因:

  1. 在数据链接层中会发送数据帧(过大会分帧发送),数据帧经过交换机时,缓存已满,CRC检验错误等会造成数据丢失。
  2. 不同主机的应用层之间经常需要可靠的、像管道一样的连接,但是IP层不提供这样的流机制,而是提供不可靠的包交换。
  3. 环境影响,在强干扰的环境下,信号出现失真时。
  4. 网络拥塞,堵塞造成的丢包。
意愿
  1. 如何保证数据安全可靠达到接收端。
  2. 如何在带宽拥塞的情况下,还能保证数据的安全发送。
  3. 如何避免数据包丢失,让数据实现端到端的传送。
  4. 如何有效利用带宽资源,提高传输效率。
  5. 如何确定连接健康有效。
提出

 在抽象一层面向连接的运输层,主要负责向两个主机中进程之间的通信提供服务,通过流量控制、分段/重组和差错控制来保证数据传输的可靠性,其中有两个常见协议 TCP协议以及UDP协议。
在这里插入图片描述

二.TCP协议

 TCP协议是一种面向连接(面向字节流)的机制,也叫做传输控制协议,需要与接收端建立连接才能实现通话,类似打电话一样,保证通话的质量。

TCP结构

在这里插入图片描述

  • 16位目标端口,用来识别接收端应用进程(App,电脑软件等),端口号0到65535之间。
  • 16位源端口, 发送端发送数据的应用进程。
  • 32位序号,用来标识源端向目标端发送的字节流,它表示这个报文的第一个数据字节位置,用来重组TCP数据,丢包验证。
  • 32位确认序号,当ACK为1时,该字段才有效,它指明目标端期望收到源端的第一个数据字节位置。
  • 数据偏移长度字段:占4比特。指定头部占32比特的数目。没有任何选项字段的TCP头部长度为20字节;最多可以有60字节的TCP头部。
  • 标志位字段(U、A、P、R、S、F):占6比特。各比特的含义如下:
    • URG:紧急指针(urgent pointer)有效。
    • ACK:为1时,确认序号有效。
    • PSH:为1时,接收方应该尽快将这个报文段交给应用层。
    • RST:为1时,重建连接。
    • SYN:为1时,同步程序,发起一个连接。
    • FIN:为1时,发送端完成任务,释放一个连接。
  • 窗口大小字段,占有16比特,用来流量控制,指期望接收的字节。
  • 校验和字段,占16比特,对整个报文,即TCP头部和TCP数据进行校验和计算,并由目标端进行验证数据是否完善。
  • 紧急指针字段,占16比特。它是一个偏移量,和序号字段中的值相加表示紧急数据最后一个字节的序号,需要紧急接收的数据序号。
  • 选择和填充字段,占用32位比特,其他扩展控制,例如流量窗口扩充因子,时间戳等。
连接过程
  • 三次握手言和

在这里插入图片描述

  1. B服务器为了先准备宴席招待A客户端的到来,缓解彼此的关系,进入Listen(监听)状态。
  2. A客户端向B服务端询问是否开始了,报文中SYN标志位1,初始序列号seq=x, 此时A客户端进入SYN-SENT(同步发送)状态。
  3. B服务端接收到客户端询问报文后,发送确认报文,告诉A客户端可以来了,报文中的ACK=1,表示启动确认序号,确认序号是x+1,数据序列号是seq=y,同时进入SYN-RCVD(同步收到)状态。
  4. A客户端收到B服务端确认报文后,要向B服务端发送现在就出发的确认报文,报文中启动确认序列号,ACK=1,确认序列号为y+1,数据的序列号是x+1。
  5. 此时,A客户端开着车到达宴会了,进入了ESTAB-LISHED(建立链接)状态,B服务端收到A客户端的出发报文后 也进入了ESTAB-LISHED状态,双方可以聚会聊天了。
  • 知识补充
  1. TCP规定,SYN为1时不能携带数据,需要消耗一个序列号seq。
  2. ACK表示启动确认序列号,确认序列号是ack,表示目标端期待接收到源端下一个数据序列号。
  3. 其中seq代表的是发送端的数据的第一个字节序列号,无论对于客户端还是服务端,都需要拿seq与自己发送的最后一次的ack做比较,如果不等,说明数据包丢失了,需要重传。
  4. 为什么不用两次连接,某种情况下,A客户端发送的询问(连接)报文在网络的拥塞或者其他原因导致滞留延迟到达B服务端,A客户端久久没有收到回复,认为B服务端没有收到,就再次发送询问报文,这次报文B服务端收到并回复确认报文,这时之前滞留的询问报文到达了B服务端,由于B服务端之前已经与A客户端建立连接,又重新建立了一次连接,浪费了网络资源等。
断开过程
  • 四次挥手道别
    在这里插入图片描述
  1. A客户端参加完宴会后,要向B服务端告别(断开),内容FIN=1,表示这是离别的意思,数据序列号seq等于之前传送数据的最后一个字节加1,假设为u,A客户端告诉后进入FIN-WAIT-1(终止等待)状态。
  2. B服务端收到离别消息后,告诉A客户端,我有礼品还需要给你,你等下,此时ACK为1,确认序号为u+1, 自己的序列号为seq=v,进入CLOSE-WAIT(关闭等待)状态。
  3. A客户端收到B服务端的通知后,就坐了下来喝茶,等B服务端拿礼品过来,进入了了FIN-WAIT-2(终止等待2)状态。
  4. B服务端将礼品拿来后,告诉A客户端这是专门给他准备的礼物,你就拿回去看看,此时的报文是FIN=1,表示结束链接,ACK=1,确认序列号为ack=u+1,seq=w,进入LAST-ACK(最后状态),等待A客户端确认。
  5. A客户端看到这个礼物后,感受到B服务端的热情,告诉B服务端,之前的事情就过往不究了,拿着礼物感慨了2∗MSL(最长报文段寿命)的时间后终于开车离开了这次的宴会,此时报文ACK=1,ack = w+1,seq=u+1,进入了TIME-WAIT(时间等待)状态。
  6. B服务端听到A客户端的释怀,自己也着手收拾起茶具,结束这次宴会了。此时进入了CLOSED状态。
  • 知识补充
  1. A客户端为什么要等待2MSL(Maximum Segment Lifetime)时间。
     因为为了保证A客户端最后一次的ACK报文能够达到B服务端,并且每次收到服务端结束的报文后时间会重置。例如,B服务端问你收下礼物开不开心,你突然说得很小声(丢包或者其他情况引起)很开心,就想开车离开,但B服务端听不到,就再次问你一次,如果A客户端直接走了,就失礼了。
     让滞留在网络上的报文请求从网络上消失,这样新的连接中就不会出现旧的连接的报文请求。
     TCP协议规定,主动关闭连接的一方要处于TIME_ WAIT状态,等待2
    MSL(maximum segment lifetime)的时间后才能回到CLOSED状态,在TIME_WAIT期间不能再次监听同样的端口。
  2. 客户端发送故障了怎么办?
     TCP有一个存活计时器,如果客户端发送故障,服务端会每隔75分钟发送一次,若发送10次报文都没有回应,说明出故障了,主动关闭连接。
  3. 为什么要四次挥手道别呢?
      因为服务端可能有未发送完的数据,需要让客户端等待一段时间。
  4. 从断开流程来看,服务端往往比客户端优先结束链接。
ACK应答机制

 上文提到过的seq数据序列号,还有ack确认序列号,就是用来应答识别丢包,以及重传数据包。TCP会把不符合MTU(1518字节)传输大小的包,实际大小为1460字节(移出各种协议的占有字节)进行分割成若干的符合MTU的包

  • 应答过程

在这里插入图片描述
在这里插入图片描述

       1. A主机发送数据到B主机,并告诉数据seq为1(数据第一个位置)
       2. 主机收到后解析数据,并告诉主机A需要起始序列号为1001的数据。
       3. 主机A收到后,解析主机B需要1001数据,就会把1001数据发送给主机B。
       4. 其他步骤同理。
  • 要点提示

 主机B每一次收到数据,都会跟最后一次确认应答ack作比较,如果不相同,则认为丢包了,这时就需要告诉主机A重传丢包的数据。

重传机制

 ACK应答能使数据完整组装,但有个问题就是丢包处理问题,如果发生数据发送丢失,这时就需要重传了。

  • 重传过程

    在这里插入图片描述

    • 主机A发送数据到主机B,seq为1,并开始重传时间倒计时。
    • 主机B收到数据后,发送确认应答ack = 1001。
    • 由于某种原因导致主机B的确认应答无法发送到主机A。
    • 主机A由于没收到主机B的确认应答,重传时间倒计时到了,再次发送序列号seq为1的数据。
    • 主机B收到再次收到数据后,根据seq查看是否有收到类似的数据,如果有就过滤了,再次发送确认应答 ack=1001.
    • 累计重传到一定次数后,TCP会认为网络异常,并且强制关闭连接。
  • 要点提示

      理想的超时时间确定,TCP为了保证任何环境下都能保持较高的通讯质量,会动态计算这个最大的超时时间, 超时都是以500ms单位的整数倍来计算.如果重发一次之后, 仍然得不到应答, 等待 2500ms 后再进行重传. 如果仍然得不到应答, 等待 4500ms 进行重传,以此类推。

滑动窗口机制
  • 滑动窗口结构
     通过应答机制,明白了每一次发送数据时,都需要给个ACK确认应答,确认后才继续发送数据,不然就重传数据。这样会有一个问题,在区域距离比较远或者通讯质量差的情况下,通讯性能会出现瓶颈。
     基于问题提出了,窗口概念,窗口大小无需等待确认应答就可以发送多条数据,当收到一个确认应答数据后就继续往后移动,所以称为滑动窗口
    在这里插入图片描述
     操作系统会在内部维护这个滑动窗口,并开辟发送缓冲区来记录当前还有哪些数据没应答,只有确认ACK应答过的数据,才从缓冲区删掉。在这里插入图片描述
  • 如何滑动

假如窗口的大小为3,每间隔1000字节表示一个包。
在这里插入图片描述

       1.  发送端同时发送三个数据包(2001-5000),
       2.  接收端响应确认应答包为ack =4001, 
       3.  发送端收到这个响应,认为(2001-4001)两个数据包已经收到了,窗口就会向下滑动一格。
       4.  可能会有疑问,为什么2001-3001这个数据包不用确认应答,这就要看看重传机制了。
  • 基于滑动窗口的重传机制,“快重传”
  • 第一种情况
     以滑动窗口大小为三,数据包大小为1000大小为例,接收端发送确认应答,由于网络因素导致发送端无法收到其中个别的确认应答,但收到最后一条,会认为之前发送的数据已经达到接收端了,滑动窗口继续向下滑动三个格子。
  • 过程
    在这里插入图片描述
  1. 发送端同时发送 3 个数据包 1-1000、1001-2000 和 2001-3000。
  2. 接收端接收到这些数据,并给出确认应答包,数据包 1-1000 和数据包 2001-3000 的确认应答包没有丢失,但是数据包 1001-2000 的确认应答包丢失了。
  3. 发送端验证seq,收到了确认应答包,虽然没有收到数据包 1001-2000 的确认应答包,但是收到了数据包 2001-3000 的确认应答包,认为第一次发送的 3 个数据包都成功到达了接收端再次发送 3 个数据包 3001-4000、4001-5000 和 5001-6000。
  4. 接收端收到后并给出确认应答包,数据包 3001-4000 和数据包 4001-5000 的确认应答包丢失了,但是数据包 5001-6000 没有丢失。
  5. 发送端收到数据包 5001-6000 确认应答的数据包。判断第 2 次发送的 3 个数据包都成功到达了接收端。再次发送 3 个数据包 6001-7000、7001-8000 和 8001-9000。
  • 第二种情况

 发送端发送的数据包丢失,例如A数据包丢失了,接收端收到B数据包,返回确认应答,指示客户端需要发送A数据包,并缓存起来B数据包,发送端收到3次这样的确认应答后,就会重新发送A数据包。

  • 过程
    在这里插入图片描述
  1. 这里窗口大小为 4,发送端发送 4 个数据包,分别为 1-1000、1001-2000、2001-3000 和 3001-4000。
  2. 发送端收到1-1000确认应答(seq比较),指示发送1001-2000,已经发送过的过滤,窗口向下滑动一格,发送4001-5000数据包;
  3. 发送端收1001-2000确认应答(seq比较),指示发送2001-3000,已经发送过的过滤,窗口向下滑动一格,发送5001-6000数据包。
  4. 接收端接收完发送1001-2000应答后,需要接收2001-3000的数据包,一直收不到,之后又收到了3001-4000的数据包,通过seq比较,认为2001-3000数据包丢失了,下一次要接收的数据为2001-3000.
  5. 发送端收到了3001-4000的数据包确认应答(seq比较),指示下一个数据包发送2001-3000,发送端认为不是已经发送过了吗,开始计数1,窗口头滑动到4001的位置,扩充窗口大小到4,把新添加进来数据包6001-7000以及7001-8000发送出去。
  6. 接收端依次收到了新的数据包4001-5000,5001-6000时,并告诉发送端,我需要2001-3000数据,并把数据缓存起来,响应确认应答,指示发送端发送2001-3000数据包。
  7. 发送端收到4001-5000确认数据包,ack指示发送数据为2001-3000,发送端认为这个数据可能有点慢到,计数为2,滑动窗口继续向下滑动一格。
  8. 发送端收到5001-6000确认数据包,ack又指示发送数据为2001-3000,发送端这时才意识到事情的严重性,计数达到3,把数据2001-3000重新发送出去,等待反馈ack,超时就重传。
  9. 之前发送出去6001-7000以及7001-8000的数据包,接收端也响应的确认应答,发送端发现ack也是要发送数据为2001-3000的数据包,刚好刚才发送了,正在等待回馈。
  10. 收到2001-3000的响应数据包后,查看ack指示下一个数据包,发现是8001,这时窗口移动到该位置,继续把包含进去的发送出去。
流量控制

 正常来说,接收端的处理数据是有限的,如果发送端发送太快,就会导致接收端的缓存区被填满,这时候再继续发送数据包,就会产生丢包问题,引发一系列的重传等连锁反应。
 基于问题,提出了流量控制,接收端可以根据自己的接收缓冲区的大小来决定下一次数据接收的数据大小,在TCP首部中就有一个“窗口大小”字段,用来指明接收的大小,通过ACK应答机制告诉发送端。
 当接收端的缓存区大小为0时,发送端收到后不会再发送数据,等待接收端发送窗口更新的数据包,如果超过重传时间还没收到这个窗口更新,发送端会发送窗口探知的数据包给接收端,反馈接收端的窗口大小。在这里插入图片描述

拥塞控制

 TCP虽然有滑动窗口来解决高效发送大量数据,但网络是每时每刻都有数据通讯,有时很通畅,有时很拥塞,如果你在拥塞的情况下,一下子发送大量数据,本来就拥塞的情况,会出现更加拥塞,甚至数据丢失的可能。
 因此引入了慢重传的机制,定义拥塞窗口,先发送少量的数据,了解当前网络通讯情况,再决定发送多大数据量,归根到底就是TCP协议想尽可能快的把数据传输给对方, 但是又想避免给网络造成太大压力。
 动态变化的拥塞的窗口CWND,其值取决于网络的拥塞程度,每次发送数据的时候,将拥塞窗口和接收端主机反馈的窗口大小做比较, 取较小的值作为实际发送的窗口.

  • 拥塞控制四个关键点

在这里插入图片描述

  • 慢开始

     假设当前的窗口CWND为1,而此时发送窗口swnd等于拥塞窗口cwnd(区较小的),因此发送方当前只能发送一个数据报文段,接收到一个确认应答报文后,拥塞窗口在扩大变为2,此时发送窗口往往大于拥塞拥塞窗口,发送窗口设为2,在继续发,以此类推,拥塞窗口增长很快,所以又提出了慢开始的阈值。
     当慢开始达到阈值ssthresh时,停止慢开始,改用拥塞避免算法。

  • 拥塞避免

     拥塞避免,并非指完全能够避免拥塞,而是在拥塞避免阶段,将拥塞窗口控制为按线性规律增长,使用网络不容易出现拥塞,意思就是过了慢开始的阈值后,每次回传拥塞窗口CWND的大小按线性增长,每次递增1.
     当数据包发送超时重传时,慢开始阈值变回原来的一般,拥塞窗口CWND大小变为1,开始慢开始算法。
     这又引出一个问题,当数据发送丢失,但实际网络未发送拥塞,那么就会错误的认为网络拥塞,并认定为超时重传,影响发送速率, 1990年又新添加了两个规则,快重传以及快恢复。

  • 快重传

     快重传,在上文的滑动窗口重传机制有介绍了,就是发送端收到一个数据包ack指示某个数据包时,就会把数据包重新发送。在这里插入图片描述

  • 快恢复

     当发送方收到3个重复确认数据包时,认定这时丢失个别的数据包,不开始超时重传,不启动慢开始算法,而执行快恢复。
     慢开始阈值降为原来的一半,更新发送窗口为拥塞窗口的大小。

延迟应答

 在TCP中,有确认应答机制以保证数据的可靠传输,但是是不是接收方收到数据就立即返回ACK应答呢,如果是这样,这时候的缓冲区中接受的数据还没能够处理,缓冲区的剩余大小就是窗口大小。
  如果接收端收到数据后立刻返回ACK应答,这时候返回的窗口可能比较小,那是因为接受完数据后,缓冲区快满了,当发送端收到这个ACK发现窗口很小,就会影响发送数据,降低网络利用率,从而引入了延迟应答机制。
 在收到数据以后并不立即返回确认应答,延迟一会,等待缓冲区中数据被处理,那么剩余的缓冲区就会大些——这是延迟应答。在这里插入图片描述

  • 例如
  1. 假设接受端缓冲区为1M,一次收到了500K的数据;如果立刻应答,返回的窗口就是500K。
  2. 但实际上可能处理端处理的速度很快,10ms之内就把500K数据从缓冲区消费掉了。
  3. 在这种情况下,接收端处理还远没有达到自己的极限,即使窗口再放大一些,也能处理过来。
  4. 如果接收端稍微等一会再应答,比如等待200ms再应答,那么这个时候返回的窗口大小就是1M;
  • 问题
  1. 如果延迟的话,要是超过重传时间怎么办. 这点会有时间限制还有数量限制,每个多少时间接收端应答一次,每个多少包接收端应答一次,尽可能避免重传时间,具体的数量和超时时间, 依操作系统不同也有差异.
  2. 在系统中,有一个固定的定时器每隔200ms会来检查是否需要发送ACK确认应答包。
  • 好处
  1. 延迟应答可以时数据窗口扩大些,提高网络利用率。
  2. 可以合并ACK,连续收到两个TCP,不一定需要ACK两次,只要把最有一次回复确认应答就好,降低网络流量。
  3. 如果接收方要发送数据,那么就会在发送数据的TCP数据包里, 带上ACK信息,可以避免大量的ACK单独发送TCP包,减少网络流量, 这点跟捎带应答机制有关。
捎带应答

 在应用层,发送出去的消息到达对端后,对端处理后会反馈一个回执,就是客户端与服务器在应用层也是“一发一收”的,意味着客户端发送“你好”,服务端也会给客户端回馈一个“你好”。
 接收端在处理数据后,不应该马上发送ACK应答数据包,在延迟应答的基础上,处理接收端要发送的数据并带上ACK确认应答 一同 发送出去,这就是捎带应答,能提高网络利用率从而降低计算机处理负荷的一种机制。在这里插入图片描述

  • 流程
  1. 主机A发送数据包,我需要数据的首部序列号是1,我把数据1-24发给你,seq=1,ack=1
  2. 主机B收到数据,延迟应答一会,把数据1-5(可能由于分包)发送给主机A,同时主机B告诉主机A,我需要数据首部序列号为25的,seq=1,ack=25.
  3. 主机A收到后,把数据首部序列号为25的25-27发给主机B,并告诉主机B我需要数据首部序列号为6的,seq=25,ack=6.
  4. 以此类推…
  • 知识回顾
  1. 每次接收端或者发送端,会延迟一会处理好数据后,携带ACK一起确认应答。
TCP是基于字节流,双全工

 当一个TCP被创建出来,内核中就会创建一个发送缓冲区以及一个接收缓冲区,可以通过这两个缓冲区进行读或写操作,这个概念就叫做双全工
在这里插入图片描述

  • 步骤
  1. 创建TCP的Socket,内核创建两个缓冲区,一个接收缓冲区,一个发送缓冲区。
  2. 使用写入(write)操作,把数据写入到发送缓冲区中。
  3. TCP协议发现,这个数据大于MTU(IP协议的数据分片)发送的最大数据(MTU)1500字节),TCP默认(1460)),对数据进行分包发送。
  4. 如果发送的数据包过小,就会等待数据填充到差不多的大小发送出去,或者需要确认应答的时候就发送出去。
  5. 接收端接收数据从物理层-数据链路层-网络层,层层拆分到TCP层载入接收缓冲区。
  6. 应用层程序就会通过端口,读取缓冲区的数据处理,同时把需要发送的数据载入到发送缓冲区。
  • 知识回顾
  1. 如果发送数据超过MTU默认长度,会分包发送。
  2. 由于发送是基于字节流的,所以不管写入(write)缓冲区多少次都没事,1次也行,100次也行,超过某段时间,TCP会携带发送缓冲区的数据应答过去。
  3. 同样,写入可以这么写,读也可以怎么读,接收缓冲区的数据都是从TCP接收过来的,当然要注意的事,要处理掉缓冲区的数,如果不处理,超过某个应答时间200ms,接收端就会发送ack应答。

三.TCP 异常情况

  1. 设备断电或者其他特殊情况,接收端认为连接还在,每隔一段时间会询问对方是否还在,这是由一个保活计时器在验证的,如果不在,连接会主动关闭。
  2. 如果是进程终止,那么内核会发送FIN结束连接的数据包,跟正常连接关闭一样。
  3. 另外也有一些应用层的检测协议,例如QQ等,时不时检测是否在线。

四.TCP总结

  • 根据以上的情况,回到开头的问题。
  1. 如果保证数据安全可靠达到接收端。
    • CRC校验和
    • seq序列号(按序到达)
    • ack确认应答
    • 超时重传
  2. 如何在带宽拥塞的情况下,还能保证数据的安全发送。
    • 流量控制
    • 拥塞控制
  3. 如何避免数据包丢失,让数据实现端到端的传送。
    • seq序列号验证丢包
    • 超时重传
    • 快重传
  4. 如何有效利用带宽资源,提高传输效率。
    • 滑动窗口
    • 快恢复以及快重传
    • 延迟应答
    • 捎带应答
  5. 如何确定连接健康有效。
    • TIME_WAIT定时器。
    • 检验连接的保活定时器。
  6. 基于TCP的应用层协议
    • HTTP和 HTTPS 通讯协议
    • SMTP
    • Telnet
    • SSH
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

晨守星

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

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

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

打赏作者

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

抵扣说明:

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

余额充值