分类 Http Socket 下的文章

可靠数据传输原理 三 TCP协议


TCP概述:RFCs-793,1122,1323,2018,2581

点对点

一个发送方,一个接收方。不支持一对多,比如一个发送方多个接收方

tcp使用流水线机制

TCP拥塞控制和流量控制机制设置窗口尺寸。
至于窗口尺寸的设置是一个比较复杂的事情了,他是基于拥塞控制和流量控制机制来动态调整窗口尺寸

发送方和接收方都设置缓存

他结合GBN和SR协议,发送方接收方都设置缓存

面向连接

  • 通信双方在发送数据之前必须建立链接。
  • 链接状态只在链接的两端中维护,在沿途节点中并不维护状态。
  • TCP链接包括:两台主机的缓存,链接状态变量,socket等

全双工

同一个连接中能够传输双向数据流

tcp的段结构

在tcp段结构中很多字段都还没有用,存在很多改进空间。

recevie window
所愿意接收的字节的字节数,来进行流量控制

序列号:

  • 序列号指的是segment中的第一个字节的编号,而不是segemnt的编号
  • 建立TCP连接时,双方随即选择序列号

不是segment的第几个这样的编号,而是第一个字节的编号
随机选择序列号,在链接之后,回互相交换信息

ACKs:

  • 希望收到的下一个字节的序列号
  • 累计确认:该序列号之前的所有字节均已被正确接收

acks表示下一个期望接收到的序列号的值
注意也是累计确认的有点像GBN

接收方如何处理乱序到达的Segement?

  • TCP规范中没有规定,由TCP的实现者做出决策

看一个例子

  1. 第一条线是在tcp链接已经建立的情况下,段的序列号是序列号是随机选择的。下一个期望接收到的序列号是79
  2. 主机b 返回的段的序列号为79,下一个期望接受到的为43。与此同时43之前的都已经被确认了
  3. 之后主机a要再发一个确认,这时候data里面不带任何数据。序列号变成了43,ack变成了80

之前看了大量的可靠传输的原理,下面来看tcp是用到了哪些可靠传输的原理来实现可靠传输服务的。

IP层是不可靠的,tcp要把他转换为可靠的服务

  • TCP在IP层提供的不可靠服务基础上实现可靠数据传输服务
  • 流水线机制
  • 累计确认
  • Tcp使用单一重传定时器

后面要了解下单一计时器是怎么使用的


可靠数据传输原理 二 滑动窗口协议之SR协议


SR协议是滑动窗口协议的另外一类。


GBN协议的缺陷是重传的时候,传很多个之前传过去的分组。比如当序列号n开始重传,那就回传n及n以后所有的未确认的分组。那么我们是否可以考虑不使用累积确认机制,进行单个确认,然后我们也不丢弃乱序的分组,而是将他们缓存起来,这就是SR协议。

设置缓存,可以接受乱序到达的分组

超过定时器时间重传,但是只重传自己


可靠数据传输原理 二 滑动窗口协议之GBN协议


Rdt3.0的性能太低了,显然需要改进它
如果细究这个效率太低的原因,那就是停等操作导致的。所以要打破停等机制,可以在等的同时,继续发送其他分组。

回顾这张图

Usender:效率
由于要等待RTT这个时间才能发下一个分组,所以效率很低。

流水线机制,可以提高资源利用率


比如一次性发三个。效率提高三倍

流水线协议


序列号也多了,一个分组用一个序列号。
之前是发一个 然后要等,所以先缓存起来,然后等确认后删除,现在是多个需要同时缓存起来了。

可以看到流水线机制,就是同时发多个分组在路上,然后返回ack的时候也有多个ack在路上

滑动窗口协议

要想实现流水线机制,需要滑动窗口协议


这些小竖条是一共可以提供使用的序列号的数量(k比特的话就是2^k次方个可用的序列号)。
窗口左边是已经发送并且已经确认了的,黄色的是发出去了,但是还没收到确认的。蓝色的是代表,剩余的可以用来发送的序列号,白色的是哪些还不能使用的序列号,因为你的窗口还没有滑动到那里。

两种滑动窗口协议:GBN,SR

后退N帧(GBN)协议(意思是从没接受到的ack的那个分组开始发送,就算后面的收到了,也都重新发送一遍?)


k-bit序列号意味着2的k次方个序列号可以用
最多n个分组未确认

【重】在来看看滑动窗口的结构

这些小竖条是一共可以提供使用的序列号的数量(k比特的话就是2^k次方个可用的序列号)。
窗口左边是已经发送并且已经确认了的,黄色的是发出去了,但是还没收到确认的。蓝色的是代表,窗口内剩余的可以用来发送的序列号,白色的是哪些还不能使用的序列号,因为你的窗口还没有滑动到那里。

GBN协议(理解的不够深)
是采用一种累积确认的机制(也就是会从一到...,n-1,到n一个个累积),当他ack(为n)的时候,说明都已经被确认了

毫无疑问,也是要为每一个分组设置定时器的,然后如果超过一定时间,即timeout了,那就会重发所有未收到的ack的以及后面的分组(比如第k个timeout了,那就会重发序列号为k+1,k+2,...,n-1,n的所有分组)。

上面的方式会造成资源的浪费

流水线机制就可能导致分组的ack乱序到达,gbn处理的方式是,直接丢掉哪些不是期望收到的ack序列号


可以看到当收到pkt3的时候直接丢弃发送ack1,因为收到pkt0,pkt1后,没有收到pkt2.直到pkt2timeout后,重新发送pkt2,以及之后的pkt3,pkt4...统统重发出去。

