前面一节咱们介绍完了TCP协议,这部分,将要介绍,TCP是如何实现可靠传输的。

TCP的可靠传输

1.滑动窗口

上一节我们介绍TCP报文段头部的时候说得到,"窗口"这个部分,"窗口"的内容就是发送/接收的数据的字节总量(窗口是以字节为单位)。

发送方A有发送窗口,接收方B有接收窗口。头部的"窗口"要配合"确认号"才能确定,要发送哪些数据和具体接收哪些数据。

现假定A收到了B发来的确认报文段中,其中窗口是20(字节),而确认号是31(这表明B期望收到的下一个序号是31,而序号31之前的数据已经收到了),A就构造出自己的发送窗口,如下图:

我们现在来讨论一下A的发送窗口:

在没有收到B确认的情况下,A可以连续把窗口内的数据都发送出去。凡是发送过的数据,会暂时保留一份副本,以便超时重传时使用。

发送窗口的位置由窗口前沿和窗口后沿的位置共同决定。

后沿: 上图中后沿的后面部分(左边)表示已经发送并且收到了确认。这些数据不在保留副本。

后沿变化的情况有两种:不动(没有收到新的确认号(>31))和前移(收到了新的确认号)。后沿是不会向后移动的,因为不能撤销掉已收到的确认。

前沿: 上图中前沿的前面部分(右边)表示不允许发送的数据。

前沿变化情况有三种:

向前移动: 收到新的确认后(>31)的通常情况

不动: 没有收到确认;收到了新的确认号(35),但窗口值变小了变成了15,那前沿的位置还是在50那。

收缩:窗口值变得更小。如上面新的确认号是35,但窗口值变成了10,那前沿的位置就到了45的位置。不过TCP的标准强烈不赞成这样做。

后沿前沿的移动,正好就把窗口滑动的特点展示出来了。

下面我们再通过举例子,再详细介绍滑动窗口的特点

假定A发送了窗口中序号为31~41的数据(黑色小方框表示),表示已发送但未收到确认。而42~50号的数据是允许发送但尚未发送的。如下图。

上图中,要描述发送窗口的状态需要三个指针:P1,P2,P3。而小于P1的是已经发到并且收到确认的部分,大于P3是不允许发送的部分。

P3 - P1 = A的发送窗口(通知窗口)

P2 - P1 = 已发送但尚未收到确认的字节数。

P3 - P2 = 允许发送但尚未发送的字节数(可用窗口或有效窗口)

再说一下B的接收窗口。先看下图。

B接收窗口内的序号(31~50)是允许接收的。在上图中,32,33的被接收到了,而31的数据没有收到(也许丢失,也许滞留在网络中)。而B只能将按顺序收到的数据中,将最高号作为确认号发出。由于31号还没有收到,所以B发送的确认报文仍然是31,而不是32或33。

现在假设B收到了31号数据,并把31~33的数据交给应用程序,然后B会删除这些数据。接着把接收窗口向前移动3个序号,同时给A发送确认号34,窗口只20。

此时A、B窗口移动后的图如下:

A收到了收到了B发送的34号确认号,20的窗口值,所以P1移至34,P3移至53。但P2指针没有动。

而我们可以看到B还接收到了37、38、40。但这些数据没有按序到达,所以只能先暂存在接收窗口中。

然后,A再继续发送完序号42~53的数据后,指针P2向前移动和P3重合。如下图:

窗口内的序号已经用完。但还没有收到B的确认。如果过了一段时间A还没有收到确认,就只能超时重传这部分数据,直到B收到确认位置。

如果A收到确认号落在发送窗口内,那么A可以使窗口向前滑动,发送新的数据。

2. 发送/接收缓存

发送方的应用进程把字节流写入TCP的发送缓存;接收方的应用进程从TCP的接收缓存中读取字节流。下图画出了TCP缓存和窗口之间的关系:

我们先来看(a)图:

可以看到数据量大小是发送缓存>应用程序>发送窗口。

发送缓存用来暂时存放:

1: 应用程序传给TCP准备发送的数据。

2: TCP已经发送但未收到确认的数据。

应用程序必须控制写入缓存的速率,不能太快,否则发送缓存就是会没有存放数据的空间。(I/Obuffer)

