12.1 引言
12.1.1 ARQ 和 重传
重传的时候,接收方可能收到被传送分苏的重复副本,这就要求使用序列号来解决:在被远端发送时,每个唯一的分组都有一个新的序列号。
如果想要吞吐量更高,我们就要求在网络中可以同时存在多个分组,这就变得更加复杂:发送方不仅要决定什么时候注入一个分组到网络中,还要考虑注入多少个,并且在等待 ACK 的时候,怎样维持计时器,同时还需要保存每个还没收到 ACK 分组的副本防止重传需要。
12.1.2 分组窗口和滑动窗口
为了解决上述问题,我们假设每个分组有一个序列号,并且定义一个分组窗口作为已经被发送但是还没完成确认的分组集合,我们把窗口中分组的数量称为窗口大小,如下图所示:
上图显示当前窗口有3个分组,整个窗口大小是3。其中,3号分组已经被发送和确认,所以发送方保存的副本可以释放了;分组 7 在发送方已经准备好,但是还没发送,因为还没“进入窗口”。现在假如发送方下一步收到分组 4 的 ACK,此时窗口向右边 “滑动”一个分组,意味着 4 可以释放了,而 7 可以发送了。这种就叫做 “滑动窗口”协议。
一般来说,这个滑动窗口在发送方和接收方都会有,在发送方,它记录着哪些分组可以释放,哪些正在等待 ACK,哪些分组还不能被发送;在接收方,它记录着哪些分组已经被接收和确认,哪些分组时下一步期望的,哪些分组即使接收了也会被丢弃。
12.1.3 变量窗口:流量控制和拥塞控制
为了处理接收方相对发送方太慢的问题,我们在接收方跟不上时会强迫发送方慢下来,这称为流量控制。主要有以下2种方式:
基于速率流量控制:给发送方指定某个速率,去报数据不能超过这个速率发送。多用于流应用程序,可被用于广播和组播发现
基于窗口流量控制:这是使用滑动窗口最流行的方法,思想是:窗口大小不固定,允许随时间变化而变化,必须有一种方法让接收方可以通知到发送方使用多大窗口(即窗口通告)
拥塞控制用于发送方减低速度以不至于压垮发送方与接收方之间的网络。
12.2 TCP的引入
TCP 提供一种字节流抽象概念给应用程序使用,这就意味着没有消息边界。举例解释一下:如果应用程序一一端写入 10 字节,随后又写入 20 字节,再随后写入 50 字节,那么在另一端时不知道每次写入多少字节的;另一端可能以每次读取20字节分4次读取或者一次性读取80字节的方式读取。
TCP根本不会解读字节流中的字节内容,它不知道传输的是二进制数据、ASCII 还是其他东西。
12.2.2 TCP中的可靠性
TCP 必须把应用程序发送的字节流转换为一组 IP可以携带的分组,这被称为组包。这些分组包含序列号,该序列号在TCP 中代表了每个分组的第一个字节在整个数据流中的字节偏移,而不是分组号。TCP传给IP的块称为 报文段。
而UDP 就不同了,应用程序每次写入通常就产生一个 UDP 数据,其大小就是写入的那么大(加上头部)。
TCP 发送一组报文段时会设置一个重传计时器,等待对方的确认。不过它不会为每个报文段设置,而是发送一个窗口的数据,它只设置一个计时器,当 ACK 到达时再更新超时。如果有一个确认没有及时接收到,这个报文段就会被重传。
12.3 TCP 头部封装
UDP 的头部一般是 8 字节,TCP 头部通常是 20 个字节(带选项的话可达 60 字节)。每个TCP 的头部都包含了 源和目的IP地址,以及源和目的 端口号。
在 TCP 术语中,一个 IP 地址和一个端口的组合被称为 套接字(Socket) 或者 端点(endpoint)
TCP 报文段的数据部分是可选的,基于后面的知识我们可以看到:当一个连接被建立和终止时(我理解的是 握手和挥手),交换的报文段只包含 TCP 头部而没有数据。
12.4 总结
处理传输过程的差错主要有2种方法:
差错校正码:添加一些冗余比特,使得即使某些比特被毁,真实的信息也能被恢复过来
重传,直至信息被正确接收