程序君译文:每个开发人员应了解的 TCP 知识


为什么要把服务器放在离用户很近的地理位置上?其中一个原因是为了实现更低的延迟 。 当您发送的数据是短的、应该尽可能快的传输数据时 , 这很有意义 。 但如果是大文件 , 比如视频等大文件呢?当然 , 在接收第一个字节时肯定会有延迟惩罚 , 但之后不应该一帆风顺吗?
通过TCP发送数据时 , 像HTTP一样 , 一个常见的误解是带宽与延迟无关 。 但是 , 对于TCP来说 , 带宽是延迟和时间的函数 。 我们来看看是怎么做到的 。 握手
在客户端开始向服务器发送数据之前 , 它需要对TCP进行握手 , 对TLS进行另一个握手 。
TCP使用三向握手来建立一个新的连接 。
发送方选择一个随机生成的序列号 "x "并发送一个SYN数据包给接收方
接收方递增 "x" , 选择一个随机生成的序列号 "y "并发送一个SYN/ACK数据包 。
发送方递增序列号 , 并回复一个ACK数据包和第一个字节的应用数据 。
TCP使用序列号是为了保证数据的有序、无漏洞的传递 。

程序君译文:每个开发人员应了解的 TCP 知识
本文插图

握手
握手引入了一个完整的往返 , 这取决于底层网络的延迟 。 TLS 握手也需要最多两次往返 。 在TLS连接打开之前 , 不能发送任何应用数据 , 这意味着在这之前 , 你的带宽是零 。 回程时间越低 , 建立连接的速度就越快 。 流量控制
流量控制是一种回避机制 , 实现的目的是防止发送方压倒接收方 。
接收方将传入的TCP数据包存储到一个接收缓冲区 , 等待应用程序处理 。

程序君译文:每个开发人员应了解的 TCP 知识
本文插图

流量控制
每当接收方承认一个数据包时 , 接收方也会向发送方反馈缓冲区的大小 。 如果发送方尊重协议 , 发送方就会避免发送更多可以装入接收方缓冲区的数据 。

程序君译文:每个开发人员应了解的 TCP 知识
本文插图

流量控制
这种机制与应用层面的速率限制没有太大区别 。 但是 , 与API密钥或IP地址上的速率限制不同 , TCP是在连接层面上的速率限制 。
发送方和接收方之间的往返时间(RTT)越低 , 发送方就越能使其输出带宽适应接收方的容量 。 拥堵控制
TCP不仅要防止接收方不堪重负 , 还要防止底层网络被淹没 。
发送方如何知道底层网络的可用带宽是多少?唯一的方法就是通过测量来估算 。
其思路是 , 发送方维护一个所谓的 "拥塞窗口" 。 拥塞窗口表示不等待对方的回执 , 可以发送的未完成的数据包总数 。 接收器窗口的大小限制了拥塞窗口的最大大小 。 拥塞窗口越小 , 在任何给定的时间内可以飞行的字节数就越少 , 带宽的利用率就越低 。
当建立新连接时 , 拥塞窗口的大小被设置为系统默认值 。 然后 , 每承认一个数据包 , 窗口的大小就会成指数级地增加 。 这意味着 , 我们不能在建立连接后立即使用网络的全部容量 。 再次 , 来回时间越低 , 发送方就越能迅速开始利用底层网络的带宽 。

程序君译文:每个开发人员应了解的 TCP 知识
本文插图

拥堵控制
如果数据包丢失了怎么办?当发送方通过超时检测到漏报时 , 一个叫做 "拥塞避免 "的机制就会启动 , 拥塞窗口大小就会减小 。 从此以后 , 时间会使窗口大小增加一定的量 , 超时则会使窗口大小减少另一个 。
如前所述 , 拥塞窗口的大小定义了无需等待确认就可以发送的最大比特数 。 而发送者需要等待一个完整的往返 , 才能得到一个确认 。 所以 , 将拥塞窗口的大小除以往返时间 , 就可以得到最大理论带宽 。
带宽= WinSize / RTT


推荐阅读