zoukankan      html  css  js  c++  java
  • TCP/IP协议

    关于 TCP/IP,必知必会的10个问题

    一、TCP/IP模型

    TCP/IP协议模型(Transmission Control Protocol/Internet Protocol),包含了一系列构成互联网基础的网络协议,是Internet的核心协议。

    基于TCP/IP的参考模型将协议分成四个层次,它们分别是链路层、网络层、传输层和应用层。下图表示TCP/IP模型与OSI模型各层的对照关系。

    TCP/IP协议族按照层次由上到下,层层包装。最上面的是应用层,这里面有http,ftp,等等我们熟悉的协议。而第二层则是传输层,著名的TCP和UDP协议就在这个层次。第三层是网络层,IP协议就在这里,它负责对数据加上IP地址和其他的数据以确定传输的目标。第四层是数据链路层,这个层次为待传送的数据加入一个以太网协议头,并进行CRC编码,为最后的数据传输做准备。

    上图清楚地表示了TCP/IP协议中每个层的作用,而TCP/IP协议通信的过程其实就对应着数据入栈与出栈的过程。入栈的过程,数据发送方每层不断地封装首部与尾部,添加一些传输的信息,确保能传输到目的地。出栈的过程,数据接收方每层不断地拆除首部与尾部,得到最终传输的数据。

    上图以HTTP协议为例,具体说明。

    二、数据链路层

    物理层负责0、1比特流与物理设备电压高低、光的闪灭之间的互换。 数据链路层负责将0、1序列划分为数据帧从一个节点传输到临近的另一个节点,这些节点是通过MAC来唯一标识的(MAC,物理地址,一个主机会有一个MAC地址)。

    • 封装成帧: 把网络层数据报加头和尾,封装成帧,帧头中包括源MAC地址和目的MAC地址。
    • 透明传输:零比特填充、转义字符。
    • 可靠传输: 在出错率很低的链路上很少用,但是无线链路WLAN会保证可靠传输。
    • 差错检测(CRC):接收者检测错误,如果发现差错,丢弃该帧。

    三、网络层

    1. IP协议

    IP协议是TCP/IP协议的核心,所有的TCP,UDP,IMCP,IGMP的数据都以IP数据格式传输。要注意的是,IP不是可靠的协议,这是说,IP协议没有提供一种数据未传达以后的处理机制,这被认为是上层协议:TCP或UDP要做的事情。

    1.1 IP地址

    在数据链路层中我们一般通过MAC地址来识别不同的节点,而在IP层我们也要有一个类似的地址标识,这就是IP地址。

    32位IP地址分为网络位和地址位,这样做可以减少路由器中路由表记录的数目,有了网络地址,就可以限定拥有相同网络地址的终端都在同一个范围内,那么路由表只需要维护一条这个网络地址的方向,就可以找到相应的这些终端了。

    A类IP地址: 0.0.0.0~127.0.0.0
    B类IP地址:128.0.0.1~191.255.0.0
    C类IP地址:192.168.0.0~239.255.255.0

    1.2 IP协议头

    这里只介绍:八位的TTL字段。这个字段规定该数据包在穿过多少个路由之后才会被抛弃。某个IP数据包每穿过一个路由器,该数据包的TTL数值就会减少1,当该数据包的TTL成为零,它就会被自动抛弃。

    这个字段的最大值也就是255,也就是说一个协议包也就在路由器里面穿行255次就会被抛弃了,根据系统的不同,这个数字也不一样,一般是32或者是64。

    2. ARP及RARP协议

    ARP 是根据IP地址获取MAC地址的一种协议。

    ARP(地址解析)协议是一种解析协议,本来主机是完全不知道这个IP对应的是哪个主机的哪个接口,当主机要发送一个IP包的时候,会首先查一下自己的ARP高速缓存(就是一个IP-MAC地址对应表缓存)。

    如果查询的IP-MAC值对不存在,那么主机就向网络发送一个ARP协议广播包,这个广播包里面就有待查询的IP地址,而直接收到这份广播的包的所有主机都会查询自己的IP地址,如果收到广播包的某一个主机发现自己符合条件,那么就准备好一个包含自己的MAC地址的ARP包传送给发送ARP广播的主机。

    而广播主机拿到ARP包后会更新自己的ARP缓存(就是存放IP-MAC对应表的地方)。发送广播的主机就会用新的ARP缓存数据准备好数据链路层的的数据包发送工作。

    RARP协议的工作与此相反,不做赘述。

    3. ICMP协议

    IP协议并不是一个可靠的协议,它不保证数据被送达,那么,自然的,保证数据送达的工作应该由其他的模块来完成。其中一个重要的模块就是ICMP(网络控制报文)协议。ICMP不是高层协议,而是IP层的协议。

    当传送IP数据包发生错误。比如主机不可达,路由不可达等等,ICMP协议将会把错误信息封包,然后传送回给主机。给主机一个处理错误的机会,这 也就是为什么说建立在IP层以上的协议是可能做到安全的原因。

    四、ping

    ping可以说是ICMP的最著名的应用,是TCP/IP协议的一部分。利用“ping”命令可以检查网络是否连通,可以很好地帮助我们分析和判定网络故障。

    例如:当我们某一个网站上不去的时候。通常会ping一下这个网站。ping会回显出一些有用的信息。一般的信息如下:

    ping这个单词源自声纳定位,而这个程序的作用也确实如此,它利用ICMP协议包来侦测另一个主机是否可达。原理是用类型码为0的ICMP发请 求,受到请求的主机则用类型码为8的ICMP回应。

    ping程序来计算间隔时间,并计算有多少个包被送达。用户就可以判断网络大致的情况。我们可以看到, ping给出来了传送的时间和TTL的数据。

    五、Traceroute

    Traceroute是用来侦测主机到目的主机之间所经路由情况的重要工具,也是最便利的工具。

    Traceroute的原理是非常非常的有意思,它收到到目的主机的IP后,首先给目的主机发送一个TTL=1的UDP数据包,而经过的第一个路由器收到这个数据包以后,就自动把TTL减1,而TTL变为0以后,路由器就把这个包给抛弃了,并同时产生 一个主机不可达的ICMP数据报给主机。主机收到这个数据报以后再发一个TTL=2的UDP数据报给目的主机,然后刺激第二个路由器给主机发ICMP数据 报。如此往复直到到达目的主机。这样,traceroute就拿到了所有的路由器IP。

    六、TCP/UDP

    TCP/UDP都是是传输层协议,但是两者具有不同的特性,同时也具有不同的应用场景,下面以图表的形式对比分析。

    面向报文

    面向报文的传输方式是应用层交给UDP多长的报文,UDP就照样发送,即一次发送一个报文。因此,应用程序必须选择合适大小的报文。若报文太长,则IP层需要分片,降低效率。若太短,会是IP太小。

    面向字节流

    面向字节流的话,虽然应用程序和TCP的交互是一次一个数据块(大小不等),但TCP把应用程序看成是一连串的无结构的字节流。TCP有一个缓冲,当应用程序传送的数据块太长,TCP就可以把它划分短一些再传送。

    关于拥塞控制,流量控制,是TCP的重点,后面讲解。

    TCP和UDP协议的一些应用

    什么时候应该使用TCP?

    当对网络通讯质量有要求的时候,比如:整个数据要准确无误的传递给对方,这往往用于一些要求可靠的应用,比如HTTP、HTTPS、FTP等传输文件的协议,POP、SMTP等邮件传输的协议。

    什么时候应该使用UDP?

    当对网络通讯质量要求不高的时候,要求网络通讯速度能尽量的快,这时就可以使用UDP。

    七、DNS

    DNS(Domain Name System,域名系统),因特网上作为域名和IP地址相互映射的一个分布式数据库,能够使用户更方便的访问互联网,而不用去记住能够被机器直接读取的IP数串。通过主机名,最终得到该主机名对应的IP地址的过程叫做域名解析(或主机名解析)。DNS协议运行在UDP协议之上,使用端口号53。

    八、TCP连接的建立与终止

    1. 三次握手

    TCP是面向连接的,无论哪一方向另一方发送数据之前,都必须先在双方之间建立一条连接。在TCP/IP协议中,TCP协议提供可靠的连接服务,连接是通过三次握手进行初始化的。三次握手的目的是同步连接双方的序列号和确认号并交换 TCP窗口大小信息。

    第一次握手: 建立连接。客户端发送连接请求报文段,将SYN位置为1,Sequence Number为x;然后,客户端进入SYN_SEND状态,等待服务器的确认;

    第二次握手: 服务器收到SYN报文段。服务器收到客户端的SYN报文段,需要对这个SYN报文段进行确认,设置Acknowledgment Number为x+1(Sequence Number+1);同时,自己自己还要发送SYN请求信息,将SYN位置为1,Sequence Number为y;服务器端将上述所有信息放到一个报文段(即SYN+ACK报文段)中,一并发送给客户端,此时服务器进入SYN_RECV状态;

    第三次握手: 客户端收到服务器的SYN+ACK报文段。然后将Acknowledgment Number设置为y+1,向服务器发送ACK报文段,这个报文段发送完毕以后,客户端和服务器端都进入ESTABLISHED状态,完成TCP三次握手。

    为什么要三次握手?

    为了防止已失效的连接请求报文段突然又传送到了服务端,因而产生错误。

    具体例子:“已失效的连接请求报文段”的产生在这样一种情况下:client发出的第一个连接请求报文段并没有丢失,而是在某个网络结点长时间的滞留了,以致延误到连接释放以后的某个时间才到达server。本来这是一个早已失效的报文段。但server收到此失效的连接请求报文段后,就误认为是client再次发出的一个新的连接请求。于是就向client发出确认报文段,同意建立连接。假设不采用“三次握手”,那么只要server发出确认,新的连接就建立了。由于现在client并没有发出建立连接的请求,因此不会理睬server的确认,也不会向server发送数据。但server却以为新的运输连接已经建立,并一直等待client发来数据。这样,server的很多资源就白白浪费掉了。采用“三次握手”的办法可以防止上述现象发生。例如刚才那种情况,client不会向server的确认发出确认。server由于收不到确认,就知道client并没有要求建立连接。”

    2. 四次挥手

    当客户端和服务器通过三次握手建立了TCP连接以后,当数据传送完毕,肯定是要断开TCP连接的啊。那对于TCP的断开连接,这里就有了神秘的“四次分手”。

    第一次分手: 主机1(可以使客户端,也可以是服务器端),设置Sequence Number,向主机2发送一个FIN报文段;此时,主机1进入FIN_WAIT_1状态;这表示主机1没有数据要发送给主机2了;

    第二次分手: 主机2收到了主机1发送的FIN报文段,向主机1回一个ACK报文段,Acknowledgment Number为Sequence Number加1;主机1进入FIN_WAIT_2状态;主机2告诉主机1,我“同意”你的关闭请求;

    第三次分手: 主机2向主机1发送FIN报文段,请求关闭连接,同时主机2进入LAST_ACK状态;

    第四次分手: 主机1收到主机2发送的FIN报文段,向主机2发送ACK报文段,然后主机1进入TIME_WAIT状态;主机2收到主机1的ACK报文段以后,就关闭连接;此时,主机1等待2MSL后依然没有收到回复,则证明Server端已正常关闭,那好,主机1也可以关闭连接了。

    为什么要四次分手?

    TCP协议是一种面向连接的、可靠的、基于字节流的运输层通信协议。TCP是全双工模式,这就意味着,当主机1发出FIN报文段时,只是表示主机1已经没有数据要发送了,主机1告诉主机2,它的数据已经全部发送完毕了;但是,这个时候主机1还是可以接受来自主机2的数据;当主机2返回ACK报文段时,表示它已经知道主机1没有数据发送了,但是主机2还是可以发送数据到主机1的;当主机2也发送了FIN报文段时,这个时候就表示主机2也没有数据要发送了,就会告诉主机1,我也没有数据要发送了,之后彼此就会愉快的中断这次TCP连接。

    为什么要等待2MSL?

    MSL:报文段最大生存时间,它是任何报文段被丢弃前在网络内的最长时间。

    原因有二:

    • 保证TCP协议的全双工连接能够可靠关闭
    • 保证这次连接的重复数据段从网络中消失

    第一点:如果主机1直接CLOSED了,那么由于IP协议的不可靠性或者是其它网络原因,导致主机2没有收到主机1最后回复的ACK。那么主机2就会在超时之后继续发送FIN,此时由于主机1已经CLOSED了,就找不到与重发的FIN对应的连接。所以,主机1不是直接进入CLOSED,而是要保持TIME_WAIT,当再次收到FIN的时候,能够保证对方收到ACK,最后正确的关闭连接。

    第二点:如果主机1直接CLOSED,然后又再向主机2发起一个新连接,我们不能保证这个新连接与刚关闭的连接的端口号是不同的。也就是说有可能新连接和老连接的端口号是相同的。一般来说不会发生什么问题,但是还是有特殊情况出现:假设新连接和已经关闭的老连接端口号是一样的,如果前一次连接的某些数据仍然滞留在网络中,这些延迟数据在建立新连接之后才到达主机2,由于新连接和老连接的端口号是一样的,TCP协议就认为那个延迟的数据是属于新连接的,这样就和真正的新连接的数据包发生混淆了。所以TCP连接还要在TIME_WAIT状态等待2倍MSL,这样可以保证本次连接的所有数据都从网络中消失。

    TCP 协议基础知识点

    • TCP 协议定义
    • TCP 首部格式
    • TCP 握手过程
    • TCP 可靠传输原理
    • TCP 流量控制
    • TCP 拥塞控制
    更多文章,欢迎 Star 和 订阅我的博客

    TCP 协议定义

    TCP(Transmission Control Protocol 传输控制协议)是一种面向连接的、可靠的、基于字节流的传输层通信协议,由 IETF 的 RFC 793 定义。在简化的计算机网络 OSI 模型中,它完成第四层传输层所指定的功能。

    TCP 协议的特点是:

    • 面向连接。
    • 点对点(一对一)。
    • 可靠交付。
    • 面向字节流,也就是说仅仅把上层协议传递过来的数据当成字节传输。

    为了实现 TCP 上述的特点,TCP 协议主要从面向连接(建立连接和关闭连接的方式)、可靠传输(错误确认和重传)、流量控制(发送方和接收方的传输速率协调)、拥塞控制四个方面去优化。

    TCP 首部格式

    TCP 协议首部最小长度是 20 字节,首部有一个长度可变的选项部分,最大 40 字节,所以 TCP 首部长度是 20-60 字节大小。具体如图:

     

     

    字段解释如下:

    • 序号:TCP 传输的时候每一个字节都按顺序编号;协议中的序号是本报文段所发送数据第一个字节的序号。序号也用于建立和结束连接时候使用。
    • 确认号:用于可靠传输中,返回确认报文序号。
    • 数据偏移:指出数据段在报文中开始的位置。
    • 窗口:可靠连接和流量控制中所用到的窗口大小。

    上图中有六个控制位,对于建立和结束连接非常关键:

    • URG(Urgent):紧急字段,可以让该报文不按报文顺序优先被处理。比如用户突然终止传输关闭连接。
    • ACK(Acknowledge):所有建立连接后传送的报文 ACK 必须为 1.
    • PSH(Push):发送方将该报文推送向前,可以不用等缓存填满先提交给应用程序。
    • RST(Reset):连接出现严重差错时候设为 1,重新建立连接。也可用于拒绝建立连接。
    • SYN(Synchronize):建立连接时候的同步标志。SYN=1 而 ACK=0 时表示建立连接请求。
    • FIN(Finish):终止连接时的标志位。

    另外,在选项中有这么几种选择:

    • 最大报文长度 MSS(Maxium Segment Size),指的是一个 TCP 报文数据段的最大长度。要尽可能大一些但是又不需要 IP 拆分。推荐是 536 字节,这样整个 TCP 报文长度是 536 + 20 = 556 字节。
    • 窗口扩大选项。可用于控制传输窗口大小。
    • 时间戳。可用于计算往返时间 RTT 、区分重复报文。因为报文的序号只能是 2^32-1 个,所以很容易就重复了,加上时间戳可以进行区分。

    TCP 握手过程

    每一次 TCP 连接的建立和断开都需要经过通过客户端和服务器端的协商,这个协商的过程我们称之为握手。

    • 三次握手
    • 四次挥手

    三次握手

    TCP 在建立连接时,需要进行 3 次确认,俗称三次握手。

     

     

    第一次握手

    客户端向服务端发送连接请求报文段。该报文段中包含自身的数据通讯初始序号 seq=x。请求发送后,客户端便进入 SYN-SENT 状态。

    第二次握手

    服务端收到连接请求报文段后,如果同意连接,则会发送一个应答,该应答中也会包含自身的数据通讯初始序号 ack=x+1,发送完成后便进入 SYN-RECEIVED 状态。

    第三次握手

    当客户端收到连接同意的应答后,还要向服务端发送一个确认报文。客户端发完这个报文段后便进入 ESTABLISHED 状态,服务端收到这个应答后也进入 ESTABLISHED 状态,此时连接建立成功。

    :::tip TCP 快速打开 TFO TCP 快速打开(Fast Open,简称 TFO)是对计算机网络中传输控制协议(TCP)连接的一种简化握手手续的拓展,用于提高两端点间连接的打开速度。

    它通过握手开始时的 SYN 包中的 TFO cookie(一个 TCP 选项)来验证一个之前连接过的客户端。如果验证成功,它可以在第三次握手最终的 ACK 包收到之前就开始发送数据,这样便跳过了一个绕路的行为,更在传输开始时就降低了延迟。这个加密的 Cookie 被存储在客户端,在一开始的连接时被设定好。然后每当客户端连接时,这个 Cookie 被重复返回。

    简单来说,就是通过快速打开(TFO)技术在服务器端第二次握手时校验 cookie 有效性,如果有效,则不用等到第三次握手后才传递数据,可以立即发送数据。 :::

    为什么 TCP 建立连接需要三次握手,明明两次就可以建立起连接?

    这是为了防止出现失效的连接请求报文被服务端接收的情况。

    可以想象如下场景。客户端发送了一个连接请求 A,但是因为网络原因造成了超时,这时 TCP 会启动超时重传的机制再次发送一个连接请求 B。此时请求顺利到达服务端,服务端应答完就建立了请求,然后接收数据后释放了连接。

    如果这时候连接请求 A 在两端关闭后终于抵达了服务端,那么此时服务端会认为客户端又需要建立 TCP 连接,从而应答了该请求并进入 ESTABLISHED 状态。但是客户端其实是 CLOSED 的状态,那么就会导致服务端一直等待,造成资源的浪费。

    :::tip SYN Flood 攻击

    在建立连接中,任意一端掉线,TCP 都会重发 SYN 包,一般会重试五次,假设一个用户向服务器发送了 SYN 报文后突然死机或掉线,那么服务器在发出 SYN+ACK 应答报文后是无法收到客户端的 ACK 报文的(第三次握手无法完成)。

    这种情况下服务器端会重试(再次发送 SYN+ACK 给客户端)并等待一段时间,如果等待超时,就会丢弃这个未完成的连接,这段时间的长度我们称为 SYN Timeout,一般来说这个时间是分钟的数量级(大约为 30 秒-2 分钟)。

    恶意攻击者可以利用 SYN Timeout 大量模拟这种情况,服务器端将为了维护一个非常大的半连接列表而消耗非常多的资源(数以万计的半连接),即使是简单的保存并遍历也会消耗非常多的 CPU 时间和内存。最后的结果往往是服务器堆栈溢出崩溃。

    遇到这种情况你可以选择调低重试次数或者干脆在不能处理的情况下拒绝请求。

    :::

    四次挥手

    TCP 在断开连接时,需要进行 4 次确认,俗称四次挥手。

     

     

    第一次挥手

    客户端 A 认为数据发送完成,它需要向服务端 B 发送连接释放请求。

    第二次挥手

    B 收到连接释放请求后,会告诉应用层要释放 TCP 链接。然后会发送 ACK 包,并进入 CLOSE_WAIT 状态,此时表明 A 到 B 的连接已经释放,不再接收 A 发的数据了。但是因为 TCP 连接是双向的,所以 B 仍旧可以发送数据给 A。

    第三次挥手

    B 如果此时还有没发完的数据会继续发送,完毕后会向 A 发送连接释放请求,然后 B 便进入 LAST-ACK 状态。

    :::tip 通过延迟确认的技术(通常有时间限制,否则对方会误认为需要重传),可以将第二次和第三次握手合并,延迟 ACK 包的发送。 :::

    第四次挥手

    A 收到释放请求后,向 B 发送确认应答,此时 A 进入 TIME-WAIT 状态。该状态会持续 2MSL(最大段生存期,指报文段在网络中生存的时间,超时会被抛弃)时间,若该时间段内没有 B 的重发请求的话,就进入 CLOSED 状态。当 B 收到确认应答后,也便进入 CLOSED 状态。

    :::warning 为什么 A 要进入 TIME-WAIT 状态,等待 2MSL 时间后才进入 CLOSED 状态? 答:为了保证 B 能收到 A 的确认应答。若 A 发完确认应答后直接进入 CLOSED 状态,如果确认应答因为网络问题一直没有到达,那么会造成 B 不能正常关闭。 :::

    TCP 可靠传输原理

    TCP 底层使用 超时重传机制(ARQ) 来保证传输的可靠性,ARQ 协议包含 停止等待 ARQ 和 连续 ARQ 两种协议。

    停止等待 ARQ

    停止等待 ARQ 指的是客户端每发送一个报文,就需要等待服务器端确认,只有收到确认后,才会继续发送下一个报文。

    例如:A 向 B 发送一段报文的同时,会在 A 端启动一个定时器,等待 B 端回应,在定时器时间内接收到 B 端应答就取消定时器,并发送下一段报文。

    :::tip 一般定时器设定的时间都会大于一个 RTT(发送端发送数据到接收到对端数据所需的往返时间) 的平均时间。 :::

    什么时候会出现重传?

    • 丢包
    • 如果在报文传输的过程中出现了丢包。这时候超过定时器设定的时间就会再次发送丢失的数据直到对端响应,所以需要每次都备份发送的数据。
    • 报文出错
    • 即使报文正常的传输到对端,也可能出现在传输过程中报文出错的问题。这时候对端会抛弃该报文并等待 A 端重传。
    • 定时器超时
    • 对端传输的应答也可能出现丢失或超时的情况。那么超过定时器时间 A 端照样会重传报文。这时候 B 端收到相同序号的报文会丢弃该报文并重传应答,直到 A 端发送下一个序号的报文。

    :::tip 在超时的情况下也可能出现应答很迟到达,这时 A 端会判断该序号是否已经接收过,如果接收过只需要丢弃应答即可。 :::

    从上面的描述中大家肯定可以发现这肯定不是一个高效的方式。假设在良好的网络环境中,每次发送数据都需要等待片刻肯定是不能接受的。接下来我们来继续学习更高效的可靠传输方式。

    连续 ARQ

    在连续 ARQ 中,发送端拥有一个发送窗口,可以在没有收到应答的情况下持续发送窗口内的数据,相比停止等待 ARQ 协议来说减少了等待时间,提高了效率。

     

     

    累计确认

    连续 ARQ 中,接收端会持续不断收到报文。通过累计确认,可以在收到多个报文以后统一回复一个应答报文。报文中的 ACK 标志位可以用来告诉发送端这个序号之前的数据已经全部接收到了,下次请发送这个序号后的数据。

    但累计确认也有一个弊端。在连续接收报文时,可能会遇到接收到序号 5 的报文后,并未接收到序号 6 的报文,然而序号 7 以后的报文已经接收。遇到这种情况时,ACK 只能回复 6,这样就会重发 6 之后的(包括 7)报文,就造成重复发送数据的问题。

    TCP 流量控制

    TCP 流量控制 简单来说就是要控制 TCP 发送速率,不能发送得太快,以免数据来不及处理,也不能发送得太慢,以免浪费资源。

    在 TCP 中,发送端和接收端其实都维护着对应的窗口:分别为发送端窗口和接收端窗口。

    发送端窗口包含:已发送但未收到应答的数据、可以发送但是未发送的数据。

    发送端窗口是由接收窗口剩余大小决定的。接收方会把当前接收窗口的剩余大小写入应答报文,发送端收到应答后根据该值和当前网络拥塞情况设置发送窗口的大小,所以发送窗口的大小是不断变化的,这个不断变化的窗口就叫做滑动窗口。

    滑动窗口是一个很重要的概念,它帮助 TCP 实现了流量控制的功能。接收方通过报文告知发送方还可以发送多少数据,从而保证接收方能够来得及接收数据,防止出现接收方带宽已满,但是发送方还一直发送数据的情况。

    Zero 窗口

    在发送报文的过程中,可能会接收到零窗口大小的情况。在该情况下,发送端会停止发送数据,并启动 persistent timer 定时器。该定时器会定时发送请求给对端,让接收端告知窗口大小。在重试次数超过一定次数后,可能会中断 TCP 连接。

    TCP 拥塞控制

    拥塞控制作用于网络,目的是防止过多的数据拥塞网络,避免出现网络负载过大,带宽被大量占用的情况。

    常见的 TCP 拥塞控制方法包括四种:

    • 慢开始
    • 拥塞避免
    • 快速重传
    • 快速恢复

    慢开始

    慢开始算法,顾名思义,就是在传输开始时将发送窗口慢慢的指数级扩大,从而避免一开始就传输大量数据导致网络拥塞。想必大家都下载过资源,每当我们开始下载的时候都会发现下载速度是慢慢提升的,而不是一蹴而就直接拉满带宽。

    慢开始算法步骤具体如下:

    • 连接初始设置拥塞窗口(Congestion Window) 为 1 MSS(一个分段的最大数据量)。
    • 每过一个 RTT 就将窗口大小乘二。
    • 指数级增长肯定不能没有限制的,所以有一个阈值限制,当窗口大小大于阈值时就会启动拥塞避免算法。

    拥塞避免

    拥塞避免算法相比简单点,每过一个 RTT 窗口大小只加一(线性增长),这样能够避免指数级增长导致网络拥塞,慢慢将大小调整到最佳值。

    在传输过程中可能出现定时器超时的情况,这时候 TCP 会认为网络拥塞了,会马上进行以下步骤:

    • 将阈值设为当前拥塞窗口的一半。
    • 将拥塞窗口设为 1 MSS。
    • 启动拥塞避免算法。

    快速重传

    快速重传一般和快恢复一起出现。一旦接收端收到的报文出现失序的情况,接收端只会回复最后一个顺序正确的报文序号。如果发送端收到三个重复的 ACK,无需等待定时器超时而是直接启动快速重传算法。具体算法分为两种:

    • TCP Taho 算法
    • TCP Reno 算法

     

     

    TCP Taho 实现

    • 将阈值设为当前拥塞窗口的一半。
    • 将拥塞窗口设为 1 MSS。
    • 重新开始慢开始算法。

    TCP Reno 实现

    • 拥塞窗口减半。
    • 将阈值设为当前拥塞窗口。
    • 进入快恢复阶段(重发对端需要的包,一旦收到一个新的 ACK 答复就退出该阶段),这种方式在丢失多个包的情况下就不那么好了。
    • 使用拥塞避免算法。

    TCP New Ren 改进后的快恢复

     

     

    TCP New Reno 算法改进了之前 TCP Reno 算法的缺陷。在之前,快恢复中只要收到一个新的 ACK 包,就会退出快恢复。

    在 TCP New Reno 中,TCP 发送方先记下三个重复 ACK 的分段的最大序号。

    假如我有一个分段数据是 1 ~ 10 这十个序号的报文,其中丢失了序号为 3 和 7 的报文,那么该分段的最大序号就是 10。发送端只会收到 ACK 序号为 3 的应答。这时候重发序号为 3 的报文,接收方顺利接收的话就会发送 ACK 序号为 7 的应答。这时候 TCP 知道对端是有多个包未收到,会继续发送序号为 7 的报文,接收方顺利接收并会发送 ACK 序号为 11 的应答,这时发送端认为这个分段接收端已经顺利接收,接下来会退出快恢复阶段。

    总结

    这一章节几乎全理论知识,需要反复理解记忆。

    • 建立连接需要三次握手,断开连接需要四次挥手。
    • 超时重传机制保证每一次传输的数据都是可靠的。
    • 滑动窗口动态调整发送端窗口大小,保证接收方来得及接收数据。
    • 拥塞窗口动态调整发送端窗口大小,防止过多的数据拥塞网络,出现网络带宽不够用的情况。

     

  • 相关阅读:
    C#中virtual 方法和abstract方法的区别
    解决zabbix的cannot allocate shared memory of size错误
    批量改名的shell脚本
    /bin/bash和/bin/sh的区别
    搭建redmine全攻略——与apache整合(CentOS 5.8 64位)
    内网监控利器——Nagios
    Maven
    TypeScript
    ShardingSphere
    Spring框架源码分析
  • 原文地址:https://www.cnblogs.com/leijiangtao/p/11905346.html
Copyright © 2011-2022 走看看