TCP/IP详解 卷1:协议 学习笔记 第二十四章 TCP的未来和性能

虽然TCP在比以太网速率高的环境中也能正确运行,但在这些高速率环境下,TCP的某些限制被暴露出来。

路径MTU发现机制通常可以使TCP为非本地的连接使用大于536字节的MTU,从而增加吞吐量。

TCP处理长肥管道(带宽时延积很大的网络)时有局限性,为处理长肥管道,增加了两个TCP选项:窗口扩大选项(增大TCP的最大窗口,使之超过65535字节)、时间戳选项(使TCP对报文段的RTT进行更加精确的测量,还能在高速率下对可能发生的序号回绕提供保护)。

T/TCP是为了增加事务功能对TCP进行的修改,通信的事务模式以客户的请求将被服务器应答为主要特征,T/TCP目的是减少两端交换的报文段数量,避免三次握手和使用4个报文段进行连接的关闭,从而使客户可以在一个RTT和处理请求所必须的时间内收到服务器的应答。

以上新功能与现有的TCP实现兼容,有这些功能的新系统仍可与旧系统交互。除了需要为MTU发现机制在ICMP报文中增加一个额外字段外,其余功能只需在需要使用它们的端系统中实现即可。

路径MTU(两个主机间的路径上任何网络的最小MTU)发现机制通过在IP首部中设置不要分片DF比特实现,之后观察当前路径上的路由器是否需要对正在发送的IP数据报进行分片,如果需要分片,则路由器返回一个ICMP不可达的差错,某版本的traceroute程序使用这一机制发现到目的地的路径MTU。

TCP的路径MTU发现过程:
1.建立连接时,TCP使用输出接口的MTU或对端声明的MSS两者中的较小值作为起始的报文段大小,如果对端没有指定MSS,则其默认值为536字节。路径MTU发现机制不允许TCP发出超过对端声明的MSS大小的报文段。一个实现也可为每个路由单独保存路径MTU信息。
2.在该连接上的所有被TCP发送的IP数据报都被设置DF比特,如果某个中间路由器需要对一个设置了DF标志的数据报分片,该路由器就丢弃这个数据报,并产生一个ICMP不能分片差错。
3.发送端收到这个差错后,如果是较新的该类ICMP差错(其中含产生该差错的路由器的下一跳的MTU),则报文段大小被设置为ICMP中包含的下一跳的MTU减去IP和TCP的首部长度;如果是一个较旧的该类ICMP差错,则尝试下一个可能的最小MTU(即尝试下图中的下一个更小的MTU)。由这个ICMP差错引起重传时,拥塞窗口不需要变化,但要慢启动。
在这里插入图片描述
由于路由可以动态变化,在最后一次减少路径MTU一段时间以后,可以尝试使用一个较大的值(但要小于对面声明的MSS或输出接口MTU两者的较小值),RFC 1191推荐时间为10分钟。

非本地目的地的默认MSS通常为536字节,路径MTU发现机制可以避免在通过MTU小于576字节(这非常罕见)的中间链路时进行分片。为了使路径MTU更加充分地利用MTU大于576字节的广域网,实现必须停止为非本地对端指定536字节的MSS默认值,为非本地对端指定的MSS的较好选择是本端输出接口的MTU减去IP首部和TCP首部的大小,大多数实现允许系统管理员修改默认MSS值。

发现路径MTU的例子:
在这里插入图片描述
主机slip和solaris建立了一个连接,slip把接口的MTU设为552字节,而不像通常一样将其设为链路的MTU(上例中为296字节),这使得slip通告一个512字节的MSS,但SLIP链路的MTU实际为296字节,这会引起超过256字节的TCP报文段被分片,我们在solaris上运行sock程序作为客户端,并向slip上的丢弃服务器进行一个512字节的写操作:
在这里插入图片描述
以下是在sun的SLIP接口上收集的tcpdump的输出:
在这里插入图片描述
前两行建立连接时的MSS值是我们所期望的,第三行solaris发送了一个带有512字节数据的对SYN进行确认的报文段。第四行显示路由器bsdi产生了一个ICMP需要分片差错,这个是较新的包含bsdi下一跳的输出接口MTU的ICMP差错。在第四行的差错到达solaris之前,solaris就发送了FIN,由于slip主机没有接收到被丢弃的512字节数据,因此不期望接收此FIN报文段中的序号513,因此在第六行中用它所期望的序号1进行了响应,此时,ICMP差错返回到了solaris,solaris用两个256字节的报文段(第7、9行)重传了这512字节的数据,因为在bsdi后面可能还有具有更小MTU的路由器,因此solaris重发的两个报文段也设置了DF比特。

