TCP可靠传输

写在前面

这是我开始学习计算机网络后的第一篇博客。之前的内容会在后面机会适当的时候补上。实际上我认为应用层的部分笔记不会少,而且会比书中的内容多很多。最近租了一个阿里云的轻量级应用服务器,不仅把博客牵上来了,还买了一个域名,登记了DNS,做好了备案。除此之外,我用roundcube和dovecot搭建了一个邮箱。目前还没有开放注册,而且只能发送本地邮件,有点鸡肋。争取在研究应用层的同时把上层的工具使用方法也研究出来。

可靠传输原理

可靠传输协议的出现原因就是复杂网络下数据包不一定能够保证传输成功,因此需要一个面向连接的可靠传输协议。TCP即为此思想的产物,本节先讨论可靠传输的基本原理。

传输协议的构建

可靠信道传输

通过可靠信道传输时,发送端只需要在上层调用时发送数据。接收端则只需要接受数据并发送给上层。

比特差错信道传输

针对比特差错信道,第一要务为检错。因此需要使用校验手段来检查是否能够接受当前数据包。
在检错以外,还需要通过重传请求来让错误包重传。
重传的方式即为发送请求,让发送方重传数据包。但是这只是在没有丢包,只有比特差错中的实现。在这个框架下,发送方在得到ACK或NAK之前是不能发送新数据的。

!!! warning
问题在于,重传请求如果出问题,那么就会出现发送方不知道该不该发下一个包的问题。因此,下一个解决的问题就是包的序号问题,而由于序号的数量有限,因此发送和接收的序号都是循环窗口。

因为目前不存在丢包问题,因此窗口大小为2即可保证顺序。
接下来放弃使用ACK和NAK,转而变为ACK0和ACK1。

丢包信道传输

冗余检测:
对于丢失的包,冗余检测机制会把丢失的包忽略,而一直发送同一个ACK,来告知对方不要发送新的包。

针对ACK丢失的情况:
在可能丢包(发送与接收方都会有)的信道中,则需要一个超时重传机制。即发送方在发送数据后,等待一段时间,如果没有收到ACK,则重传数据包。而在此基础上,发展出了两种重传机制:

  1. 回退N步:针对一个发送与接收的窗口(通常发送窗口大小为N而接收窗口小于等于N/2)。如果接收窗口没有接收到k号包,当发送方计时器发现k号包的ACK没有收到且超时,就会重传K和之后的所有包。好处是实现简单,坏处是效率低。
  2. 选择重传:发送方在发送数据包后,等待ACK,如果没有收到ACK,就会重传这个包。这样的好处是效率高,但是实现复杂。因为要考虑接受的包的顺序,窗口的分组被缓存到所有更小的包都接收之后。每次只有收到后接收方窗口才会滑动,而只有收到ACK的最小窗口才会向前移动。

在这里还有一个TCP实现的(回退N步的)技术细节,即快速重传。在接收方收到一个包的时候,如果发现有一个包丢失,就一直发送当前的ACK,如果接收方得到了三次同样序号ACK,就直接重传而不等待超时。

传输速率的考虑

考虑传输速率的话,如果每次都等ACK到达才发送下一个包,那么bubble就会很多,因此提出了pipeline模式的发送数据包,在窗口变大时,可以同时发送好几个包来同时等待ACK。如同流水线的工作方式,每收到一个新的ACK就让窗口向前滑动。

TCP的实现

TCP的基本原理是面向连接的。其不保持一个链路上或者物理上的持续链接,而是收发双方共同保持状态的逻辑连接。