滑动窗口(sliding window)

滑动窗口是用于流量控制的,发送端根据接收端的处理能力发送数据,不至于造成过多的丢包。 是发送方和接收方间的协调,对方的接收窗口大小就是自己的发送窗口大小。
在TCP头中有一个字段window,这个字段就是接收端告诉发送端自己还有多少缓冲区可以接收数据。发送端根据这个字段的值来发送数据,当值为0时就停止发送。
发送端和接收端各自维护着一个窗口,发送的滑动窗口控制可以发送的数据大小,接收端的窗口控制可以接收数据的大小。

发送端:LastByteAcked指向已经被成功接收的位置,LastByteSent指向最后已发送出去的位置,usable window表示发送端还可以发送的数据大小。如上图,发送端还有5个单位数据还未被ack,还可以再发送7个单位的数据。


接收端:LastByteExpected指向接收端收到的连续包的最后一个位置,LastByteRcvd指向收到的包的最后一个位置,waited come表示期望收到的包序列,waited read表示在缓冲区中还未读走的数据,usable window表示缓冲区还能接受的大小。如上图,缓冲区还能接受7个单位的数据,就会把7赋值给tcp头中的window字段。

发送端当收到window为0时,就停止发送数据,会陆续发送3次ZWP(zero window probe)询问接收端是否有可用窗口,接收端会回复可用窗口,如果3次都为0,发送端可能中断链接。

拥塞控制

滑动窗口用于流量控制,避免发送超过接收端处理能力的数据,导致数据丢失,是两端之间的协调。
拥塞控制是TCP用于发送端和网络情况间的协调,和慢启动一起避免恶化网络状况。根据网络延时情况,确定可发送窗口大小。这就抽象出一个拥塞窗口(congestion window)的概念,其最大值是发送窗口大小。
TCP有四个算法来动态调节拥塞窗口(cwnd)大小:

  • 慢启动
    连接建立时,cwnd=1
    cwnd线性上升,每收到一个ACK,cwnd++
    cwnd指数上升,每过一个RTT(round trip time),cwnd = cwnd * 2

  • 拥塞避免
    当cwnd>=ssthresh(slow start threshold),进入拥塞避免,cwnd的增加算法改成如下:
    每收到一个ack,cwnd=cwnd + 1/cwnd,基本不增加
    每过一个RTT,cwnd=cwnd + 1,在一个往返时间内最多为 cwnd增加 1 个报文段

  • 拥塞发生(超时RTO,丢包-重复收到同一个包的ACK)
    ssthresh = cwnd/2
    cwnd = 1,发送端基本不发送数据了。开始了慢启动的过程。

  • 快速恢复
    TCP为保证数据达到有两种重传算法,超时重传和快速重传。超时重传是等待RTT时间没收到ack,则重传;快速重传是接收端配合,接收端每收到一个tcp segment,返回的都是收到的连续序列的下一个序号,发送端收到3次同样的序号就进行重传。
    快速恢复通常和快速重传一起使用,如果接收端还能收到重复的ACK,说明收发两端还有数据流动。所以没必要反映那么强烈,不需要把cwnd降为1,可以缓和点减少流量,不进入慢启动。这是快速恢复的思想。
    1) 当收到第 3 个重复的 ACK时(认为拥塞发生),将 ssthresh设置为当前拥塞窗口 cwnd的一半。重传丢失的报文段。设置cwnd为ssthresh加上3倍的报文段大小。
    2) 每次收到另一个重复的 ACK时, cwnd增加 1个报文段大小并发送 1 个分组(如果新的cwnd允许发送)。
    3) 当下一个确认新数据的ACK到达时,设置 cwnd为ssthresh(在第1步中设置的值)。这个ACK应该是在进行重传后的一个往返时间内对步骤 1 中重传的确认。另外,这个ACK也应该是对丢失的分组和收到的第 1 个重复的 ACK之间的所有中间报文段的确认。这一步采用的是拥塞避免,因为当分组丢失时我们将当前的速率减半。
    总结下,收到重复的ack时,窗口和阈值减半,进入拥塞避免,试探性的重发丢失的报文段,直到无窗口可用或者拥塞消除。

注:网络实际传输受slidingwnd和cwnd控制,TCP能传输的最大数据 = MIN(slidingwnd, cwnd)
参考TCP的那些事儿(下)http://coolshell.cn/articles/11609.html