传统观点认为,在分组大小不足以引起分片时,越大的分组花费越少,即首部占比更小。但有人不同意此观点,如下例,通过4个路由器发送8192字节,每个路由器与一个T1电话线(544000b/s)相连,首先我们使用两个4096字节的分组:
在这里插入图片描述
问题在于路由器是存储转发设备,它们通常接收整个分组,检验包含IP检验和的IP首部,进行选路判决,然后发送输出分组,上图中假定在路由器中的操作不花费时间,计算从一个路由器到另一个路由器发送一个分组所需时间:
在这里插入图片描述
从上图可知,整个发送时间是4个单位时间,即85.6ms,每个链路空闲2个单位时间(42.8ms)。

当我们发送16个512字节的分组时:
在这里插入图片描述
此时每个单位时间为:
在这里插入图片描述
此时总时间为18*2.9=52.2ms,每个链路也空闲2个单位时间(5.8ms)。

上例中,我们忽略了ACK返回所需时间、建立和终止连接的时间、与其他报文共享链接的耗时。[Bellovin 1993]显示更大并不总是更好。我们需要在更多网络环境中做更多研究。

时延带宽积也可称其为两端的管道大小,此值越大,TCP的某些局限性就会暴露出来。
在这里插入图片描述
具有大的时延带宽积的网络被称为长肥网络(LFN,Long Fat Network),运行在LFN上的TCP连接被称为长肥管道,使用长肥管道会遇到很多问题:
1.TCP首部中窗口大小是16bit,从而将窗口大小限制在65535字节内。
2.在一个长肥网络内丢失的分组会使吞吐量急剧减少,如果有一个报文段丢失,需要使用快速重传和快速恢复算法避免管道中数据变得很少,即使使用了这些算法,在一个窗口内发生的多个分组丢失也会使管道中数据变得很少(慢启动又将它渐渐填满,但此过程需经过多个RTT)。RFC 1072中建议使用有选择的确认(SACK)来处理一个窗口发生的多个分组丢失,但这个功能在RFC 1323中被忽略了,因为作者觉得在把它纳入TCP前需要先解决一些技术上的问题。
3.许多TCP实现对每个窗口的RTT仅进行一次测量,在LFN上需要更好的RTT测量机制。
4.TCP对每一个字节用一个32bit无符号的序号进行标识,如果网络中有一个被延迟一段时间的报文段,它所在的连接已经释放,而一个新的连接在这两个主机之间又建立了,防止这个报文段再次出现的措施:
(1)IP首部中的TTL为每个IP段规定了一个生存时间的上限(255跳或255秒,看哪个上限先达到),推荐的最大报文段生存时间MSL值为2分钟,但许多实现使用的MSL为30秒。
(2)在LFN上,由于TCP序号空间是有限的,在传输了4294967296个字节后序号会被重用,由于每个IP报文段最多只生存MSL的时间,因此序号如果在此时间内没有发生回绕,接收端就不会把回绕前上一轮序号中的同样值当作本轮中的序号接收,但网络是否可能快到在不到一个MSL的时候序号就发生了回绕?在以太网上发生回绕通常需要60分钟左右,因此不会发生这种情况,但当带宽增加时,这个时间将减少,一个T3电话线(45Mb/s)在12分钟内会发生回绕,FDDI(100Mb/s)为5分钟,而一个千兆比特网络(1000Mb/s)则为34秒,此时这个问题不再是带宽时延乘积,而在于带宽本身。为解决此问题,可使用PAWS(Protection Against Wrapped Sequence numbers)算法保护回绕的序号,此算法使用到了TCP的时间戳选项。

