滑动窗口(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/IP模型

    ### OSI:open system interconnection ### 开放系统互联网模型是由ISO国际标准化组织定义的网络分层模型,共七层 1. 物理层:物理定义了所有电子及物理设备的规范, ...

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

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

  3. 【Linux网络编程】TCP网络编程中connect()、listen()和accept()三者之间的关系

    [Linux网络编程]TCP网络编程中connect().listen()和accept()三者之间的关系 基于 TCP 的网络编程开发分为服务器端和客户端两部分,常见的核心步骤和流程如下: conn ...

  4. 【Linux 网络编程】TCP网络编程中connect()、listen()和accept()三者之间的关系

    基于 TCP 的网络编程开发分为服务器端和客户端两部分,常见的核心步骤和流程如下: connect()函数:对于客户端的 connect() 函数,该函数的功能为客户端主动连接服务器,建立连接是通过三 ...

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

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

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

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

  7. Linux网络编程学习(二) ----- 进程控制(第三章)

    1.进程和程序 程序是一个可执行文件,而一个进程是一个执行中的程序实例.一个进程对应于一个程序的执行,进程是动态的,程序是静态的,多个进程可以并发执行同一个程序.比如几个用户可以同时运行一个编辑程序, ...

  8. Linux 网络编程系列教程

    一.基础理论篇 01.网络协议入门 02.LAN.WAN.WLAN.VLAN 和 VPN 的区别 03.IP 地址介绍 04.广播地址介绍 05.无连接和面向连接协议的区别 06.因特网的IP协议是不 ...

  9. linux网络编程之断点传输文件

    以下载链接"http://www.boa.org/boa-0.94.13.tar.gz"为例: 断点续传实验大概步骤: ===================== 1,使用geth ...

随机推荐

  1. SVN使用总结

    ## 常用命令 建立分支 --- svn copy/cp svn cp http://example.com/repos/myproject/trunk http://example.com/repo ...

  2. 京东2017校园招聘笔试题 【第K个幸运数】

    题目描述 4和7是两个幸运数字,我们定义,十进制表示中,每一位只有4和7两个数的正整数都是幸运数字. 前几个幸运数字为:4,7,44,47,74,77,444,447... 现在输入一个数字K,输出第 ...

  3. Javascript重要知识点梳理

    Javascript重要知识点梳理 一.Javascript流程控制 js中常用的数据类型 var关键字的使用 if – else if – else switch while for 二.Javas ...

  4. node学习笔记(三)

    //事件驱动events //events是node最重要的模块没有之一,因为node.js本身的架构就是事件式的,而他提供了唯一的接口,所以堪称node.js事件编程的基石; //events几乎被 ...

  5. selenium隔离环境安装、以及示例

    1.virtual虚拟环境---分割项目---类似于创建文件夹---复制主环境 2.Python -n venv +目录 注意须在win环境下 3.激活虚拟环境 目录\Scripts\activate ...

  6. Vim自动补全神器–YouCompleteMe

    YouCompleteMe的特别之处 基于语义补全 总所周知,Vim是一款文本编辑器.也就是说,其最基础的工作就是编辑文本,而不管该文本的内容是什么.在Vim被程序员所使用后,其慢慢的被肩负了与IDE ...

  7. linux指令记录

    sudo mount /dev/sda3 data 挂载硬盘到当前目录下的data文件夹

  8. lib/sqlalchemy/cextension/processors.c:10:20: 致命错误: Python.h:没有那个文件或目录

    本文地址:http://www.cnblogs.com/yhLinux/p/4063444.html $ sudo easy_install sqlalchemy [sudo] password fo ...

  9. ArcGIS Js/Flex等前端API(Query(StatisticDefinition)时)针对SDE的SHAPE.AREA/SHAPE.LEN知道查询无效,而对GDB的SHAPE_Area/SHAPE_Length有效探索。

    FIeld 'SHAPE.AREA' and 'SHAPE.LEN' of SDE For Oracle,Field 'SHAPE_Area' and 'SHAPE_Length' of gdb(ge ...

  10. Python排列组合问题

    1.字符串的全排列 问题描述:打印出原字符串中所有字符的所有排列.——将输入字符串中的每个字符作为一个不同的字符看待,即使它们是重复的,如'aaa'应打印6次. Python可以用生成器解决: def ...