看一道题:

11.数据链路层采用后退N帧(GBN)协议,发送方已经发送了编号为0~7的帧。当计时器超时时,若发送方只接收到0、2、3号帧的确认,则发送方需要重发的帧数是(C )。

A.2 B.3 C.4 D.5

解析:连续ARQ协议中,接收方一般采用累积确认的方式即接收方对按序到达的最后一个分组发送确认,

题目中收到3的确认帧就代表编号为0、1、2、3的帧已接收,而此时发送方未收到1号帧的确认只能代表确认帧在返回的过程中丢失了,而不代表1号帧未到达接收方。因此需要重传的帧是编号为4、5、6、7的帧。

GBN协议有一定的难度,需要多看几遍,反复琢磨一下。


可靠数据传输原理 一(rdt3.0)


在Rdt2.0及2.x时代,假定的是信道只有一种不可靠特征,也就是只发生位bit的错误,不会丢失分组等错误,现在假设更实际一些。

如果信道极可能发生错误,也可能丢失分组,怎么办?

  • “校验和+序列号+ACK+重传”够用吗?

例子假如说现在发送方发了一个分组给接收方,而接受方没有收到,则接收方一直等着,发送方也一直等着接收方发来确认消息。

这时候这些机制就不够用了,怎么处理分组丢失呢?

解决办法:

设置一个等待的合理的时间。过了时间就重传。

  • 如果没有收到ACK,重传。
  • 如果分组或者ACK知识延迟,而不是丢了。
    重传会产生重复,序列号机制能够处理
    接收方需要在ACK中显式告知所确认的分组
  • 需要定时器。

状态图

下面是正常情况:


发送方发了pkt0,接收方收到后,发ack0。然后发送方收到了ack0,则继续发pkt1,接收方正常接收后,发ack1.发送方收到后,再发pkt0...

下面是丢包的情况下:


当发pkt1的时候,发送失败后,timeout后,触发再次发送pkt1。

如果丢失了ack怎么办?


ack1没有发给发送方,则过了timeout的时间后发送方会重新发送pkt1,这时候其实接收方接到了两次pkt1,删除掉重复的,然后再发一次ack1(ack永远是最后一个收到的分组)给发送方

如果定时器设置过短呢?

在发送方没有接受到ack的时候,又重传的情况

网络延迟是不确定的,timeout的值不好设定。

Rdt3.0功能正确的,性能怎么样?


Rdt3.0性能是由于这样的停等操作引起的效率非常低。


过了半个rtt,第一个bit到达接收方,再过L/R的时间,该分组的最后一个bit到达接收方,然后发ack(ack很小可以认为一次性发过去),再花半个RTT的时间,到达发送方。所以发送一个分组的总时间为t=RTT+L/R.
所以利用率就是


可靠数据传输原理 一(rdt1.0 2.0 2.1 2.2)


把不可靠的数据传输编程可靠的数据传输

  • 信道的不可靠特性决定了靠靠数据传输协议(Rdt)的复杂性
  • 要实现不丢,不乱,不错


应用层和传输层的箭头是单项的,而传输层跟网络层,链路层是双向的控制消息的流动完成的,后面会进一步去看

利用状态机刻画传输协议

圆圈是表示一个状态,横线上边是一个事件,下面是一个动作

Rdt1.0:可靠信道上的可靠数据传输(信道本省就是可靠的情况)

发送方:


由于确定百分之百可靠的传输所以发完之后,又回来重新等待继续发送不用管别的

接收方:


接收方也就一个状态,就等着从下层发过来,

Rdt2.0:可能产生位错误的信道,但是不会丢包等其他错误。

  • 底层信道可能翻转分组中的位,可以利用校验和检验位错误

发完了后发送方不知道错没错,只有接收方告诉他

如何从错误中恢复?

  • 确认机制(ACK):接收方显式的告知发送方分组已确认接收
  • NAK:接收方显式的告知发送方分组有错误
  • 发送方收到NAK后,重传分组。

也就是要有机制的概念了,引入了ACK的机制,NAK机制,重传机制。

这种基于重传机制的rdt协议称为ARQ(automatic repeat reQuest)协议

比1.0多的东西,Rdt2.0中引入的新机制

  • 差错检测
  • 接收方反馈控制消息:ACK/NAK
  • 重传


在rdt1.0的时候,发送方接收方一个状态就够了,
首先是等待上层调用,这个没有变。第二个状态是等待Ack,Nak,也就是法完之后要等待对方控制消息的状态,也就叫停等协议

而且发送的时候要加入不仅仅是data,还要加入checksum这个参数

Rdt2.1 应对ACK/NAK消息发生错误或者被破坏

  • 为ACK/NAK增加校验和,检错并纠错
  • 发送方收到被破坏的ACK/NAK时候不知道接收方发生了什么,添加额外的控制消息
  • 如果ACK/NAK坏掉,发送重传
  • 不能简单的重传,因为会产生重复分组

常用的一种方法,发送方接收到ack,nak错误的时候不管三七二十一直接重传,但是会带来的问题就是重复分组。怎么解决呢?

增加序列号,丢弃重复分组

rdt2.0和rdt2.1的区别

注意:接收方无法知道ack/nak是否被发送方正确收到。

Rdt2.2


是否真的需要NAK这样的机制,多了一种机制,处理逻辑就更复杂


shijiebei 365bet manbetx 188bet xinshui caipiao 95zz tongbaoyule beplay 88bifa 18luck betway bwin hg0088 aomenjinshayulecheng ca88 shenbotaiyangcheng vwin w88 weide