时延和带宽之间的差别如下:发送一个100万字节的文件时,假定时延是30ms,下图中,上部分使用了一个1544000b/s的T1电话线,下部分使用了一个1Gb/s网络:
在这里插入图片描述
上图显示,在30ms后,两个网络中的第1个比特的数据都已到达对端,但对于T1网络,由于管道容量仅为5790字节,因此发送方仍然有994210个字节等待发送,而千兆比网络的容量为3750000字节,因此整个文件仅使用了25%左右的带宽,此时文件的最后一个比特已经到达第1个字节后的8ms处。

经过T1网络传输文件的总时间为5.211秒,如果增加更多的带宽,如使用一个T3网络(45000000b/s),则总时间减少到0.208秒,增加了约29倍带宽,总时间减小到约25分之一。

使用千兆比网络传输文件的总时间为0.038秒(30ms的时延+8ms的真正传输文件的时间),假定将带宽增加为2000Mb/s,我们只能将总时间减小为0.304ms,此时带宽加倍仅能将时间减少约10%,在千兆比速率下,时延限制占据了主要地位,带宽不再成为限制。

时延主要是由光速引起的,不能被减小。

窗口扩大选项能使TCP的通告窗口的最大值从65525增加到230(1Gb),这是通过定义一个选项实现对16bit的扩大操作来完成的,TCP首部仍然使用16bit窗口大小。

窗口扩大选项的移位计数器可取值0(没有扩大窗口)到14,最大值14表示的窗口大小为65535*214字节。

窗口扩大选项只能出现在一个SYN报文段中,当连接建立后,在每个方向上的扩大因子是固定的,主动建立连接的一方在其SYN中发送这个选项,被动建立连接的一方只有在收到带有这个选项的SYN后才能发送这个选项,两个方向上的扩大因子可以不同。

如果主动连接的一方发送一个非0的扩大因子,但没有从另一端收到一个窗口扩大选项,就将发送和接收的移位计数器置为0,这允许较新的系统能与较旧的、不理解新选项的系统进行互操作。

Host Requirements RFC要求TCP接受在任何报文段中的一个选项,忽略不理解的选项。

假定我们在使用窗口扩大选项,如果发送给对端的移位计数为S,接收到对端的移位计数为R,则我们收到对端的16bit的通告窗口时要将其左移R位以获得实际的通告窗口大小;我们向对端发送一个窗口通告时,我们将实际的32bit窗口大小右移S位,用它来替换TCP首部中的16bit值。

TCP根据接收缓存的大小自动选择移位计数,这个大小是由TCP设置的,但通常向应用进程提供了修改途径。

以下是在vangogh主机上与bsdi主机上的echo服务器建立两次连接来观察TCP计算窗口扩大因子的情况,第1个连接指定接收缓存为128000字节,第2个缓存为220000字节:
在这里插入图片描述
以下为这两个连接的tcpdump输出:在这里插入图片描述
第一行中,vangogh通告一个65535的窗口,并通过设置移位计数为1来指明窗口扩大选项,这个通告窗口是比我们接收缓存小的最大的可能值,因为在SYN段中,窗口字段不会缩放(因为还没有确定对方是否支持窗口扩大选项)。

vangogh发送的窗口扩大因子为1,意味着vangogh最大会通告131070字节的窗口大小,这与我们的接收缓存(128000)差不多大小。由于服务端bsdi在它的SYN中没有发送窗口扩大选项,因此这个选项没有被使用,vangogh在随后的连接阶段继续使用65535作为最大的可能窗口。

第二个连接vangogh的窗口扩大因子为2,表明它要发送的窗口通告大小最多为262140(65535*22)字节,这比我们的接收缓存大。

时间戳选项使发送方在每个报文段中放置一个时间戳值,接收方在确认中返回这个数值,从而允许发送方为每一个收到的ACK(此处是ACK而非报文段,因为TCP通常用一个ACK确认多个报文段)计算RTT。

许多实现为每一个窗口只计算一个RTT,这对于包含8个报文段的窗口而言是正确的,较大的窗口大小需要进行更好的RTT计算。通常RTT通过对一个数据信号(包含数据的报文段)以较低的频率(每个窗口一次)进行采样来计算被估计的RTT,如果一个窗口能容纳8个报文段,则计算被估计的RTT时,采样速率为数据速率的1/8,这可以忍受,但如果每个窗口中有100个报文段,采样速率变为数据速率的1/100,这将导致被估计的RTT不精确,从而引起不必要的重传,如果一个报文段被丢失,会使情况变得更糟。