再看一下(b)图:

接收缓存用来暂时存放:

1: 按序到达的、但尚未被接收应用程序读取的数据

2: 未按序到达的数据

如果收到的分组被检测出有差错,则要丢弃。如果应用程序来不及读取收到的数据,接收缓存最终就会被填满,使接收窗口减小到0。反之,如果应用程序能够及时从接收缓存中读取收到的数据,接收窗口就可以增大,但不能超过接收缓存的大小。(b)中还指出了,下一个期望收到的字节号,这个字节号也就是接收方给发送方的报文段的首部中的确认号。

经过讨论,可以强调3点:

1. A的发送窗口是根据B的接收窗口来设置的。

2. TCP对不按序到达的数据会先临时存放在接收窗口中,等到缺少字节收到后,再上交付到应用程序。

3. TCP要求接收方必须有积累确认的功能,这样可以减小传输开销。接收方可以在合适的时候发送确认,也可以在自己有数据要发送时把确认信息顺便捎带上。

3. 超时重传选择

3.1超时重传时间设置

如果超时时间设置的太短,就会引起报文段不必要的重传,增大网络负荷;如果设置的太长,又增加了网络的空闲时间,降低了传输效率。所以超时重传时间设置应该是动态变化的。

RTT(报文段的往返时间): 一个报文段发出的时间,到收到确认的时间。

RTTs(加权平均往返时间或平滑往返时间): 根据RTT计算出来的,超时重传时间。

新的RTTs = (1-α)*(旧的RTTs) + α*(新的RTT样本)。新的RTT即动态变化的重传时间。

RFC2988推荐的α值为1/8。用这种方法得出的加权平均往返时间RTTs就比测量出的RTT值更加平滑。

3.2超时计时器的设置

RTO(超时计时器设置的超时重传时间),应该略大于RTTs。RTO就是真正用来计算超时重传的时间设置。

RTO=RTTs + 4 * RTTd

RTTd是RTT的偏差的加权平均值。当第一次测量时,RTTd值为测量到的RTT值的一半,往后的测量中,RTTd的计算公式如下:

新的RTTd = (1-β) * (旧的RTTd) + β * |RTTs - 新的RTT样本|

β的推荐值是1/4。

3.3Karn算法

重传后,如何判定此确认报文段是对先发送的报文段的确认,还是对后来重传报文段的确认?重传报文段和原来的报文段完全一样,因此源主机在收到确认后无法作出正确的判断,而RTTs的值对正确的判断影响很大。

Karn提出了一个算法:在计算RTTs时,只要报文段重传了,就不采用重传报文段的往返时间样本(即上面公式中新的RTT)。这样得出的RTTs和RTO就比较准确。

但有个问题,就是超时重传时间无法更新。于是修正后的Karn算法是:报文段每重传一次,就把超时重传时间RTO增加大一些。典型做法是取新的重传时间为2倍的旧的重传时间。当不发生重传时,才根据上面RTO的公式计算超时重传时间。

选择确认SACK

在第一章介绍报文段头部选项的时候有介绍SACK的作用:只传送缺少的数据,不重传已经正确到达接收方的数据。

然而SACK文档没有指明发送方应当怎样响应SACK。因此大多数的实现所有未被确认的数据块。

