请选择 进入手机版 | 继续访问电脑版

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

[复制链接]
丶禁飞 发表于 2021-1-1 10:30:00 | 显示全部楼层 |阅读模式 打印 上一主题 下一主题
什么是TCP协议

一.概要

 在网络层有Ip协议管理了网络区域的分别,不同网络位置定位等问题,但这无法包管数据是否是完整的,枚举几个原因:

  • 在数据链接层中会发送数据帧(过大会分帧发送),数据帧颠末互换机时,缓存已满,CRC检验错误等会造成数据丢失。
  • 不同主机的应用层之间常常需要可靠的、像管道一样的毗连,但是IP层不提供这样的流机制,而是提供不可靠的包互换。
  • 环境影响,在强干扰的环境下,信号出现失真时。
  • 网络拥塞,堵塞造成的丢包。
意愿


  • 如何包管数据安全可靠到达接收端。
  • 如安在带宽拥塞的情况下,还能包管数据的安全发送。
  • 如何制止数据包丢失,让数据实现端到端的传送。
  • 如何有效使用带宽资源,提高传输效率。
  • 如何确定毗连康健有效。
提出

 在抽象一层面向毗连的运输层,主要负责向两个主机中进程之间的通信提供服务,通过流量控制、分段/重组和不对控制来包管数据传输的可靠性,此中有两个常见协议 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位比特,其他扩展控制,比方流量窗口扩充因子,时间戳等。
毗连过程



  • 三次握手言和


  • B服务器为了先准备宴席招待A客户端的到来,缓解相互的关系,进入Listen(监听)状态。
  • A客户端向B服务端询问是否开始了,报文中SYN标记位1,初始序列号seq=x, 此时A客户端进入SYN-SENT(同步发送)状态。
  • B服务端接收到客户端询问报文后,发送确认报文,告诉A客户端可以来了,报文中的ACK=1,表示启动确认序号,确认序号是x+1,数据序列号是seq=y,同时进入SYN-RCVD(同步收到)状态。
  • A客户端收到B服务端确认报文后,要向B服务端发送现在就出发简直认报文,报文中启动确认序列号,ACK=1,确认序列号为y+1,数据的序列号是x+1。
  • 此时,A客户端开着车到达宴会了,进入了ESTAB-LISHED(创建链接)状态,B服务端收到A客户端的出发报文后 也进入了ESTAB-LISHED状态,双方可以集会谈天了。


  • 知识补充

  • TCP规定,SYN为1时不能携带数据,需要消耗一个序列号seq。
  • ACK表示启动确认序列号,确认序列号是ack,表示目的端等待接收到源端下一个数据序列号。
  • 此中seq代表的是发送端的数据的第一个字节序列号,无论对于客户端照旧服务端,都需要拿seq与自己发送的最后一次的ack做比力,如果不等,说明数据包丢失了,需要重传。
  • 为什么不消两次毗连,某种情况下,A客户端发送的询问(毗连)报文在网络的拥塞大概其他原因导致滞留延迟到达B服务端,A客户端久久没有收到回复,认为B服务端没有收到,就再次发送询问报文,这次报文B服务端收到并回复确认报文,这时之前滞留的询问报文到达了B服务端,由于B服务端之前已经与A客户端创建毗连,又重新创建了一次毗连,浪费了网络资源等。
断开过程



  • 四次挥手道别



  • A客户端参加完宴会后,要向B服务端告别(断开),内容FIN=1,表示这是离别的意思,数据序列号seq即是之前传送数据的最后一个字节加1,假设为u,A客户端告诉后进入FIN-WAIT-1(终止等待)状态。
  • B服务端收到离别消息后,告诉A客户端,我有礼品还需要给你,你等下,此时ACK为1,确认序号为u+1, 自己的序列号为seq=v,进入CLOSE-WAIT(关闭等待)状态。
  • A客户端收到B服务端的通知后,就坐了下来品茗,等B服务端拿礼品过来,进入了了FIN-WAIT-2(终止等待2)状态。
  • B服务端将礼品拿来后,告诉A客户端这是专门给他准备的礼品,你就拿回去看看,此时的报文是FIN=1,表示竣事链接,ACK=1,确认序列号为ack=u+1,seq=w,进入LAST-ACK(最后状态),等待A客户端确认。
  • A客户端看到这个礼品后,感受到B服务端的热情,告诉B服务端,之前的事情就过往不究了,拿着礼品感慨了2∗MSL(最长报文段寿命)的时间后终于开车脱离了这次的宴会,此时报文ACK=1,ack = w+1,seq=u+1,进入了TIME-WAIT(时间等待)状态。
  • B服务端听到A客户端的释怀,自己也着手收拾起茶具,竣事这次宴会了。此时进入了CLOSED状态。


  • 知识补充

  • A客户端为什么要等待2MSL(Maximum Segment Lifetime)时间。
     因为为了包管A客户端最后一次的ACK报文可以或许到达B服务端,而且每次收到服务端竣事的报文后时间会重置。比方,B服务端问你收下礼品开不开心,你突然说得很小声(丢包大概其他情况引起)很开心,就想开车脱离,但B服务端听不到,就再次问你一次,如果A客户端直接走了,就失礼了。
     让滞留在网络上的报文请求从网络上消失,这样新的毗连中就不会出现旧的毗连的报文请求。
     TCP协议规定,主动关闭毗连的一方要处于TIME_ WAIT状态,等待2
    MSL(maximum segment lifetime)的时间后才气回到CLOSED状态,在TIME_WAIT期间不能再次监听同样的端口。
  • 客户端发送故障了怎么办?
     TCP有一个存活计时器,如果客户端发送故障,服务端会每隔75分钟发送一次,若发送10次报文都没有回应,说明出故障了,主动关闭毗连。
  • 为什么要四次挥手道别呢?
      因为服务端大概有未发送完的数据,需要让客户端等待一段时间。
  • 从断开流程来看,服务端往往比客户端优先竣事链接。