包含时间戳选项的TCP首部长度将从正常的20字节增加到32字节(实际TCP时间戳选项有10字节,TCP首部长度必须是4字节的倍数,因此补两个字节)。

时间戳选项不需要两个主机间进行时钟同步。

时间戳是一个单调递增的值,RFC 1323推荐在1ms到1秒之间将时间戳的值加1,4.4 BSD在启动时将时间戳始终设置为0,然后每隔500ms将时间戳加1。

时间戳选项只有主动发起连接的一方在它的SYN中指定且从另一方的SYN中收到此选项后,该选项才会在以后的报文段中设置。

如果接收方发送一个ACK对多个报文段进行确认,那么哪一个时间戳应该放到回显应答字段发回去呢?TCP是一个对称的协议,允许数据在任何时间任何方向上传输,因此时间戳回显可能出现在任意方向上,为了简单和对称,我们假设时间戳总是会在两个方向上被发送和回显,为了效率,时间戳和时间戳回显字段都在一个TCP时间戳选项中:
在这里插入图片描述
如上如,时间戳选项中有两个4字节时间戳字段,时间戳值字段(TSval)是TCP发送此选项时时间戳时钟(如前所述,这个时间戳时钟每1ms到1秒之间将时间戳的值加1)的当前值。

时间戳回显应答字段(TSerc)只有当TCP头部中ACK位被设置时才生效,如果TSerc是有效的,它的值是之前对端TCP发送的带时间戳选项报文的TSval字段值,且该值通常来自最新收到的带时间戳选项的报文;如果TSerc是无效的,它的值必须设为0。

此算法这样处理以下情况:
1.如果ACK被接收方迟延,则作为回显值的时间戳值应对应于最早被确认的报文段。如两个包含1~1024和1025~2048字节的报文段到达,且每一个都带有一个时间戳选项,接收方产生ACK 2049对它们进行确认时,ACK中的时间戳应该是包含字节1~1024的第一个报文段中的时间戳。这样是正确的,发送方在进行重传超时时间的计算时,就将迟延的ACK也考虑在内了。
2.如果收到的报文段在窗口范围内,但它是失序的,这表明前面的报文段已经丢失,当丢失的报文段到达时,丢失的报文段中的时间戳(而非失序的报文段中的时间戳)将被回显。例如,假设有3个报文段,每个报文段包含1024字节,这3个报文段按以下顺序收到:
1.含字节1~1024的报文段1;
2.含字节2049~3072的报文段3;
3.含字节1025~2048的报文段2。
发回的ACK应该是以下顺序:
1.带有从报文段1中获取的时间戳的对1025字节序号的ACK(这是一个我们期望的ACK);
2.带有从报文段1中获取的时间戳的对1025字节序号的ACK(一个对窗口内,但失序的数据报的重复ACK);
3.带有从报文段2中获取的时间戳的对3073字节序号的ACK(而不是从报文段3中获取的时间戳,如果此时报文段2不是在网络中被迟延而是被发送方又重发,其中的时间戳值会是第二次重发时的发送方时间戳,而非第一次发送时的时间戳值)。
当有多个报文段同时丢失时,以上过程对RTT值的估计会偏大,因为这多个报文段重发到接收端时,会取第一个到达的重发报文段中的时间戳,但这比对RTT值的估计偏小要好。如果以上过程中第3个ACK中含有的时间戳来自报文段3,在收到报文段3到发送对3073字节序号的ACK期间,可能会出现重复ACK的返回和报文段2的重发或发送方报文段2的重传计时器超时然后发送报文段2,这两种情况都会使RTT的计算出现偏差。

