可靠数据传输原理
可靠数据传输协议
在可靠数据传输协议中,数据可以通过一条可靠的信道进行传输,从而使数据比特不会在传输过程中损坏或丢失,并且所有数据按照发送顺序进行交付。
TCP是在不可靠的(IP协议)端到端网络层之上实现的可靠数据传输协议。
经完全可靠信道的可靠数据传输:rdt 1.0
假设底层信道是完全可靠的,那么发送方只需要向接收方发送数据,不需要关心接收方是否成功收到;而接收方只需要接收数据,而不需要提供任何反馈给发送方。由于通信过程中不会出现任何差错,因此接收方没有必要请求发送方减缓发送速率。
经具有比特差错的可靠数据传输:rdt 2.0
假定分组中的比特可能受损,但是所有发送的分组能按其发送的顺序接收。这时候需要采用肯定确认(ACK) 和 否定确认(NAK),用于让发送方知道哪些内容被正确接收,哪些内容有误因此需要重传,基于这样重传机制的可靠数据传输协议称为自动重传请求协议(ARQ)。
通常ARQ协议需要三种协议功能处理存在比特差错的情况:
- 差错检测:接收方使用检验和字段等方式检测到分组出现了差错;
- 接收方反馈:接收方通接收情况反馈给发送方,如用一个比特长进行表示,0代表NAK,1代表ACK;
- 重传:接收方收到有差错的分组时,发送方重传该分组。
当发送方处于等待ACK或NAK的状态时,它不能从上层获得更多的数据,发送方将不会发送新数据,除非发送方确认接收方已正确接收放弃分组,这样的协议称为停等协议。
rdt 2.1 & rdt 2.2
rdt 2.0协议并没有考虑到ACK或NAK分组受损的可能性,rdt 2.1对此的解决方式为:让发送方对分组进行编号,并在分组中添加序号字段,接收方检查序号即可确定收到的分组是否是一次重传。当接收方接收到失序的分组时,对所接收的分组发送一个ACK;接收到受损的分组时,则发送一个NAK。
实际上不需要NAK,而是对上一个正确接收的分组发送一个ACK,发送方接收到对同一个分组的两个ACK(冗余ACK),就直到接收方没有正确接收该分组之后的分组,rdt 2.2就是在rdt2.1的基础上,通过接收方在ACK报文中包括所确认的分组序号实现的一个无NAK的可靠数据传输协议,发送方此时必须检查ACK报文中的分组序号。
经具有比特差错的丢包信道的可靠数据传输:rdt 3.0(比特交替协议)
假定除了比特受损外,底层信道还会丢包,那么发送方需要等待一定的时间以确认分组或接收方对分组的ACK发生了丢失,如果在这个时间内没有收到ACK,则重传该分组。
为了实现基于时间的重传机制,需要一个倒计数定时器,在一个给定的时间量过期后,可中断发送方。为此发送方需要:
- 每次发送一个分组时,便启动一个定时器;
- 响应定时器中断;
- 终止定时器。
归纳可靠数据传输协议的要点
- 检验和
- 序号
- 定时器
- 肯定和否定确认分组
流水线可靠数据传输协议
由于rdt 3.0是一个停等协议,因此具有性能问题,该问题的一个解决办法是:不以停等方式运行,允许发送方发送多个分组而无须等待确认,这种技术称为流水线。实现流水线技术需要:
- 增加序号范围,因为每个输送中的分组必须有一个唯一的序号;
- 发送方最低限度应当能缓存那些已发送但未确认的分组,接收方或许也需要缓存那些已正确接收的分组;
- 所需序号范围和缓存的要求取决于数据传输协议如何处理丢失、损坏及延时过大的分组,解决流水线的差错恢复有两种基本方法:回退N步(GBN)、选择重传(SR)。
回退N步
回退N步协议也称为滑动窗口协议,允许发送方发送多个分组而不需要等待确认,但是在流水线中未确认的分组数不能超过某个最大允许数N,N常被称为窗口长度。
定义基序号base为最早未确认分组的序号,下一个序号next为下一个待发分组的序号,则在:
- [0, base - 1]段内的序号对应于已经发送并被确认的分组;
- [base, next - 1]段内对应已经发送但未确认的分组;
- [next, base + N - 1]段内对应要被立即发送的分组;
- 大于等于base + N的序号是不能使用的,直到当前流水线中未被确认的分组得到确认为止。
一个分组的序号承载在分组首部的一个固定长度的字段中,如果分组序号的比特数是k,则序号范围是[0, ],所有涉及序号的运算使用模运算。TCP序号按照字节流中的字节进行计数,而不是分组计数。
在一个基于ACK、无NAK的GBN协议中,GBN发送方必须响应三种类型事件:
- 上层的调用。当上层调用发送方法时,发送方首先检查发送窗口是否已满,如果窗口未满,则产生一个新分组并发送;如果窗口已满,则将数据返回上层,隐式地指示窗口已满。
- 收到ACK。GBN协议对序号为n的分组采用累计确认,表明接收方已正确接收到序号小于等于n的所有分组。
- 超时事件。如果出现超时,发送方重传所有已发送但还未确认的分组。
如果一个序号为n的分组被正确且按序接收到,则接收方为分组n发送一个ACK,并将分组中的数据部分交付到上层;其他所有情况下,接收方丢弃该分组,并未最近按序接收的分组重新发送ACK。当接收到每一个连续的ACK时,窗口向前滑动,发送方可以发送信道分组。
总结:GBN协议中使用了序号、累计确认、检验和、超时重传等操作。
选择重传
选择重传(SR) 协议,通过让发送方仅重传那些在接收方出错的分组避免不必要的重传,它同样采用滑动窗口限制流水线中未完成、未被确认的分组数,但是窗口中一些分组可能已经收到ACK。SR接收方确认一个正确接收的分组,无论是否按序,失序的分组将被缓存,直到序号更小的分组皆被收到,然后将这批分组按序交付到上层。
SR发送方需要对以下事件进行响应:
- 从上层收到数据,SR发送方检查下一个可用于该分组的序号,如果序号位于发送方的窗口内,则将数据打包并发送;否则要么将数据缓存,要么将其返回给上层以便于以后传输;
- 超时,每个分组必须有自己的逻辑定时器,以便超时后只发送一个分组;
- 收到ACK,若分组序号在窗口内,则SR发送方将该分组标记为已接收;如果分组序号为base,则窗口移动到具有最小序号的未确认分组处;如果窗口移动了且有在窗口内的未发送分组,则发送这些分组。
SR接收方需要对以下事件进行响应:
- 序号在[base, base + N - 1]内的分组被正确接收,收到的分组落在接收方的窗口内,则发送ACK给发送方,如果该分组以前没收到过,则缓存该分组;如果该分组的序号等于接收窗口的base,则从缓存的分组中,将该分组之前的且序号连续的分组交付给上层,然后接收窗口向前移动,按序交付接下来的分组。
- 序号在[base - N, base - 1]内的分组被正确接收到,产生一个ACK,即使该分组已曾经确认过,因为如果不进行确认,则发送方窗口无法向前移动。
- 其他情况,忽略该分组。
可靠数据传输机制及其用途的总结
- 检验和:用于检测在一个传输分组中的比特错误;
- 定时器:用于超时重传一个分组;
- 序号:用于为从发送方流向接收方的数据分组按顺序编号;
- 确认:接收方用于告诉发送方一个分组或一组分组已被正确接收到了;
- 否定确认:接收方用于告诉发送方某个分组未被正确接收;
- 窗口、流水线:发送方也许被限制仅发送那些序号落在一个指定范围内的分组。
——————————————————————————————————
TCP
TCP是因特网传输层的面向连接、可靠的传输协议,依赖差错检测、重传、累计确认、定时器、用于序号和确认号的首部字段实现可靠数据传输。
TCP连接
使用TCP的一个应用进程在可以开始向另一个应用进程发送数据前,两个进程必须先相互发送预备报文段,以建立确保数据传输的参数、初始化TCP状态变量,称为握手,之后两个进程间就会点对点地建立起一条全双工的逻辑连接。
连接建立后,当客户端向服务器发送数据时,客户端进程通过套接字传递数据流,TCP将数据引导到该连接的发送缓存,接下来TCP会不时从发送缓存里取出一块数据传递到网络层。TCP可从缓存中去除并放入报文段的数据量受限于最大报文段长度(MSS),它是报文段里应用层数据的最大长度(不包括TCP首部),通常根据由本地发送主机发送的最大链路层帧长度,即最大传输单元(MTU) 进行设置。接下来TCP为每个数据配上一个TCP首部从而形成TCP报文段并下发给网络层,网络层将其封装在IP数据报中并发送到网络中。当TCP在另一端接收到一个报文段后,该报文段的数据就被放入该TCP连接的接收缓存中,应用程序从接收缓存读取数据流。
因此TCP连接的组成包括:
- 发送主机:发送缓存、变量、进程连接的套接字;
- 接收主机:接收缓存、变量、进程连接的套接字。
TCP报文段结构
TCP报文段由首部字段和数据字段组成,其中数据字段的长度受MSS限制,当TCP发送一个大文件,该文件将被分成长度小于等于MSS的若干块。
TCP首部包括:
- 源端口号、目的端口号:用于多路复用/分解来自或送到上层应用的数据;
- 检验和字段
- 序号字段、确认号字段:32比特,用于实现可靠数据传输。
- 首部长度字段:4比特。
- 标志字段:6比特,ACK用于指示确认字段中的值是有效的;RST、SYN、FIN用于连接建立和拆除,PUSH、URG在实践中未使用。
- 可选与变长的选项字段。
序号和确认号
序列号建立在字节流之上,一个报文段的序号是该报文段首字节的字节流编号,如MSS为1000字节的报文段,第一个报文段序号为0,第二个为1000,以此类推。
当主机A从B使用TCP接收数据时,A填充进报文段的确认号是A期望从B收到的下一字节的序号,TCP只确认该流中至第一个丢失字节为止的字节,即提供累计确认。
可靠数据传输
TCP采用超时/重传机制来处理报文段的丢失问题,仅采用单一的重传定时器实现定时器管理过程。TCP发送方有3个与发送和重传相关的事件:
- 当从上层应用程序接收数据,那么TCP把数据封装在一个报文段中,并把该报文段交给IP,然后启动该定时器;
- 当出现超时,TCP通过重传引起超时的报文段响应超时事件,然后TCP重启定时器;
- 当收到来自接收方的ACK报文段,TCP将ACK的值y与它的变量SendBase(最早未被确认的字节序号)进行比较,如果y > SendBase,则该ACK是在确认一个或多个未被确认的报文段,发送方更新SendBase;如果当前有未被确认的报文段,TCP重新启动定时器。
快速重传
由于发送方经常连续发送大量报文段,因此一个报文段丢失可能引起多个冗余ACK,如果发送方收到3个对相同数据的冗余ACK,TCP就执行快速重传,即在该报文段的定时器过期之前重传丢失的报文段。
流量控制
流量控制是一个速度匹配服务,即发送方的发送速率与接收方的读取速率相匹配。TCP通过让发送方维护一个接收窗口变量实现流量控制。UDP不提供流量控制,因此报文段可能由于缓存溢出在接收方丢失。
TCP连接管理
三次握手
三次握手的步骤如下:
-
客户端的TCP首先把一个特殊的TCP报文段封装在一个IP数据报中,发送给服务器,该报文段不包含应用层数据,首部的SYN标志位被置为1,因此这个报文段被称为SYN报文段,客户端还会随机选择一个初始序号 client_isn放置于TCP报文首部的序号字段中;
-
服务器接收到SYN报文段的IP数据报后从中提取TCP SYN报文段,为该TCP连接分配TCP缓存和变量,并向客户TCP发送允许连接的报文段。该报文段也不包含应用层数据,SYN置为1,确认号字段被置为client_isn + 1,服务器选择自己的初始序号sever_isn放置到TCP报文首部的序号字段中,该报文段被称为SYNACK报文段;
-
客户端收到SYNACK报文段后给该连接分配缓存和变量,并向服务器发送另一个报文段,用于对服务器的允许连接报文段进行确认,该报文段SYN置为0,并且可以携带数据。
三次握手的过程如下图:
四次挥手
四次挥手的步骤如下:
- 客户端TCP向服务器发送一个FIN标志位置为1的报文段,表示数据已经发送完毕,请求关闭连接;
- 服务器接收到后向客户端发送一个ACK报文段进行确认;
- 服务器发送FIN标志位置为1的报文段,表示数据接收完毕,请求关闭连接;
- 客户端接收到后向服务器发送一个ACK报文段进行确认,经过定时等待后两台主机用于连接的所有资源释放。
四次挥手的过程如下图:
TCP生命周期
TCP生命周期如下图:
SYN洪泛攻击
SYN洪泛攻击是一种DOS攻击,攻击者发送大量的TCP SYN报文段而不完成三次握手,使服务器不断为这些半开连接分配资源导致服务器的连接资源消耗殆尽。一种有效的防御手段称为SYN cookie:
-
服务器收到一个SYN报文时,不会为该报文段生成一个半开连接,而是根据报文段的源IP地址与端口号、仅服务器知道的秘密数使用散列函数生成一个初始序列号,称为cookie,并发送以cookie作为初始序列号的SYNACK分组,而服务器并不记忆该cookie或是任何SYN的其他信息;
-
合法用户会返回一个ACK报文段,服务器收到后根据SYNACK的源IP地址与端口号以及仅服务器知道的秘密数使用散列函数计算后加1,如果计算结果与SYNACK中的确认号相同的话则判断该用户合法,服务器于是生成一个全开连接;
-
如果客户端没有返回ACK报文段,则服务器没有为它分配任何资源,因此初始SYN并没有对服务器产生危害。
端口扫描原理
假如一台主机接收了具有目的端口80的TCP SYN分组,但该主机在端口80不接受连接,则该主机向源发送一个特殊重置报文段,其RST标志位置为1;如果接收到的是UDP分组,且目的端口与进行中的UDP套接字不匹配,则主机发送一个特殊的ICMP数据报。
当发送主机往目标主机的6789端口发送一个TCP SYN报文段,则有源主机接收到的3种可能:
- TCP SYNACK报文段,意味着目标主机上一个应用程序使用TCP端口6789运行;
- TCP RST报文段,意味着SYN报文段到达了目标主机,但目标主机没有使用TCP端口6789的应用程序;
- 什么也没收到,意味着SYN报文段可能被防火墙阻挡,无法到达目标主机。
TCP拥塞控制
拥塞控制是通过遏制发送方从而减少网络拥塞的服务,主要分为以下两种方法:
- 端到端拥塞控制:网络层没有为运输层提供显式支持,通过端系统对网络时行为的观察推断网络拥塞;
- 网络辅助的拥塞控制:路由器向发送方提供关于网络中拥塞状况的显式反馈信息。
TCP使用的是端到端拥塞控制,让每一个发送方根据所感知到的网络拥塞程度来提高或者降低发送速率,限制发送流量的行为主要通过拥塞窗口进行实现,表示为cwnd,发送方中未确认的数据量不会超过cwnd和rwnd的最小值(rwnd为接收窗口)。
TCP发送方通过丢包事件感知在与目的地之间的路径上出现的拥塞,即:出现超时,或收到3个冗余ACK,因为当出现过度拥塞时,路径上的一台或多台路由器的缓存会溢出,引起数据报被丢弃。
拥塞控制算法
一个报文段丢失意味着拥塞,此时应当降低发送方的速率;一个确认报文段表示网络正在向接收方交付发送方的报文段,此时能够增加发送方的速率;为探测拥塞开始时的速率,TCP发送方增加传输速率,发生拥塞时从该速率后退,进而再次开始探测。
TCP拥塞控制算法主要包括3个部分:
- 慢启动
- 拥塞避免
- 快速恢复
其中慢启动和拥塞避免是TCP的强制部分,快速恢复是推荐部分。
慢启动
TCP连接开始时,cwnd的值通常初始置为一个MSS的较小值,为了快速找到可用带宽的数量,cwnd的值以一个MSS开始,并且每当传输的报文被首次确认,即每过一个RTT就翻番。
如果出现了超时指示的丢包事件,发送方结束慢启动,具体有3种做法:
- 将cwnd设置为1并重新开始慢启动过程,并将慢启动阈值(ssthresh) 设置为cwnd / 2;
- 直接与ssthresh的值相关联,当cwnd的值等于ssthresh时,结束慢启动并将TCP转移到拥塞避免模式;
- 如果检测到3个冗余ACK,TCP执行快速重传并进入快速恢复状态;
拥塞避免
一旦进入拥塞避免状态,cwnd的值大约是上次遇到拥塞时的一半,此时不再每过一个RTT就使cwnd翻番,而是增加一个MSS;当出现超时,cwnd被设置为1个MSS;当出现丢包时,ssthresh的值被更新为cwnd的一半。接下来进入快速恢复状态;
快速恢复
对于引起TCP进入快速恢复状态的缺失报文段,对收到的每个冗余ACK,cwnd的值增加一个MSS,当对丢失报文段的一个ACK到达时,TCP在降低cwnd后进入拥塞避免状态;如果出现超时事件,快速回复在执行慢启动或拥塞避免后迁移到慢启动状态;当出现丢包事件,cwnd的值被设为1个MSS,ssthresh的值被设为cwnd的一半。
TCP拥塞控制总结
TCP拥塞控制:每个RTT内线性增加1MSS,出现3个冗余ACK时cwnd减半,即加性增、乘性减。