ACK应答机制

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


  • 应答过程


  1.        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.        1.  发送端同时发送三个数据包(2001-5000),       2.  接收端响应确认应答包为ack =4001,        3.  发送端收到这个响应,认为(2001-4001)两个数据包已经收到了,窗口就会向下滑动一格。       4.  大概会有疑问,为什么2001-3001这个数据包不消确认应答,这就要看看重传机制了。
复制代码


  • 基于滑动窗口的重传机制,“快重传”
  • 第一种情况

     以滑动窗口巨细为三,数据包巨细为1000巨细为例,接收端发送确认应答,由于网络因素导致发送端无法收到此中个别简直认应答,但收到最后一条,会认为之前发送的数据已经到达接收端了,滑动窗口继续向下滑动三个格子。
  • 过程



  • 发送端同时发送 3 个数据包 1-1000、1001-2000 和 2001-3000。
  • 接收端接收到这些数据,并给出确认应答包,数据包 1-1000 和数据包 2001-3000 简直认应答包没有丢失,但是数据包 1001-2000 简直认应答包丢失了。
  • 发送端验证seq,收到了确认应答包,虽然没有收到数据包 1001-2000 简直认应答包,但是收到了数据包 2001-3000 简直认应答包,认为第一次发送的 3 个数据包都成功到达了接收端再次发送 3 个数据包 3001-4000、4001-5000 和 5001-6000。
  • 接收端收到后并给出确认应答包,数据包 3001-4000 和数据包 4001-5000 简直认应答包丢失了,但是数据包 5001-6000 没有丢失。
  • 发送端收到数据包 5001-6000 确认应答的数据包。判断第 2 次发送的 3 个数据包都成功到达了接收端。再次发送 3 个数据包 6001-7000、7001-8000 和 8001-9000。


  • 第二种情况
 发送端发送的数据包丢失,比方A数据包丢失了,接收端收到B数据包,返回确认应答,指示客户端需要发送A数据包,并缓存起来B数据包,发送端收到3次这样简直认应答后,就会重新发送A数据包。


  • 过程



  • 这里窗口巨细为 4,发送端发送 4 个数据包,分别为 1-1000、1001-2000、2001-3000 和 3001-4000。
  • 发送端收到1-1000确认应答(seq比力),指示发送1001-2000,已经发送过的过滤,窗口向下滑动一格,发送4001-5000数据包;
  • 发送端收1001-2000确认应答(seq比力),指示发送2001-3000,已经发送过的过滤,窗口向下滑动一格,发送5001-6000数据包。
  • 接收端接收完发送1001-2000应答后,需要接收2001-3000的数据包,一直收不到,之后又收到了3001-4000的数据包,通过seq比力,认为2001-3000数据包丢失了,下一次要接收的数据为2001-3000.
  • 发送端收到了3001-4000的数据包确认应答(seq比力),指示下一个数据包发送2001-3000,发送端认为不是已经发送过了吗,开始计数1,窗口头滑动到4001的位置,扩充窗口巨细到4,把新添加进来数据包6001-7000以及7001-8000发送出去。
  • 接收端依次收到了新的数据包4001-5000,5001-6000时,并告诉发送端,我需要2001-3000数据,并把数据缓存起来,响应确认应答,指示发送端发送2001-3000数据包。
  • 发送端收到4001-5000确认数据包,ack指示发送数据为2001-3000,发送端认为这个数据大概有点慢到,计数为2,滑动窗口继续向下滑动一格。
  • 发送端收到5001-6000确认数据包,ack又指示发送数据为2001-3000,发送端这时才意识到事情的严重性,计数到达3,把数据2001-3000重新发送出去,等待反馈ack,超时就重传。
  • 之前发送出去6001-7000以及7001-8000的数据包,接收端也响应简直认应答,发送端发现ack也是要发送数据为2001-3000的数据包,刚好刚才发送了,正在等待回馈。
  • 收到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发现窗口很小,就会影响发送数据,低就逮络使用率,从而引入了延迟应答机制。
 在收到数据以后并不立刻返回确认应答,延迟一会,等待缓冲区中数据被处理惩罚,那么剩余的缓冲区就会大些——这是延迟应答。



  • 比方

  • 假设接受端缓冲区为1M,一次收到了500K的数据;如果立刻应答,返回的窗口就是500K。
  • 但实际上大概处理惩罚端处理惩罚的速度很快,10ms之内就把500K数据从缓冲区消费掉了。
  • 在这种情况下,接收端处理惩罚还远没有到达自己的极限,即使窗口再放大一些,也能处理惩罚过来。
  • 如果接收端稍微等一会再应答,好比等待200ms再应答,那么这个时候返回的窗口巨细就是1M;


  • 问题

  • 如果延迟的话,要是凌驾重传时间怎么办. 这点会有时间限制还有数量限制,每个多少时间接收端应答一次,每个多少包接收端应答一次,尽大概制止重传时间,详细的数量和超时时间, 依操纵系统不同也有差别.
  • 在系统中,有一个固定的定时器每隔200ms会来检查是否需要发送ACK确认应答包。


  • 长处

  • 延迟应答可以时数据窗口扩大些,提高网络使用率。
  • 可以归并ACK,一连收到两个TCP,不一定需要ACK两次,只要把最有一次回复确认应答就好,低就逮络流量。
  • 如果接收方要发送数据,那么就会在发送数据的TCP数据包里, 带上ACK信息,可以制止大量的ACK单独发送TCP包,淘汰网络流量, 这点跟捎带应答机制有关。