使用窗口扩大选项的TCP连接的最大可能窗口大小为230(1Gb,但其实是65535*214,但差距很小,不影响讨论)字节,假定此连接还使用了时间戳选项且发送方指定的时间戳在发送完每个窗口后加1,以下是传输6千兆字节的数据时,两个主机间可能的数据流,1G大小为1073741824(2的30次方),字节序号是32bit的,因此每发送4个窗口大小的数据后会发生序号回绕:
在这里插入图片描述
如上图,32bit的序号在时间D和E之间发生了回绕,假定一个报文段在时间B丢失并被重传且这个丢失的报文段在时间F重新出现,这意味着在报文段丢失和重新出现之间的时间差小于MSL,否则这个报文段在它的TTL到期时会被某个路由器丢弃,此时旧的报文段重新出现并带有当前要传输的序号,此时可用时间戳选项避免这种情况,接收方将时间戳视为序列号的一个32bit的扩展,时间E重新出现的报文段的时间戳为2,这比最近有效的时间戳小(5或6),因此PAWS(防止序号回绕,Protection Against Wrapped Sequence Numbers)算法将其丢弃。

PAWS算法不需要发送方和接收方之间进行任何形式的时间同步,接收方只需要时间戳的值单调递增且每个窗口至少加1。

TCP提供的是一种虚电路方式的运输服务,一个连接的生存时间包括三个不同阶段:建立、数据传输、终止,这种虚电路服务适合远程登录和文件传输类的应用。

有一些应用被设计成使用事务服务,一个事务是符合下面特征的一个客户请求及其随后的服务器响应:
1.应避免连接建立和连接终止的开销,发送一个请求分组并接收一个应答分组。
2.等待时间应减少到等于RTT(Round-Trip Time,往返时间)和SPT(Server Processing Time,服务器处理请求的时间)之和。
3.服务器应能检测出重复的请求,收到一个重复的请求时不必重新处理事务,而是返回保存的、与该请求对应的应答。

一个使用上述类型服务的应用是域名服务,尽管DNS不关心服务器怎样回复相同的请求。

程序设计人员面对TCP和UDP需要做出选择,TCP提供了过多的事务特征,而UDP提供的不够。通常应用程序使用UDP来避免TCP连接的开销,而许多重要特征(如动态超时和重传、拥塞避免等)被放置到应用层,又重新设计和实现一遍。

一个较好的解决方法是提供一个能够提供充足的事务处理功能的运输层,如T/TCP协议,这是一个事务协议,我们从它的定义(即RFC 1379)开始介绍。

T/TCP通过使用加速打开来避免三次握手:
1.它为打开的连接指定一个32bit的连接计数CC(Connection Count),无论主动打开还是被动打开。一个主机的CC值从一个全局计数器中获得,该计数器每次使用时加1。
2.在两个使用T/TCP的主机之间的每一个报文段都包括一个新的TCP选项CC,这个选项长度为6字节,其中包含发送方在该连接上的32bit的CC值。
3.一个主机为每个主机维持一个缓存,该缓存保留该主机上一次的CC值,这个CC值从来自这个主机的一个可接受的SYN报文段中获得。
4.在一个开始的SYN中收到一个CC选项的时候,接收方比较收到的值与为该发送方缓存的CC值,如果收到的CC值比缓存的大,则该SYN是新的,此报文段中的数据直接传递给应用进程,这个连接被称为半同步;如果接收的CC比缓存小,或接收主机上没有这个客户的缓存CC,则执行正常的TCP三次握手过程。
5.为响应一个SYN,带有SYN和ACK的报文段在CCECHO选项中回显所接收到的CC值。
6.在一个非SYN报文段中的CC值用来检测和拒绝来自同一个连接的前一个替身的报文段。

以上加速打开的代价是必须记住从每个客户接收的最近CC值。

T/TCP基于在两个主机之间测量RTT来动态计算TIME_WAIT的延时(2MSL),可以缩短TIME_WAIT状态,TIME_WAIT时延被设置为8倍的超时重传值RTO(该值是通过RTT计算出来的)。

通过以上特征,最小的事务序列是交换三个报文段:
1.主动打开引起的客户到服务器的报文段,包含客户的SYN、客户的请求、客户的FIN、客户的CC。
2.服务器到客户的报文段,包含服务器的SYN、服务器的应答、服务器的FIN、对客户的ACK(由于TCP的确认是累积的,因此这个确认包含对客户的SYN、客户数据、客户FIN的确认)、服务器的CC、包含客户CC的CCECHO选项。客户收到1中的报文段后,将其传送给客户应用进程。
3.客户到服务器的报文段,包含对2中报文段的ACK,它确认了服务器的SYN、服务器的数据、服务器的FIN。