TCP学习总结(二)的更多相关文章

  1. 网络编程基础之TCP学习(二)编程案例

    TCP网络编程流程如下: 实现功能:服务器端与客户端成功通讯后返回get! 服务器端程序 #include <netdb.h> #include <sys/socket.h> ...

  2. TCP学习之二:客户端与服务端的连接

    主要参考张子阳大神的博客:http://www.cnblogs.com/JimmyZhang/category/101698.html TcpClient是对Socket的封装 一个TcpClient ...

  3. CentOS 7 学习(二) 配置Nginx反向代理

    CentOS 7 学习(二) 配置Nginx反向代理 Nginx可以通过php-fpm来运行PHP程序,也可以转向apache,让apache调用php程序来运行. 不过对于Nginx来说,其反向代理 ...

  4. 《Spring Cloud》学习(二) 负载均衡!

    第二章 负载均衡 负载均衡是对系统的高可用.网络压力的缓解和处理能力扩容的重要手段之一.Spring Cloud Ribbon是一个基于 HTTP 和 TCP 的客户端负载均衡工具,它基于Netfli ...

  5. Netty 学习(二):服务端与客户端通信

    Netty 学习(二):服务端与客户端通信 作者: Grey 原文地址: 博客园:Netty 学习(二):服务端与客户端通信 CSDN:Netty 学习(二):服务端与客户端通信 说明 Netty 中 ...

  6. crawler4j 学习(二)

    crawler4j 学习(二) 实现控制器类以制定抓取的种子(seed).中间数据存储的文件夹.并发线程的数目: public class Controller { public static voi ...

  7. 从零开始学习jQuery (二) 万能的选择器

    本系列文章导航 从零开始学习jQuery (二) 万能的选择器 一.摘要 本章讲解jQuery最重要的选择器部分的知识. 有了jQuery的选择器我们几乎可以获取页面上任意的一个或一组对象, 可以明显 ...

  8. Android Animation学习(二) ApiDemos解析:基本Animators使用

    Android Animation学习(二) ApiDemos解析:基本Animatiors使用 Animator类提供了创建动画的基本结构,但是一般使用的是它的子类: ValueAnimator.O ...

  9. AspectJ基础学习之二搭建环境(转载)

    AspectJ基础学习之二搭建环境(转载) 一.下载Aspectj以及AJDT 上一章已经列出了他的官方网站,自己上去download吧.AJDT是一个eclipse插件,开发aspectj必装,他可 ...

随机推荐

  1. prometheus相关文章

    prometheus book https://yunlzheng.gitbook.io/prometheus-book/ 开发自己的分布式监控Prometheus Exporter时遇到的坑 htt ...

  2. 另类AOP设计

    常见的AOP设计都基于Remoting的RealProxy,或者基于Emit实现的动态代理,或者基于反射的Attribute扫描拦截.但是我们还有另类的拦截方案DynamicObject,只要我们继承 ...

  3. JVM调优之Tomcat启动加速(二)

    使用 startup.bat 启动Tomcat 服务器时,start.bat  调用了bin 目录下的calalina.bat 文件. 如果需要配置 Tomcat的JVM参数,可以将参数写入 cata ...

  4. 8.3 GOF设计模式二: 适配器模式 Adapter

    GOF设计模式二: 适配器模式 Adapter  为中国市场生产的电器,到了美国,需要有一个转接器才能使用墙上的插座,这个转接 器的功能.原理?复习单实例模式  SingleTon的三个关键点  ...

  5. LCSS最长公共子序列算法

    0.论文基本介绍以及相关内容 分析移动用户位置的相似性,提取移动用户的相似路径在出行路径预测.兴趣区域发现.轨迹聚类.个性化路径推荐等领域具有广泛的应用. 重点:利用移动用户定位数据找到合适轨迹的表示 ...

  6. win2012服务器配置ftp

    1.打开服务器管理器,选择添加角色和功能 2.按照下述向导,安装IIS 选择iis 勾选FTP服务器 3.添加新用户 用户密码按照下图勾选,创建用户 4.IIS配置FTP站点 指定用户访问,并授权,点 ...

  7. python 近义词库包 synonyms 的使用

    最近接触到nlp的一些东西,需要找出中文词语的近义词,也接触到了一个synonyms 的库, 分词,去停用词,word2vector  等 一些列nlp 的操作,还可以输出中文词语的近义词 https ...

  8. Jquery版本对IE浏览器的支持

    浏览器名称 Jquery最低 Jquery最高 IE6 1.0 1.12 IE7 1.0 1.12 IE8 1.0 1.13 jquery各版本下载:https://code.jquery.com/j ...

  9. python3爬虫_环境安装

    一.环境安装 1.python3安装 官网:https://www.python.org/downloads/ 64 位系统可以下载 Windows x86-64 executable install ...

  10. PDF 补丁丁 0.6.0.3355 版发布(修复阅读模式、书签缩放的问题)

    PDF补丁丁的新版本修复了染色阅读模式失效.编辑器书签缩放比例调整在某些场合下失败的问题.