捎带应答

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



  • 流程

  • 主机A发送数据包,我需要数据的首部序列号是1,我把数据1-24发给你,seq=1,ack=1
  • 主机B收到数据,延迟应答一会,把数据1-5(大概由于分包)发送给主机A,同时主机B告诉主机A,我需要数据首部序列号为25的,seq=1,ack=25.
  • 主机A收到后,把数据首部序列号为25的25-27发给主机B,并告诉主机B我需要数据首部序列号为6的,seq=25,ack=6.
  • 以此类推…


  • 知识回首

  • 每次接收端大概发送端,会延迟一会处理惩罚好数据后,携带ACK一起确认应答。
TCP是基于字节流,双全工

 当一个TCP被创建出来,内核中就会创建一个发送缓冲区以及一个接收缓冲区,可以通过这两个缓冲区举行读或写操纵,这个概念就叫做双全工



  • 步调

  • 创建TCP的Socket,内核创建两个缓冲区,一个接收缓冲区,一个发送缓冲区。
  • 使用写入(write)操纵,把数据写入到发送缓冲区中。
  • TCP协议发现,这个数据大于MTU(IP协议的数据分片)发送的最大数据(MTU)1500字节),TCP默认(1460)),对数据举行分包发送。
  • 如果发送的数据包过小,就会等待数据填充到差不多的巨细发送出去,大概需要确认应答的时候就发送出去。
  • 接收端接收数据从物理层-数据链路层-网络层,层层拆分到TCP层载入接收缓冲区。
  • 应用层步调就会通过端口,读取缓冲区的数据处理惩罚,同时把需要发送的数据载入到发送缓冲区。


  • 知识回首

  • 如果发送数据凌驾MTU默认长度,会分包发送。
  • 由于发送是基于字节流的,所以不管写入(write)缓冲区多少次都没事,1次也行,100次也行,凌驾某段时间,TCP会携带发送缓冲区的数据应答过去。
  • 同样,写入可以这么写,读也可以怎么读,接收缓冲区的数据都是从TCP接收过来的,固然要注意的事,要处理惩罚掉缓冲区的数,如果不处理惩罚,凌驾某个应答时间200ms,接收端就会发送ack应答。
三.TCP 异常情况


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



  • 根据以上的情况,回到开头的问题。

  • 如果包管数据安全可靠到达接收端。

    • CRC校验和
    • seq序列号(按序到达)
    • ack确认应答
    • 超时重传

  • 如安在带宽拥塞的情况下,还能包管数据的安全发送。

    • 流量控制
    • 拥塞控制

  • 如何制止数据包丢失,让数据实现端到端的传送。

    • seq序列号验证丢包
    • 超时重传
    • 快重传

  • 如何有效使用带宽资源,提高传输效率。

    • 滑动窗口
    • 快规复以及快重传
    • 延迟应答
    • 捎带应答

  • 如何确定毗连康健有效。

    • TIME_WAIT定时器。
    • 检验毗连的保活定时器。

  • 基于TCP的应用层协议

    • HTTP和 HTTPS 通讯协议
    • SMTP
    • Telnet
    • SSH



来源:https://blog.csdn.net/jiaxunnanling/article/details/111244440
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

发布主题

专注素材教程免费分享
全国免费热线电话

18768367769

周一至周日9:00-23:00

反馈建议

27428564@qq.com 在线QQ咨询

扫描二维码关注我们

Powered by Discuz! X3.4© 2001-2013 Comsenz Inc.( 蜀ICP备2021001884号-1 )