zoukankan      html  css  js  c++  java
  • TCP之Nagle算法&&延迟ACK

    转载自:https://www.cnblogs.com/wanpengcoder/p/5366156.html

    1.糊涂窗口综合症
    糊涂窗口综合征:
    当发送端应用进程产生数据很慢、或接收端应用进程处理接收缓冲区数据很慢,或二者兼而有之;
    就会使应用进程间传送的报文段很小,特别是有效载荷很小。 极端情况下,有效载荷可能只有1个字节;
    而传输开销有40字节(20字节的IP头+20字节的TCP头) 这种现象就叫糊涂窗口综合症。
    发送端解决办法:Nagle算法 而他选择的等待时间是一个RTT,即下个ACK来到时
    接受端解决办法:
    解决方法是只要有数据到达就发送确认,但宣布的窗口大小为零,直到或者缓存空间已能放入
    具有最大长度的报文段,或者缓存空间的一半已经空了。


    2. Nagle算法:
    是为了减少广域网的小分组数目,从而减小网络拥塞的出现;
    该算法要求一个tcp连接上最多只能有一个未被确认的未完成的小分组,在该分组ack到达之前不能发送其他的小分组,
    tcp需要收集这些少量的分组,并在ack到来时以一个分组的方式发送出去;其中小分组的定义是小于MSS的任何分组;
    该算法的优越之处在于它是自适应的,确认到达的越快,数据也就发送越快;而在希望减少微小分组数目的低速
    广域网上,则会发送更少的分组;

    3. 延迟ACK:
    如果tcp对每个数据包都发送一个ack确认,那么只是一个单独的数据包为了发送一个ack代价比较高,
    所以tcp会延迟一段时间,如果这段时间内有数据发送到对端,则捎带发送ack,如果在延迟ack定时器触发时候,
    发现ack尚未发送,则立即单独发送;
    延迟ACK好处:
    (1) 避免糊涂窗口综合症;
    (2) 发送数据的时候将ack捎带发送,不必单独发送ack;
    (3) 如果延迟时间内有多个数据段到达,那么允许协议栈发送一个ack确认多个报文段;

    4. 当Nagle遇上延迟ACK:
    试想如下典型操作,写-写-读,即通过多个写小片数据向对端发送单个逻辑的操作,两次写数据长度小于MSS,当
    第一次写数据到达对端后,对端延迟ack,不发送ack,而本端因为要发送的数据长度小于MSS,所以nagle算法起
    作用,数据并不会立即发送,而是等待对端发送的第一次数据确认ack;这样的情况下,需要等待对端超时发送ack,
    然后本段才能发送第二次写的数据,从而造成延迟;

    5. 关闭Nagle算法:

    使用TCP套接字选项TCP_NODELAY可以关闭套接字选项;
    如下场景考虑关闭Nagle算法:
    (1) 对端不向本端发送数据,并且对延时比较敏感的操作;这种操作没法捎带ack;
    (2) 如上写-写-读操作;对于此种情况,优先使用其他方式,而不是关闭Nagle算法:
    --使用writev,而不是两次调用write,单个writev调用会使tcp输出一次而不是两次,只产生一个tcp分节,这是首选方法;
    --把两次写操作的数据复制到单个缓冲区,然后对缓冲区调用一次write;
    --关闭Nagle算法,调用write两次;有损于网络,通常不考虑;

    6. 禁止Nagle和开启Nagle算法发送数据与确认示意图:

  • 相关阅读:
    MYSQL常用命令集合(转载)
    Spring(七)持久层
    Spring(六)AOP切入方式
    面试题目
    11 集合
    10 常用类
    9 异常机制
    8 面向对象之抽象类+接口+内部类
    7 面向对象的三大特征
    6 面向对象之类和对象
  • 原文地址:https://www.cnblogs.com/BGPYC/p/8186380.html
Copyright © 2011-2022 走看看