DSLBQ'S_BLOG

分类: 网络

  • 交换机

    交换机

    介绍

    本节介绍交换机的帧转发技术,MAC地址表的维护方式,三种帧转发模式,以及冲突域和广播域。

    更多信息

    帧转发:

    网络及电信中的交换概念

    以太网上的帧包含源MAC地址与目的MAC地址。交换机从源设备接收到帧并快速发往目的地址。交换的基本概念指基于以下两条准则做出决策的设备:

    • 进入(ingress)端口
    • 目的地址

    术语ingress用于描述帧通过特定端口进入设备,egress用于描述设备通过特定端口离开设备。交换机做出转发决定的时候,是基于进入端口以及消息的目的地址的。

    LAN交换机维护一张表,通过这张表决定如何转发数据流。LAN交换机唯一智能部分是利用这张表基于消息的进入端口和目的地址来转发。一个LAN交换机中只有一张定义了地址和端口的主交换表;因此,无论进入端口如何,同一目的地址的消息永远从同一出口离开。

    MAC地址表的动态更新

    一个交换机要知道使用哪一个端口传送帧,首先必须学习各端口有哪些设备。随着交换机学习到端口与设备的关系,它建立起一张MAC地址表,或内容可寻址寄存表(CAM)。CAM是一种应用于高速查找应用的特定类型的memory。交换机将连接到它的端口的设备的MAC地址记录到MAC表中,然后利用表中信息将帧发送至输出端口设备,该端口已指定给该设备。

    记住交换机操作模式的一句简单的话是:交换机学习“源地址”,基于“目的地址”转发。帧进入交换机时,交换机“学习”接收帧的源MAC地址,并将此地址添加到MAC地址表中,或刷新已存在的MAC地址表项的老化寄存器;后续报文如果去往该MAC地址,则可以根据此表项转发。帧转发时,交换机检查目的MAC地址并与MAC地址表中地址进行比较。如果地址在表中,则转发至表中与MAC地址相对应的端口。如果没有在表中找到目的MAC地址,交换机会转发到除了进入端口以外的所有端口泛洪(flooding)。有多个互连交换机的网络中,MAC地址表对于一个连接至其他交换机的端口记录多个MAC地址。

    以下步骤描述了更新MAC地址表的方法:

    1. 交换机在port 1接收到来自PC 1的帧。

    2. 交换机检查源MAC地址并与MAC地址表相比较。

    • 如果地址不在表中,则交换机在MAC地址表中将PC 1的源MAC地址关联到进入端口(port 1)。
    • 如果已经存在该源地址的MAC地址表项,则交换机重置老化计时器。通常一个表项会保持5分钟。

    3. 交换机记录源地址信息之后,检查目的地址

    • 如果目的MAC地址不在表项中或如果它是一个广播MAC地址,则交换机把该帧泛洪(flood)至除了进入端口以外的所有端口。

    4. 目标设备(PC 3)返回目的地址为PC 1的单播帧。

    5. 交换机地址表中输入PC 3的源MAC地址以及进入端口的端口号。在表项中找到该帧的目的地址及关联的输出端口。

    6. 交换机现在可以在源和目标设备之间传送帧而无需泛洪,因为地址表中已有指定关联端口的表项。

    交换机转发方式:

    存储转发交换(Store-and-Forward)

    运行在存储转发模式下的交换机在发送信息前要把整帧数据读入内存并检查其正确性。尽管采用这种方式比采用直通方式更花时间,但采用这种方式可以存储转发数据,从而保证其准确性。由于运行在存储转发模式下的交换机不传播错误数据,因而更适合大型局域网。存储转发模式有两大主要特征区别于直通转发模式:

    差错控制:

    使用存储转发技术的交换机对进入帧进行差错控制。在进入端口接收完整一帧之后,交换机将数据报最后一个字段的帧校验序列(frame check sequence, FCS)与自己的FCS进行比较。FCS校验过程用以帮助确保帧没有物理及数据链路错误,如果该帧校验正确,则交换机转发。否则,丢弃。

    自动缓存:

    存储转发交换机通过进入端口缓存,支持不同速率以太网的混合连接。例如,接收到一个以1Gb/s速率发出的帧,转发至百兆以太网端口,就需要使用存储转发方式。当进入与输出端口速率不匹配时,交换机将整帧内容放入缓存中,计算FCS校验,转发至输出缓存之后将帧发出。

    Cisco的主要交换方式是存储转发交换。

    直通交换(Cut-Through)

    直通交换的一个优势是比存储转发技术更为快速。采用直通模式的交换机会在接收完整个数据包之前就读取帧头,并决定把数据发往哪个端口。不用缓存数据也不用检查数据的完整性。这种交换方式有两大特点:快速帧转发以及无效帧处理。

    快速帧转发:

    如下图所示,一旦交换机在MAC地址表中查找到目的MAC地址,就立刻做出转发决定。而无需等待帧的剩余部分进入端口再做出转发决定。

    使用直通方式的交换机能够快速决定是否有必要检查帧头的更多部分,以针对额外的过滤目的。例如,交换机可以检查前14个字节(源MAC地址,目的MAC,以太网类型字段),以及对之后的40字节进行检查,以实现IPv4三层和四层相关功能。

    无效帧处理:

    对于大多数无效帧,直通方式交换机并不将其丢弃。错误帧被转发至其他网段。如果网络中出现高差错率(无效帧),直通交换可能会对带宽造成不利影响,损坏以及无效帧会造成带宽拥塞。在拥塞情况下,这种交换机必须像存储转发交换机那样缓存。

    无碎片转发(Fragment Free)

    无碎片转发是直通方式的一种改进模式。交换机转发之前检查帧是否大于64字节(小于则丢弃),以保证没有碎片帧。无碎片方式比直通方式拥有更好的差错检测,而实际上没有增加延时。它比较适合于高性能计算应用,即进程到进程延时小于10毫秒的应用场景。

    交换机域:

    交换机比较容易混淆的两个术语是冲突域和广播域。这一段讲述这两个影响LAN性能的重要概念。

    冲突域

    设备间共享同一网段称为冲突域。因为该网段内两个以上设备同时尝试通讯时,可能发生冲突。使用工作在数据链路层的交换机可将各个网段的冲突域隔离,并减少竞争带宽的设备数量。交换机的每一个端口就是一个新的网段,因为插入端口的设备之间无需竞争。结果是每一个端口都代表一个新的冲突域。网段上的设备可以使用更多带宽,冲突域内的冲突不会影响到其他网段,这也成为微网段。

    如下图所示,每一个交换机端口连接到一台主机,每一个交换机端口代表一个隔离的冲突域。

    广播域

    尽管交换机按照MAC地址过滤大多数帧,它们并不能过滤广播帧。LAN上的交换机接收到广播包后,必须对所有端口泛洪。互连的交换机集合形成了一个广播域。网络层设备如路由器,可隔离二层广播域。路由器可同时隔离冲突和广播域。

    当设备发出二层广播包,帧中的目的MAC地址被设置为全二进制数,广播域中的所有设备都会接收到该帧。二层广播域也称为MAC广播域。MAC广播域包含LAN上所有接收到广播帧的设备。广播通信比较多时,可能会带来广播风暴。特别是在包含不同速率的网段,高速网段产生的广播流量可能导致低速网段严重拥挤,乃至崩溃。

  • 网络传输

    网络传输

    首先来看一个例子:

    示例:网络服务器向客户端传送数据的过程:

    在详细阐述网络传输过程之前,先来看一个最常见的例子,下图显示了一个网络服务器向客户端传送数据的完整过程:

    数据封装

    消息要在网络中传输,必须对它进行编码,以特定的格式进行封装,同时需要适当地封装以足够的控制和地址信息,以使它能够从发送方移动到接收方。

    消息大小

    理论上,视频或邮件信息是能够以大块非中断型流从网络源地址传送到目的地址,但这也意味着同一时刻同一网络其他设备就无法收发消息。这种大型数据流会造成显著延时。并且,如果传输过程中连接断开,整个数据流都会丢失需要全部重传。因此更好的方法是将数据流分割(segmentation)为较小的,便于管理的片段,能够带来两点好处:

    • 发送较小片段,网络上同时可有多个会话交错进行。这种在网络上将不同会话片段交错进行的过程称为多路传输(multiplexing)。
    • 分割可提高网络通讯的可靠性。各消息片段从源地址到目的地址无需经过相同路径,如果一条路径被堵塞或断开,其余消息可从替换路径到达目的地址。如果部分消息到不了目的地址,那只需重传丢失部分。

    通过对片段打上标签的方式来保证顺序以及在接收时重组。

    协议数据单元(Protocol Data Unit, PDU)

    应用层数据在传输过程中沿着协议栈传递,每一层协议都会向其中添加信息。这就是封装的过程。

    数据片段在各层网络结构中采用的形式就称为协议数据单元(PDU)。封装过程中,下一层对从上一层收到的PDU进行封装。在处理的每一个阶段PDU都有不同的名字来反应它的功能。

    PDU按照TCP/IP协议的命名规范:

    • 数据(Data):应用层PDU的常用术语
    • 分段(Segment):传输层PDU
    • 帧(Frame):网络层PDU
    • 比特(Bits):在介质上物理传输数据所使用的PDU。

    封装

    封装是指在传输之前为数据添加额外的协议头信息的过程。在绝大多数数据通信过程中,源数据在传输前都会封装以数层协议。在网络上发送消息时,主机上的协议栈从上至下进行操作。

    以网络服务器为例,HTTP应用层协议发送HTML格式网页数据到传输层,应用层数据被分成TCP分段。各TCP分段被打上标签,称为头(header),表明接收方哪一个进程应当接收此消息。同时也包含使得接收方能够按照原有的格式来重组数据的信息。

    传输层将网页HTML数据封装成分段并发送至网络层,执行IP层协议。整个TCP分段封装成IP报文,也就是再添上IP头标签。IP头包括源和目的IP地址,以及发送报文到目的地址所必须的信息。

    之后,IP报文发送到接入层,封装以帧头和帧尾。每个帧头都包含源和目的物理地址。物理地址唯一指定了本地网络上的设备。帧尾包含差错校正信息。最后,由服务器网卡将比特编码传输给介质。

    解封装

    接收主机以相反的方式进行操作称为解封装。解封装是接收设备移除一层或多层协议头的过程。数据在协议栈中向上移动直到终端应用层伴随着解封装。

    访问本地资源:

    访问本地网络资源需要两种类型的地址:网络层地址和数据链路层地址。网络层和数据链路层负责将数据从发送设备传输至接收设备。两层协议都有源和目的地址,但两种地址的目的不同。

    示例:客户端PC1与FTP在同一IP网络的通信

    网络地址

    网络层地址或IP地址包含两个部分:网络前缀和主机。路由器使用网络前缀部分将报文转发给适当的网络。最后一个路由器使用主机部分将报文发送给目标设备。同一本地网络中,网络前缀部分是相同的,只有主机设备地址部分不同。

    源IP地址:发送设备,即客户端PC1的IP地址:192.168.1.110
    目的IP地址:接收设备,即FTP服务器:192.168.1.9

    数据链路地址

    数据链路地址的目的是在同一网络中将数据链路帧从一个网络接口发送至另一个网络接口。以太网LAN和无线网LAN是两种不同物理介质的网络示例,分别有自己的数据链路协议。

    当IP报文的发送方和接收方位于同一网络,数据链路帧直接发送到接收设备。以太网上数据链路地址就是以太网MAC地址。MAC地址是物理植入网卡的48比特地址。

    源MAC地址:发送IP报文的PC1以太网卡MAC地址,AA-AA-AA-AA-AA-AA。
    目的MAC地址:当发送设备与接收设备位于同一网络,即为接收设备的数据链路地址。本例中,FTP MAC地址:CC-CC-CC-CC-CC-CC。

    源和目的MAC地址添加到以太网帧中。

    MAC与IP地址

    发送方必须知道接收方的物理和逻辑地址。发送方主机能够以多种方式学习到接收方的IP地址:比如域名系统(Domain Name System, DNS),或通过应用手动输入,如用户指定FTP地址。

    以太网MAC地址是怎么识别的呢?发送方主机使用地址解析协议(Address Resolution Protocol, ARP)以检测本地网络的所有MAC地址。如下图所示,发送主机在整个LAN发送ARP请求消息,这是一条广播消息。ARP请求包含目标设备的IP地址,LAN上的每一个设备都会检查该ARP请求,看看是否包含它自身的IP地址。只有符合该IP地址的设备才会发送ARP响应。ARP响应包含ARP请求中IP地址相对应的MAC地址。

    访问远程资源:

    默认网关

    当主机发送消息到远端网络,必须使用路由器,也称为默认网关。默认网关就是位于发送主机同一网络上的路由器的接口IP地址。有一点很重要:本地网络上的所有主机都能够配置自己的默认网关地址。如果该主机的TCP/IP设置中没有配置默认网关地址,或指定了错误的默认网关地址,则远端网络消息无法被送达。

    如下图所示,LAN上的主机PC 1使用IP地址为192.168.1.1的R1作为默认网关,如果PDU的目的地址位于另一个网络,则主机将PDU发送至路由器上的默认网关。

    与远端网络设备通讯

    下图显示了客户端主机PC 1与远端IP网络服务器进行通讯的网络层地址与数据链路层地址:

    网络地址

    当报文的发送方与接收方位于不同网络,源和目的IP地址将会代表不同网络上的主机。

    源IP地址:发送设备即客户端主机PC 1的IP地址:192.168.1.110。
    目的IP地址:接收设备即网络服务器的IP地址:172.16.1.99。

    数据链路地址

    当报文的发送方与接收方位于不同网络,以太网数据链路帧无法直接被发送到目的主机。以太网帧必须先发送给路由器或默认网关。本例中,默认网关是R1,R1的接口IP地址与PC 1属于同一网络,因此PC 1能够直接达到路由器。

    源MAC地址:发送设备即PC 1的MAC地址,PC1的以太网接口MAC地址为:AA-AA-AA-AA-AA-AA。
    目的MAC地址:当报文的发送方与接收方位于不同网络,这一值为路由器或默认网关的以太网MAC地址。本例中,即R1的以太网接口MAC地址,即:11-11-11-11-11-11。

    IP报文封装成的以太网帧先被传输至R1,R1再转发给目的地址即网络服务器。R1可以转发给另一个路由器,如果目的服务器所在网路连接至R1,则直接发送给服务器。

    发送设备如何确定路由器的MAC地址?每一个设备通过自己的TCP/IP设置中的默认网关地址得知路由器的IP地址。之后,它通过ARP来得知默认网关的MAC地址,该MAC地址随后添加到帧中。

  • TCP窗口调整与流控

    TCP窗口调整与流控

    介绍

    在客户端与服务器的连接中,客户端告知服务器它一次希望从服务器接收多少字节数据,这是客户端的接收窗口,即服务器的发送窗口。类似地,服务器告知客户端一次希望从客户端接收多少字节数据,也就是服务器的接收窗口和客户端的发送窗口。

    要理解为什么窗口大小会产生波动,首先需要理解它的含义。最简单的方式是它代表了设备对于特定连接的接收缓存大小。即,窗口大小代表一个设备一次能够从对端处理多少数据,之后再传递给应用层处理。

    更多信息

    当服务器从客户端接收数据,它就将数据放在缓存中,服务器必须对数据做以下两步操作:

    确认:服务器必须将确认信息发回客户端以表明数据接收。
    传输:服务器必须处理数据,将它传递给目标应用程序处理

    区分开这两件事情是非常重要的。关键在于基本的滑动窗口机制中,数据于接收时确认,但并不一定立即从缓存中传输出去。也就意味着当接收数据速度快于接收TCP处理速度时,缓存有可能被填满。当这一情况发生时,接收设备需要调整窗口大小已防止缓存过载。

    由于窗口大小能够以这种方式管理连接两端设备数据流的速率,TCP就是以这种方式实现流控这一传输层非常典型的任务。流控对于TCP来说是很重要的,因为它是设备间互通状态的方式。通过增加或缩小窗口大小,服务器和客户端能够确保对端发送数据的速度等同于处理速度。

    减小窗口大小以降低发送速率:

    首先看一下客户端到服务器的数据传输,如下图所示:

    客户端传输140字节数据至服务器。之后,客户端的可用窗口还剩下220字节:发送窗口的360字节减去发送的140字节。

    一段时间过后,服务器接收到140字节并将它们放在缓存中。现在,理想的情况下,140字节进入缓存,确认之后立刻从缓存移出。也就是说,缓存有足够的大小来容纳客户端发送的所有数据。缓存的空闲空间维持在360字节,因此告知客户端窗口大小保持不变。

    只要服务器处理速度和数据进入速度相同,窗口大小就会保持在360字节。客户端在接收到140字节的确认信息以及窗口大小保持不变的信息之后,将360字节窗口向右移动140字节。由于现在未确认字节数为0,因此客户端又可以发送360字节数据。对应于之前可用窗口的220字节,加上刚刚确认的140字节数据。

    然而,现实中服务器可能需要处理数十,数百乃至数千个TCP连接。TCP可能无法立刻处理数据,或应用应用程序本身无法接收140字节数据。任何一种情况下,服务器TCP都无法立刻将140字节从缓存中移出。这时,除了发回确认信息给客户端以外,服务器会想要告知客户端更改窗口大小,以表示缓存已经被部分写入了。

    假设我们接收到140字节,但只能发送40字节给应用程序,缓存中剩下100字节。当发送140字节的确认信息,服务器将发送窗口缩小100字节,至260字节。当客户端从服务器接收到这一片段,它将会看到140字节的确认信息并将窗口向右滑动140字节。在滑动过程中,将大小缩减至260字节。可以认为将窗口左端滑动140字节,但右端仅滑动40字节。新的稍小一些的窗口保证服务器从客户端接收最多260字节数据,以适应接收缓存中的剩余空间,如下图的1-3步所示:

    缩减发送窗口以停止发送新数据:

    如果服务器无法接收任何新数据会怎么样呢?假设客户端下一次传输180字节,但是服务器太忙碌而无法对其进行处理。这种情况下,服务器将这180字节缓存下来,并且在确认信息中,将窗口大小从260字节缩减为80字节。当客户端接收到180字节的确认信息,它也会看到窗口缩减了180字节,它会滑动与缩减同样的大小,告知服务器:我确认接收180字节数据,但不允许你再发送新的数据。也可以看作窗口左端滑动180字节,但右端维持不动。只要右端不移动,客户端就无法发送更多数据。这一过程显示在上图的4-6中。

    关闭发送窗口:

    窗口调整可以通过双方设备来完成。如果服务器从客户端接收的数据持续快于推送给应用的速率,则服务器将会继续减小接收窗口。假设发送窗口减小至80字节,客户端发送第三个请求,长度为80字节,但服务器仍处于繁忙状态。之后服务器将窗口减小为0,也称为关闭窗口。这一信息告知客户端服务器已经过载,它需要彻底停止发送数据,如上图最后一步所示。之后,当服务器负载减轻时,可以再次增加这一连接的窗口,允许更多数据传输。

  • TCP确认机制

    TCP确认机制

    介绍

    在TCP确认机制中,无法有效处理非连续TCP片段。确认号表明所有低于该编号的sequence number已经被发送该编号的设备接收。如果我们收到的字节数落在两个非连续的范围内,则无法只通过一个编号来确认。这可能导致潜在严重的性能问题,特别是高速或可靠性较差的网络。

    更多信息

    还是以下图为例,服务器发送了4个片段并收到1条回复,确认号为201。因此,片段1和片段2被当成已确认。它们从重传队列中移出,同时允许服务器发送窗口向右移动200字节,从而发送数据增加200个字节。

    然而,再次假设片段3,从sequence number201开始,在发送过程中丢失了。由于客户端从没有收到这一片段,所以它也无法发送确认号高于201的确认信息,从而导致滑动窗口停滞。服务器可以继续发送其他片段直到填满客户端的接收窗口,但是直到客户端发送另一条确认信息,服务器的发送窗口都不会滑动。

    另一个问题是如果片段3丢失了,客户端将无法告知服务器是否收到后续的片段。在客户端接收窗口填满之前,很有可能客户端已经接收到片段4以及之后的片段。但是客户端无法发送值为501的确认信息以表明接收到片段4,因为这意味着片段3也接收到了。

    这里我们看到了TCP单编号,累积确认机制的缺点。我们可以想象一个最差的情况,服务器被告知它有一个10,000字节窗口,20个片段每个片段500字节。第一个片段丢失了,其他19个被接收到了。但是由于第一个片段从没有接收到,其他19个也无法确认。

    未确认片段处理策略:

    我们怎样处理丢失片段之后的片段呢?本例中,当服务器片段3重传超时,它必须决定怎样处理片段4,它不知道客户端是否已经接收到。在上述最差情况下,第一个片段丢失后,其余19个可能或可能无法被客户端接收到。

    处理这种情况有两种可能的方式:

    仅重传超时片段:这是一种更加保守的方式,仅重传超时的片段,希望其他片段都能够成功接收。如果该片段之后的其他片段实际上接收到了,这一方式是最佳的,如果没接收到,就无法正常执行。后者的情况每一个片段需要单独计时并重传。假设上述最坏情况下,所有20个500字节片段都丢失了。我们需要等片段1超时并重传。这一片段也许会得到确认,但之后我们需要等待片段2超时并重传。这一过程会重复多次。

    重传所有片段:这是一种更激进或者说更悲观的方式。无论何时一个片段超时了,不仅重传该片段,还有所有其他尚未确认的片段。这一方式确保了任何时间都有一个等待确认的停顿时间,在所有未确认片段丢失的情况下,会刷新全部未确认片段,以使对端设备多一次接收机会。在所有20个片段都丢失的情况下,相对于第一种方式节省了大量时间。这种方式的问题在于可能这些重传是不必要的。如果第一个片段丢失而其他19个实际上接收到了,也得重传那9500字节数据。

    由于TCP不知道其他片段是否接收到,所以它也无法确认哪种方法更好,但只能选择一种方式。上图示例了保守的方式,而下图显示的是激进的方式:

    问题的关键在于无法确认非连续片段。解决方式是对TCP滑动窗口算法进行扩展,添加允许设备分别确认非连续片段的功能。这一功能称为选择确认(selective acknowledgment,SACK)。

    选择确认:

    通过SACK,连接的两方设备必须同时支持这一功能,通过连接时使用的SYN片段来协商是否允许SACK。这一过程完成之后,任一设备都可以在常规TCP片段中使用SACK选项。这一选项包含一个关于已接收但未确认片段数据sequence number范围的列表,由于它们是非连续的。

    各设备对重传队列进行修改,如果该片段已被选择确认过,则该片段中的SACK比特位置为1。该设备使用图2中激进方式的改进版本,一个片段重传之后,之后所有片段也会重传,除非SACK比特位为1。

    例如,在4个片段的情况下,如果客户端接收到片段4而没有接收到片段3,当它发回确认号为201(片段1和片段2)的确认信息,其中包含一个SACK选项指明:“已接收到字节361至500,但尚未确认”。如果片段4在片段1和2之后到达,上述信息也可以通过第二个确认片段来完成。服务器确认片段4的字节范围,并为片段4打开SACK位。当片段3重传时,服务器看到片段4的SACK位为1,就不会对其重传。如下图所示。

    在片段3重传之后,片段4的SACK位被清除。这是为了防止客户端出于某种原因改变片段4已接收的想法。客户端应当发送确认号为501或更高的确认信息,正式确认片段3和4接收到。如果这一情况没有发生,服务器必须接收到片段4的另一条选择确认信息才能将它的SACK位打开,否则,在片段3重传时或计时器超时的情况下会对其自动重传。

  • TCP重传

    TCP重传

    介绍

    TCP的主要任务是很简单:打包和发送数据。TCP与其他协议的不同之处在于使用滑动窗口来管理基本数据收发过程,同时确保数据流的有效及可靠传输,从而不致发送速率明显快于接收速率。本文将描述TCP是如何确保设备可靠、有效地进行传输的。首先阐述TCP检测丢失片段以及重传的基本方法,之后介绍TCP如何判断一个片段为丢失片段。

    更多信息

    TCP片段重传计时器以及重传队列:

    检测丢失片段并对之重传的方法概念上是很简单的。每一次发送一个片段,就开启一个重传计时器。计时器有一个初始值并随时间递减。如果在片段接收到确认之前计时器超时,就重传片段。TCP使用了这一基本技术,但实现方式稍有不同。原因在于为了提高效率需要一次处理多个未被确认的片段,以保证每一个在恰当的时间重传。TCP按照以下特定顺序工作:

    放置于重传队列中,计时器开始 包含数据的片段一经发送,片段的一份复制就放在名为重传队列的数据结构中,此时启动重传计时器。因此,在某些时间点,每一个片段都会放在队列里。队列按照重传计时器的剩余时间来排列,因此TCP软件可追踪那几个计时器在最短时间内超时。

    确认处理 如果在计时器超时之前收到了确认信息,则该片段从重传队列中移除。

    重传超时 如果在计时器超时之前没有收到确认信息,则发生重传超时,片段自动重传。当然,相比于原片段,对于重传片段并没有更多的保障机制。因此,重传之后该片段还是保留在重传队列里。重传计时器被重启,重新开始倒计时。如果重传之后没有收到确认,则片段会再次重传并重复这一过程。在某些情况下重传也会失败。我们不想要TCP永远重传下去,因此TCP只会重传一定数量的次数,并判断出现故障终止连接。

    但是我们怎样知道一个片段被完全确认呢?重传是基于片段的,而TCP确认信息是基于序列号累积的。每次当设备A发送片段给设备B,设备B查看该片段的确认号字段。所有低于该字段的序列号都已经被设备A接收了。因此,当片段中所发送的所有字节的序列号都比设备A到设备B的最后一个确认号小的时候,一个从设备B发到设备A的片段被认为是确认了。这是通过计算片段中最后一个序列号结合片段的数据字段来实现的。

    让我们以下图为例来说明一下确认和重传是怎样工作的。假设连接中的服务器发出了四个连续片段(号码从1开始)

    片段1 序列号字段是1片段长度80。所以片段1中最后一个序列号是80。
    片段2 序列号是81片段长度是120。片段2中最后一个序列号是200。
    片段3 序列号是201片段长度是160。片段3中最后一个序列号是360。
    片段4 序列号是361片段长度是140。片段3中最后一个序列号是500。

    这些片段是一个接一个发送的,而无需等待前一个发送得到确认。这是TCP滑动窗口的一个主要优势

    假设客户端接收到前两个传输,它会发回一条确认消息确认号为201。从而告知服务器前两个片段已经被客户端成功接收了,它们从重传队列中移除(并且服务器发送窗口右移200字节)。在接收到确认号361或更高的片段之前,片段3会保留在重传队列中;片段4需要确认号501或更高。

    现在,让我们进一步假设传输过程中片段3丢失了,但片段4被接收到了。客户端将片段4保存在接收buffer中,但是不需要确认,因为TCP是累积确认机制——确认片段4表示片段3也接收到了,但实际上并没有。因此,客户端需要等待片段3。实际上,服务器端片段3的重传计时器会超时,服务器之后重传片段3。之后客户端收到,然后发送片段3和4的确认信息给服务器。

    还有一个重要的问题,服务器将如何处理片段4呢?虽然客户端在等待片段3,服务器没有收到反馈,所以它并不知道片段3丢失了,同样它也不知道片段4发生了什么(以及接下来传输的数据)。很有可能客户端已经接收到了片段4但是不能确认,也有可能片段4也丢失了。一些实现中会选择仅仅重传片段3,也有些会把3和4都重传。

    最后一个问题是重传队列中所使用片段重传计时器的值。如果设置过低,会发生过量重传,如果设置过高,重传丢失片段会减弱性能。必须通过一个称为自适应重传的过程来动态调整这个值。

  • TCP滑动窗口

    TCP滑动窗口

    介绍

    将TCP与UDP这样的简单传输协议区分开来的是它传输数据的质量。TCP对于发送数据进行跟踪,这种数据管理需要协议有以下两大关键功能:
    可靠性:保证数据确实到达目的地。如果未到达,能够发现并重传。
    数据流控:管理数据的发送速率,以使接收设备不致于过载。
    要完成这些任务,整个协议操作是围绕滑动窗口确认机制来进行的。因此,理解了滑动窗口,也就是理解了TCP。

    更多信息

    TCP面向流的滑动窗口确认机制:

    TCP将独立的字节数据当作流来处理。一次发送一个字节并接收一次确认显然是不可行的。即使重叠传输(即不等待确认就发送下一个数据),速度也还是会非常缓慢。

    TCP消息确认机制如上图所示,首先,每一条消息都有一个识别编号,每一条消息都能够被独立地确认,因此同一时刻可以发送多条信息。设备B定期发送给A一条发送限制参数,制约设备A一次能发送的消息最大数量。设备B可以对该参数进行调整,以控制设备A的数据流。为了提高速度,TCP并没有按照字节单个发送而是将数据流划分为片段。片段内所有字节都是一起发送和接收的,因此也是一起确认的。确认机制没有采用message ID字段,而是使用的片段内最后一个字节的sequence number。因此一次可以处理不同的字节数,这一数量即为片段内的sequence number。

    TCP数据流的概念划分类别

    假设A和B之间新建立了一条TCP连接。设备A需要传送一长串数据流,但设备B无法一次全部接收,所以它限制设备A每次发送分段指定数量的字节数,直到分段中已发送的字节数得到确认。之后,设备A可以继续发送更多字节。每一个设备都对发送,接收及确认数据进行追踪。

    如果我们在任一时间点对于这一过程做一个“快照”,那么我们可以将TCP buffer中的数据分为以下四类,并把它们看作一个时间轴:

    1. 已发送已确认 数据流中最早的字节已经发送并得到确认。这些数据是站在发送设备的角度来看的。如下图所示,31个字节已经发送并确认。
    2. 已发送但尚未确认 已发送但尚未得到确认的字节。发送方在确认之前,不认为这些数据已经被处理。下图所示14字节为第2类。
    3. 未发送而接收方已Ready 设备尚未将数据发出,但接收方根据最近一次关于发送方一次要发送多少字节确认自己有足够空间。发送方会立即尝试发送。如图,第3类有6字节。
    4. 未发送而接收方Not Ready 由于接收方not ready,还不允许将这部分数据发出。

    接收方采用类似的机制来区分已接收并已确认,尚未接受但准备好接收,以及尚未接收并尚未准备好接收的数据。实际上,收发双方各自维护一套独立的变量,来监控发送和接收的数据流落在哪一类。

    Sequence Number设定与同步:

    发送方和接收方必须就它们将要为数据流中的字节指定的sequence number达成一致。这一过程称为同步,在TCP连接建立时完成。为了简化假设第一个字节sequence number是1,按照上图示例,四类字节如下:

    1. 已发送已确认字节1至31。
    2. 已发送但尚未确认字节32至45。
    3. 未发送而接收方已Ready字节46至51。
    4. 未发送而接收方Not Ready字节52至95。

    发送窗口与可用窗口:

    整个过程关键的操作在于接收方允许发送方一次能容纳的未确认的字节数。这称为发送窗口,有时也称为窗口。该窗口决定了发送方允许传送的字节数,也是2类和3类的字节数之和。因此,最后两类(接收方准备好而尚未发送,接收方未准备好)的分界线在于添加了从第一个未确认字节开始的窗口。本例中,第一个未确认字节是32,整个窗口大小是20。

    可用窗口的定义是:考虑到正在传输的数据量,发送方仍被允许发送的数据量。实际上等于第3类的大小。左边界就是窗口中的第一个字节(字节32),右边界是窗口中最后一个字节(字节51)。概念的详细解释看下图。

    可用窗口字节发送后TCP类目与窗口大小的改变:
    当上图中第三类的6字节立即发送之后,这6字节从第3类转移到第2类。字节变为如下:

    1. 已发送已确认字节1至31。
    2. 已发送但尚未确认字节32至51。
    3. 未发送而接收方已Ready字节为0。
    4. 未发送而接收方Not Ready字节52至95。

    确认处理以及窗口缩放:

    过了一段时间,目标设备向发送方传回确认信息。目标设备不会特别列出它已经确认的字节,因为这会导致效率低下。目标设备会发送自上一次成功接收后的最长字节数。

    例如,假设已发送未确认字节(32至45)分为4段传输:32-34,35-36,37-41,42-45。第1,2,4已经到达,而3段没有收到。接收方只会发回32-36的确认信息。接收方会保留42-45但不会确认,因为这会表示接收方已经收到了37-41。这是很必要的,因为TCP的确认机制是累计的,只使用一个数字来确认数据。这一数字是自上一次成功接收后的最长字节数。假设目标设备同样将窗口设为20字节。

    当发送设备接收到确认信息,则会将一部分第2类字节转移到第1类,因为它们已经得到了确认。由于5个字节已被确认,窗口大小没有改变,允许发送方多发5个字节。结果,窗口向右滑动5个字节。同时5个字节从第二类移动到第1类,5个字节从第4类移动至第3类,为接下来的传输创建了新的可用窗口。因此,在接收到确认信息以后,看起来如下图所示。字节变为如下:

    1. 已发送已确认字节1至36。
    2. 已发送但尚未确认字节37至51。
    3. 未发送而接收方已Ready字节为52至56。
    4. 未发送而接收方Not Ready字节57至95。

    每一次确认接收以后,这一过程都会发生,从而让窗口滑动过整个数据流以供传输。

    处理丢失确认信息:

    但是丢失的42-45如何处理呢?在接收到第3段(37-41)之前,接收设备不会发送确认信息,也不会发送这一段之后字节的确认信息。发送设备可以将新的字节添加到第3类之后,即52-56。发送设备之后会停止发送,窗口停留在37-41。

    TCP包括一个传输及重传的计时机制。TCP会重传丢失的片段。但有一个缺陷是:因为它不会对每一个片段分别进行确认,这可能会导致其他实际上已经接收到的片段被重传(比如42至45)。