Linux网络编程系列-TCP传输控制的更多相关文章

  1. Linux网络编程系列-TCP编程实例

    实例: client #include <stdio.h> #include <sys/socket.h> #include <netinet/in.h> #inc ...

  2. Linux网络编程系列-套接口选项控制

    获取和设置套接口选项的方法有: getsockopt/setsockopt fcntl ioctl getsockopt/setsockopt 这两个函数仅用于套接口(socket)的设置,另外两个函 ...

  3. linux网络编程笔记——TCP

    1.TCP和UDP TCP是长连接像持续的打电话,UDP是短消息更像是发短信.TCP需要消耗相对较多的资源,但是传输质量有保障,UDP本身是不会考虑传输质量的问题. 2.网络传输内容 我习惯的做法是直 ...

  4. Linux网络编程系列-常见疑惑

    1.并发TCP最大连接数 一个TCP连接有一个四元组唯一标识{local_ip, local_port, remote_ip, remote_port} client端建立连接请求时,通常让系统分配一 ...

  5. linux网络编程系列-网络连接的建立

    一个比较实用的连接函数,支持host为域名. #include <netdb.h> #include <sys/socket.h> #include <sys/types ...

  6. Linux 网络编程(TCP)

    客户端代码 #include<stdio.h> #include<stdlib.h> #include<string.h> #include<sys/sock ...

  7. Linux网络编程入门 (转载)

    (一)Linux网络编程--网络知识介绍 Linux网络编程--网络知识介绍客户端和服务端         网络程序和普通的程序有一个最大的区别是网络程序是由两个部分组成的--客户端和服务器端. 客户 ...

  8. [转] - Linux网络编程 -- 网络知识介绍

    (一)Linux网络编程--网络知识介绍 Linux网络编程--网络知识介绍客户端和服务端         网络程序和普通的程序有一个最大的区别是网络程序是由两个部分组成的--客户端和服务器端. 客户 ...

  9. 【转】Linux网络编程入门

    (一)Linux网络编程--网络知识介绍 Linux网络编程--网络知识介绍客户端和服务端         网络程序和普通的程序有一个最大的区别是网络程序是由两个部分组成的--客户端和服务器端. 客户 ...

随机推荐

  1. 使用NSAssert()和NSParameterAssert调试程序

    NSAssert: NSAssert()只是一个宏,用于开发阶段调试程序中的Bug,通过为NSAssert()传递条件表达式来断定是否属于Bug,满足条件返回真值,程序继续运行,如果返回假值,则抛出异 ...

  2. android性能优化练习:过度绘制

    练习:https://github.com/zhangbz/AndroidUIPorblems 查看过度绘制 在开发者选项中开启"调试GPU过度绘制" 判断标准 无色:没有过度绘制 ...

  3. Tomcat重启脚本restart.sh停止脚本stop.sh

    Tomcat重启脚本restart.sh停止脚本stop.sh Tomcat本身提供了 startup.sh(启动)shutdown.sh(关闭)脚本,我们在部署中经常会出现死进程形象,无法杀掉进程需 ...

  4. linux命令:gzip

    1.命令介绍: gzip用来压缩或解压文件,对文本文件的压缩率有60~70%. 2.命令格式: gzip [选项] 文件/目录 3.命令参数: -a或--ascii  使用ASCII文字模式. -c或 ...

  5. .clear 万能清除浮动

    html body div.clear, html body span.clear { background: none; border: 0; clear: both; display: block ...

  6. bzoj 3118: Orz the MST(单纯形)

    题目链接:http://www.lydsy.com:808/JudgeOnline/problem.php?id=3118 题意:给出一个图以及图中指定的n-1条边组成的生成树.每条边权值加1或者减去 ...

  7. SSIS 学习(5):容器【转】

    容器是Integration Services 包中非常重要的一部分功能,它可以对控制流中的任务进行直观的划分与组织,使包的结构简明扼要.易于管理.易于维护. 在Integration Service ...

  8. 【SSSP】A forward-backward single-source paths algorithm

    0. 引子基础的算法和数据结构已经学习的差不多了,上学期期末就打算重点研究研究STOC和FOCS上面的论文.做这件事情的初衷是了解别人是如何改进原有算法的,搞清楚目前比较热的算法问题有哪些,更重要的是 ...

  9. C++ STL之pair常用指令

    只记载本人在ACM中常用的函数. pair<first, second>,将两个数据组合成一个数据.在其他stl(如map),函数需要传回两个值时可能会用到. 1.初始化 #include ...

  10. effective C++: 5实现

    五.实现 大多数情况下,适当提出拟的类定义以及函数声明,是花费最多心力的两件事.尽管如此,还是有很多东西需要小心:太快定义变量可能造成效率上的拖延:过度使用转型(casts)可能导致代码变慢又难维护, ...