个人的TCP/UDP的总结(二)

前面一节咱们介绍完了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)中还指出了,下一个期望收到的字节号,这个字节号也就是接收方给发送方的报文段的首部中的确认号。

猜你喜欢

转载自my.oschina.net/u/3707537/blog/1643489
今日推荐