客户发送请求到收到响应的时间为RTT和SPT的和。

实现T/TCP时:
1.服务器的SYN和ACK必须被迟延,从而允许捎带上应答一起发送。普通TCP对SYN的ACK是不迟延的,但也不能迟延太久,否则客户将超时并引起重传。
2.请求可以是多个报文段,服务器必须处理它们失序到达的情况。普通TCP当数据在SYN之前到达时,该数据会被丢弃并产生一个复位,使用T/TCP时需要将这些数据放入队列中处理。
3.API必须使服务器进程用一个单一的操作来发送数据和关闭连接,从而允许第二个报文段中的FIN与应答一起捎带发送。普通TCP的服务器进程先写应答,从而引起发送一个应答报文段,然后关闭连接,引起发送FIN。
4.收到来自服务器的MSS通告之前,客户就会在第一个报文段中发送数据,这需要客户缓存服务器主机的MSS,以避免客户猜测对方一个很小的MSS。
5.客户也会在服务器没有通告窗口大小时就发送数据。T/TCP建议客户默认服务器的窗口大小为4096字节,并且建议客户要缓存到该服务器的拥塞阈值。
6.由于最少情况只使用了三个报文段交换,此时每个方向上只能计算一次RTT,并且客户测量的RTT还包含服务器的处理时间。这意味着到该服务器的被平滑的RTT及其方差也必须缓存起来。

T/TCP对现有协议进行了最小的修改,同时兼容了现有实现,它还利用了TCP中的动态超时和重传、拥塞避免等特征,避免了应用来处理这些问题。

通用报文事务协议VMTP(Versatile Message Transaction Protocol)也是一个事务协议,它不是对现有TCP协议的扩充,而是使用IP的一个完整的运输层。VMTP处理差错检测、重传、重复抑制,它还支持多播通信。

TCP的限制:
1.不能比最慢的链路更快。
2.不能比最慢的机器内存更快(将数据从用户空间复制到内核中)。
3.不能比接收方提供的窗口大小除以往返时间所得结果更快,如果使用最大窗口扩大因子14,则窗口大小为1073兆字节,它除以RTT的结果就是带宽的极限。

一个系统发送一个窗口扩大因子为0的开始SYN报文段意味着发送TCP支持窗口扩缩选项,另一端可以说明一个窗口扩缩因子(可以是0或非0)。

已经定义了的窗口扩大因子不能在扩大因子变化时通过ACK发往对端(除非该窗口因子变化的通知是顺带的),因为单纯的ACK报文段可能丢失。

假定MSL为2分钟,在速率为至少为232*8/2/60=286Mb/s时会在一个MSL内发生序号回绕,从而导致问题。(TCP首部中的序号字段指的是字节的序号)

由于PAWS被定义为只在一个单独的连接中进行,为了让TCP能用PAWS替换2MSL等待时间(TIME_WAIT),即要想通过PAWS来判断是否收到了上一个连接的化身的数据,需要TCP记住所有连接上收到的上一个时间戳,包括已经关闭的连接。

在计算平均RTT时,只要报文段重传了,就不使用其往返时延样本,这是karn算法,但如果使用了时间戳选项,则可以明确ACK是对哪个报文段的,就可以使用这个往返时延样本。

如果服务器没有使用T/TCP扩展,即使客户主动开启T/TCP发送带有FIN和请求数据的SYN报文段,客户在接收服务器的请求结果的时延仍然会是两倍RTT加SPT,过程如下:
1.客户到服务器的报文段,其中包含SYN、请求数据、FIN。
2.服务器到客户的报文段,其中包含SYN和对客户SYN的确认。
3.客户到服务器的报文段,其中包含对服务器SYN的确认、客户的FIN。这使服务器进入连接建立状态,报文段1中的排队客户请求数据传递给服务器应用。
4.服务器到客户的报文段,其中包含对客户请求数据和FIN的确认、服务器的应答数据、服务器的FIN。此处假定SPT足够短以和这个延迟的确认一起发送。
5.客户到服务器的报文段,其中包含对服务器FIN的确认。

T/TCP总是会比UDP花费更多时间,因为它涉及了UDP没有做的状态处理。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值