Windows系统下的TCP参数优化
1. TCP连接的状态
⾸先介绍⼀下TCP连接建⽴与关闭过程中的状态。TCP连接过程是状态的转换,促使状态发⽣转换的因素包括⽤户调⽤、特定数据包以及超时等,具体状态如下所⽰:
CLOSED:初始状态,表⽰没有任何连接。
tcpip协议是一个完整的体系结构由tcp协议和ip协议组成LISTEN:Server端的某个Socket正在监听来⾃远⽅的TCP端⼝的连接请求。
SYN_SENT:发送连接请求后等待确认信息。当客户端Socket进⾏Connect连接时,会⾸先发送SYN包,随即进⼊SYN_SENT状态,然后等待Server端发送三次握⼿中的第2个包。
SYN_RECEIVED:收到⼀个连接请求后回送确认信息和对等的连接请求,然后等待确认信息。通常是建⽴TCP连接的三次握⼿过程中的⼀个中间状态,表⽰Server端的Socket接收到来⾃Client的SYN包,并作出回应。
ESTABLISHED:表⽰连接已经建⽴,可以进⾏数据传输。
FIN_WAIT_1:主动关闭连接的⼀⽅等待对⽅返回ACK包。若Socket在ESTABLISHED状态下主动关闭连接并向对⽅发送FIN包(表⽰⼰⽅不再有数据需要发送),则进⼊FIN_WAIT_1状态,等待对⽅返回ACK包,此后还能读取数据,但不能发送数据。在正常情况下,⽆论对⽅处于何种状态,都应该马上返回ACK包,所以FIN_WAIT_1状态⼀般很难见到。
FIN_WAIT_2:主动关闭连接的⼀⽅收到对⽅返回的ACK包后,等待对⽅发送FIN包。处于FIN_WAIT_1状态下的Socket收到了对⽅返回的ACK包后,便进⼊FIN_WAIT_2状态。由于FIN_WAIT_2状态下的Socket需要等待对⽅发送的FIN包,所有常常可以看到。若在FIN_WAIT_1状态下收到对⽅发送的同时带有FIN和ACK的包时,则直接进⼊TIME_WAIT状态,⽆须经过FIN_WAIT_2状态。
TIME_WAIT:主动关闭连接的⼀⽅收到对⽅发送的FIN包后返回ACK包(表⽰对⽅也不再有数据需要发送,此后不能再读取或发送数据),然后等待⾜够长的时间(2MSL)以确保对⽅接收到ACK包(考虑到丢失ACK包的可能和迷路重复数据包的影响),最后回到CLOSED状态,释放⽹络资源。
CLOSE_WAIT:表⽰被动关闭连接的⼀⽅在等待关闭连接。当收到对⽅发送的FIN包后(表⽰对⽅不再有数据需要发送),相应的返回ACK包,然后进⼊CLOSE_WAIT状态。在该状态下,若⼰⽅还有数据未发送,则可以继续向对⽅进⾏发送,但不能再读取数据,直到数据发送完毕。
LAST_ACK:被动关闭连接的⼀⽅在CLOSE_WAIT状态下完成数据的发送后便可向对⽅发送FIN包(表
⽰⼰⽅不再有数据需要发送),然后等待对⽅返回ACK包。收到ACK包后便回到CLOSED状态,释放⽹络资源。
CLOSING:⽐较罕见的例外状态。正常情况下,发送FIN包后应该先收到(或同时收到)对⽅的ACK包,再收到对⽅的FIN包,⽽CLOSING状态表⽰发送FIN包后并没有收到对⽅的ACK包,却已收到了对⽅的FIN包。有两种情况可能导致这种状态:其⼀,如果双⽅⼏乎在同时关闭连接,那么就可能出现双⽅同时发送FIN包的情况;其⼆,如果ACK包丢失⽽对⽅的FIN包很快发出,也会出现FIN 先于ACK到达。
TCP连接的状态转换如下图所⽰
2. TCP连接的关闭⽅式
建⽴TCP连接需要三次握⼿,⽽关闭连接则需要四次握⼿,并且分为主动关闭和被动关闭。这是由于TCP连接是全双⼯的,我关了你的连接,并不等于你关了我的连接,因此双⽅都必须单独进⾏关闭。当⼀⽅完成它的数据发送任务后可以发送FIN包来终⽌这个⽅向的连接,表明⾃⼰不再有数据需要发送;收到FIN包的那⼀⽅虽然不能再读取数据,但仍能发送数据。以Client主动关闭连接为例:
1. Client向Server发送FIN包,表⽰Client主动关闭连接,然后进⼊FIN_WAIT_1状态,等待Server返回ACK包。此后Client不能再向
Server发送数据,但能读取数据。
2. Server收到FIN包后向Client发送ACK包,然后进⼊CLOSE_WAIT状态,此后Server不能再读取数据,但可以继续向Client发送数据。
Client收到Server返回的ACK包后进⼊FIN_WAIT_2状态,等待Server发送FIN包。
3. Server完成数据的发送后,将FIN包发送给Client,然后进⼊LAST_ACK状态,等待Client返回ACK包,此后Server既不能读取数据,
也不能发送数据。
4. Client收到FIN包后向Server发送ACK包,然后进⼊TIME_WAIT状态,接着等待⾜够长的时间(2MSL)以确保Server接收到ACK包,
最后回到CLOSED状态,释放⽹络资源。Server收到Client返回的ACK包后便回到CLOSED状态,释放⽹络资源。
TCP连接的建⽴到关闭,需要经历以下状态迁移(假定Client发起连接,并主动关闭连接):
Client
CLOSED -> SYN_SENT -> ESTABLISHED -> FIN_WAIT_1 -> FIN_WAIT_2 -> TIME_WAIT -> CLOSED
Server
CLODES -> LISTEN -> SYN_RECEIVED -> ESTABLISHED -> CLOSE_WAIT -> LAST_ACK -> CLOSED
3. 对Server与Client的影响
在详细了解TCP连接的状态和关闭⽅式后,我们会发现TIME_WAIT状态是⼀个坑爹的存在!主动关闭连接的⼀⽅在发送最后⼀个ACK 包后,⽆论对⽅是否收到都会进⼊TIME_WAIT状态,等待2MSL的时间,然后才能释放⽹络资源。MSL就是Maximum Segment
Lifetime(数据包的最⼤⽣命周期),是⼀个数据包能在互联⽹上⽣存的最长时间,若超过这个时间则该数据包将会消失在⽹络中。操作系统通常会将2MSL设为4分钟,最低不少于30秒,因⽽TIME_WAIT状态⼀般维持在30秒⾄4分钟。这个是TCP/IP协议必不可少的,是TCP/IP
设计者设计的,也就是⽆法解决的。TIME_WAIT状态的存在主要有两个原因:
1. 可靠地实现TCP全双⼯连接的终⽌。在关TCP闭连接时,最后的ACK包是由主动关闭⽅发出的,如果这个ACK包丢失,则被动关闭⽅
将重发FIN包,因此主动⽅必须维护状态信息,以允许它重发这个ACK包。如果不维持这个状态信息,那么主动⽅将回到CLOSED状态,并对被动⽅重发的FIN包响应RST包,⽽被动关闭⽅将此包解释成⼀个错误(在Java中会抛出connection reset的
SocketException)。因⽽,要实现TCP全双⼯连接的正常终⽌,必须能够处理四次握⼿协议中任意⼀个包丢失的情况,主动关闭⽅必须维持状态信息进⼊TIME_WAIT状态。
2. 确保迷路重复数据包在⽹络中消失,防⽌上⼀次连接中的包迷路后重新出现,影响新连接。TCP数据包可能由于路由器异常⽽迷路,
在迷路期间,数据包发送⽅可能因超时⽽重发这个包,迷路的数据包在路由器恢复后也会被送到⽬的地,这个迷路的数据包就称为Lost Duplicate。在关闭⼀个TCP连接后,如果马上使⽤相同的IP地址和端⼝建⽴新的TCP连接,那么有可能出现前⼀个连接的迷路重复数据包在前⼀个连接关闭后再次出现,影响新建⽴的连接。为了避免这⼀情况,TCP协议不允许使⽤处于TIME_WAIT状态的连接的IP和端⼝启动⼀个新连接,只有经过2MSL的时间,确保上⼀次连接中所有的迷路重复数据包都已消失在⽹络中,才能安全地建⽴新连接。
对于Client⽽⾔,每个连接都需要占⽤⼀个端⼝,⽽系统允许的可⽤端⼝数不⾜65000个(这也是在TCP参数优化后才能达到)。因此,如果Client发起过多的连接并主动关闭(假设没有重⽤端⼝或者连接多个Server),就会有⼤量的连接在关闭后处于TIME_WAIT状态,等待2MSL的时间后才能释放⽹络资源(包括端⼝),于是Client会由于缺少可⽤端⼝⽽⽆法新建连接。
对Server⽽⾔(特别是处理⾼并发短连接的Server),Server端与Client建⽴的连接是使⽤同⼀个端⼝的,即监听的端⼝,每个连接通过⼀个五元组区分,包括源IP地址、源端⼝、传输层协议号(协议类型)、⽬的IP地址、⽬的端⼝,因⽽在理论上,Server不受系统端⼝数的限制。但是,Server对每个端⼝上的连接数是有限制的,它要使⽤哈希表记录端⼝上的每个连接,并受到⽂件描述符的最⼤打开数的限制。所以,如果Server主动关闭连接,同样会有⼤量的连接在关闭后处于TIME_WAIT状态,等待2MSL的时间后才能释放⽹络资源(包括哈希表上的连接记录和⽂件描述符),于是Server会由于达到哈希表和⽂件描述符的限制⽽⽆法接受新连接,造成性能的急剧下滑,性能曲线会持续产⽣严重的波动。对于这种情况,有三种应对⽅式:
1. 试图让Client主动关闭连接,由于每个Client的并发量都⽐较低,因⽽不会产⽣性能瓶颈。
2. 优化Server的系统TCP参数,使其⽹络资源的最⼤值、消耗速度和恢复速度达到平衡。
3. 改写TCP协议,重新实现底层代码,不过该⽅式难度很⼤,⽽且系统的稳定性和安全性可能受到影响。
4. TCPWindowSize
TCPWindowSize的值表⽰TCP的窗⼝⼤⼩。TCP Receive Window(TCP数据接收缓冲)定义了发送端在没有获得接收端的确认信息的状态下可以发送的最⼤字节数。此数值越⼤,返回的确认信息就越少,相应的在发送端和接收端之间的通信就越好。此数值较⼩时可以降低发送端在等待接收端返回确认信息时发⽣超时的可能性,但这将增加⽹络流量,降低有效吞吐率。TCP在发送端和接收端之间动态调整⼀个最⼤段长度MSS(Maximum Segment Size)的整数倍。MSS在连接开始建⽴时确定,由于TCP Receive Window被调整为MSS的整数倍,在数据传输中完全长度的TCP数据段的⽐例增加,故⽽提⾼了⽹络吞吐率。
缺省情况下,TCP将试图根据MSS来优化窗⼝⼤⼩,起始值为16KB,最⼤值为64KB。TCPWindowSize的最⼤值通常为65535字节(64KB),以太⽹最⼤段长度为1460字节,低于64KB的1460的最⼤整数倍为62420字节,因⽽可以在注册表中将TCPWindowSize设置为62420,作为⾼带宽⽹络中适⽤的性能优化值。具体操作如下:
浏览⾄HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\TCPIP\Parameters注册表⼦键,在Parameters⼦键下创建或修改名为TCPWindowSize的REG_DWORD值,该值的范围是从0到65535,将该值设置为62420。
5. TCP1323Opts
为了更⾼效地利⽤⾼带宽⽹络,可以使⽤⽐上述TCP窗⼝⼤得多的TCP窗⼝⼤⼩,此特性是Windows 2000和Windows Server 2003中的新特性,称为TCP Window Scaling,它将以前的65535字节(64KB)的限制提⾼到了1073741824字节(1GB)。在带宽与延迟的乘积值很⾼的连接上(例如卫星连接),可能需要将窗⼝的⼤⼩增加到64KB以上。使⽤TCP Window Scaling,系统可以允许确认信息间更⼤数据量的传输,增加了⽹络吞吐量及性能。发送端和接收端往返通信所需的时间被称为回环时间(RTT)。TCP Window Scaling仅在TCP连接的双⽅都开启时才真正有效。TCP有⼀个时间戳选项,通过更加频繁地计算来提⾼RTT值的估测值,此选项特别有助于估测更长距离的⼴域⽹上连接的RTT值,并更加精确地调整TCP重发超时时间。时间戳在TCP报头提供了两个区域,⼀个记录开始重发的时间,另⼀个记录接收到的时间。时间戳对于TCP Window Scaling,即确认信息收到前的⼤数据包传送特别有⽤,激活时间戳仅仅在每个数据包的头部增加12字节,对⽹络流量的影响微乎其微。数据完整性与数据吞吐率最⼤化哪个更为重要是个需要评估的问题。在某些环境中,例如视频流传输,需要更⼤的TCP窗⼝,这是最重要的,⽽数据完整性排在第⼆位。在这种环境中,TCP Window Scaling可以不打开时间戳。当发送端和接收端均激活TCP Window Scaling和时间戳时,此特性才有效。不过,若在发包时加⼊了时间戳,经过NAT之后,如果前⾯相同的端⼝被使⽤过,且时间戳⼤于这个连接发出的SYN中的时间戳,就会导致服务器忽略该SYN,表现为⽤户⽆法正常完成TCP的3次握⼿。初始时⽣成⼩的TCP窗⼝,之后窗⼝⼤⼩将按照内部算法增⼤。具体操作如下:
浏览⾄HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\TCPIP\Parameters注册表⼦键,在Parameters⼦键下创建或修改名为TCP1323Opts的REG_DWORD值,该值的具体含义为:0(缺省值)表⽰禁⽤TCP Window Scaling和时间戳;1表⽰只启⽤TCP Window Scaling;2表⽰只启⽤时间戳;3表⽰同时启⽤TCP Window Scaling和时间戳。TCP1323Opts设置为激活TCP Window Scaling 后,可以将上⽂中的注册表项TCPWindowSize的值增⼤,最⼤能达到1GB,为了达到最佳性能,这⾥的值最好设置成MSS的倍数,推荐值为256960字节。
6. TCP 控制块表
对于每个TCP连接,控制变量保存在⼀个称为TCP控制块(TCB)的内存块中。TCB表的⼤⼩由注册表项MaxHashTableSize控制。在活动连接很多的系统中,设定⼀个较⼤的表可以降低系统定位TCB表的时间。在TCB表上分区可以降低对表的访问的争夺。增加分区的数量,TCP的性能会得到优化,特别是在多处理器的系统上。注册表项NumTcbTablePartitions控制分区的数量,默认是处理器个数的平⽅。TCB通常预置在内存中,以防⽌TCP反复连接和断开时,TCB反复重新定位浪费时间,这种缓冲的⽅式促进了内存管理,但同时也限制了同
⼀时刻允许的TCP连接数量。注册表项MaxFreeTcbs决定了处于空闲等待状态的TCB重新可⽤之前的连接数量,在NT架构中常设置成⾼于默认值,以确保有⾜够的预置的TCB。从Windows 2000开始添加了
⼀个新特性,降低超出预置TCB运⾏的可能性。如果处于等待状态的连接多于MaxFreeTWTcbs中的设置,所有等待时间超过60秒的连接将被强制关闭,以后再次启⽤。此特性合并到Windows 2000 Server和Windows Server 2003后,MaxFreeTcbs将不再⽤于优化性能。具体操作:
浏览⾄HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\TCPIP\Parameters注册表⼦键,在Parameters⼦键下创建或修改名为MaxHashTableSize的REG_DWORD值,该值的范围是从1到65536,并且必须为2的N次⽅,缺省值为512,建议设为8192。然后在Parameters⼦键下创建或修改名为NumTcbTablePartitions的REG_DWORD值,该值的范围是从1到65536,并且必须为2的N次⽅,缺省值为处理器个数的平⽅,建议设为处理器核⼼数的4倍。
7. TcpTimedWaitDelay
TcpTimedWaitDelay的值表⽰系统释放已关闭的TCP连接并复⽤其资源之前,必须等待的时间。这段时间间隔就是以前的Blog中提到的TIME_WAIT状态(2MSL,数据包最长⽣命周期的两倍状态)。如果系统显⽰⼤量连接处于TIME_WAIT状态,则会导致并发量与吞吐量的严重下降,通过减⼩该项的值,系统可以更快地释放已关闭的连接,从⽽为新连接提供更多的资源,特别是对于⾼并发短连接的Server具有积极的意义。
该项的缺省值是240,即等待4分钟后释放资源;系统⽀持的最⼩值为30,即等待时间为30秒。具体操
作:
浏览⾄HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\TCPIP\Parameters注册表⼦键,在Parameters⼦键下创建或修改名为TcpTimedWaitDelay的REG_DWORD值,该值的范围是从0到300,建议将该值设置为30。
8. MaxUserPort
MaxUserPort的值表⽰当应⽤程序向系统请求可⽤的端⼝时,TCP/IP可分配的最⼤端⼝号。如果系统显⽰建⽴连接时出现异常,那么有可能是由于匿名(临时)端⼝数不够导致的,特别是当系统打开⼤量端⼝来与Web service、数据库或其他远程资源建⽴连接时。
该项的缺省值是⼗进制的5000,这也是系统允许的最⼩值。Windows默认为匿名(临时)端⼝保留的端⼝号范围是从1024到5000。为了获得更⾼的并发量,建议将该值⾄少设为32768以上,甚⾄设为理论最⼤值65534,特别是对于模拟⾼并发测试环境的Client具有积极的意义。具体操作:
浏览⾄HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\TCPIP\Parameters注册表⼦键,在Parameters⼦键下创建或修改名为MaxUserPort的REG_DWORD值,该值的范围是从5000到65534,缺省值为5000,建议将该值设置为65534。
9. 动态储备
动态储备的值使系统能⾃动调整其配置,以接受⼤量突发的连接请求。如果同时接收到⼤量连接请求,超出了系统的处理能⼒,那么动态储备就会⾃动增⼤系统⽀持的暂挂连接的数量(即Client已请求⽽Server尚未处理的等待连接数,TCP连接的总数包括已连接数与等待连接数),从⽽可减少连接失败的数量。系统的处理能⼒和⽀持的暂挂连接的数量不⾜时,Client的连接请求将直接被拒绝。
缺省情况下,Windows 不启⽤动态储备,可以通过以下操作进⾏开启和设置:
浏览⾄HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\AFD\Parameters注册表⼦键,在Parameters⼦键下创建或修改下列名称的REG_DWORD值。
EnableDynamicBacklog,值为1,表⽰开启动态储备。
MinimumDynamicBacklog,值为128,表⽰⽀持的最⼩暂挂连接的数量为128。
MaximumDynamicBacklog,值为2048,表⽰⽀持的最⼤暂挂连接的数量为2048。对于⾼并发短连接的Server,建议最⼤值设为1024及以上。
DynamicBacklogGrowthDelta,值为128,表⽰⽀持的暂挂连接的数量的增量为128,即数量不⾜时⾃增长128,直到达到设定的最⼤值,如2048。
10. KeepAliveTime
KeepAliveTime的值控制系统尝试验证空闲连接是否仍然完好的频率。如果该连接在⼀段时间内没有活动,那么系统会发送保持连接的信号,如果⽹络正常并且接收⽅是活动的,它就会响应。如果需要对丢失接收⽅的情况敏感,也就是说需要更快地发现是否丢失了接收⽅,请考虑减⼩该值。⽽如果长期不活动的空闲连接的出现次数较多,但丢失接收⽅的情况出现较少,那么可能需要增⼤该值以减少开销。
缺省情况下,如果空闲连接在7200000毫秒(2⼩时)内没有活动,系统就会发送保持连接的消息。通常建议把该值设为1800000毫秒,从⽽丢失的连接会在30分钟内被检测到。具体操作:
浏览⾄HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\TCPIP\Parameters注册表⼦键,在Parameters⼦键下创建或修改名为KeepAliveTime的REG_DWORD值,为该值设置适当的毫秒数。
11. KeepAliveInterval
KeepAliveInterval的值表⽰未收到另⼀⽅对“保持连接”信号的响应时,系统重复发送“保持连接”信号的频率。在⽆任何响应的情况下,连续发送“保持连接”信号的次数超过TcpMaxDataRetransmissions(下⽂将介绍)的值时,将放弃该连接。如果⽹络环境较差,允许较长的响应时间,则考虑增⼤该值以减少开销;如果需要尽快验证是否已丢失接收⽅,则考虑减⼩该值或TcpMaxDataRetransmissions值。
缺省情况下,在未收到响应⽽重新发送“保持连接”的信号之前,系统会等待1000毫秒(1秒),可以根据具体需求修改,具体操作:
浏览⾄HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\TCPIP\Parameters注册表⼦键,在Parameters⼦键下创建或
修改名为KeepAliveInterval的REG_DWORD值,为该值设置适当的毫秒数。
12. TcpMaxDataRetransmissions
TcpMaxDataRetransmissions的值表⽰TCP数据重发,系统在现有连接上对⽆应答的数据段进⾏重发的次数。如果⽹络环境很差,可能需要提⾼该值以保持有效的通信,确保接收⽅收到数据;如果⽹络环境很好,或者通常是由于丢失接收⽅⽽导致数据的丢失,那么可以减⼩该值以减少验证接收⽅是否丢失所花费的时间和开销。
缺省情况下,系统会重新发送未返回应答的数据段5次,可以根据具体需求修改,具体操作:
浏览⾄HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\TCPIP\Parameters注册表⼦键,在Parameters⼦键下创建或修改名为TcpMaxDataRetransmissions的REG_DWORD值,该值的范围是从0到4294967295,缺省值为5,根据实际情况进⾏设置。
13. TcpMaxConnectRetransmisstions
TcpMaxConnectRetransmisstions的值表⽰TCP连接重发,TCP退出前重发⾮确认连接请求(SYN)的次数。对于每次尝试,重发超时是成功重发的两倍。在Windows Server 2003中默认超时次数是2,默认超时时间为3秒(在注册表项TCPInitialRTT中)。速度较慢的WAN 连接中超时时间可相应增加,不同环境中可能会有不同的最优化设置,需要在实际环境中测试确定。超时时间不要设置太⼤否则将不会发⽣⽹络连接超时时间。具体操作:
浏览⾄HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\TCPIP\Parameters注册表⼦键,在Parameters⼦键下创建或修改名为TcpMaxConnectRetransmisstions的REG_DWORD值,该值的范围是从0到255,缺省值为2,根据实际情况进⾏设置。然后在Parameters⼦键下创建或修改名为TCPInitialRTT的REG_DWORD值,同样根据实际情况进⾏设置。
14. TcpAckFrequency
TcpAckFrequency的值表⽰系统发送应答消息的频率。如果值为2,那么系统将在接收到2个分段之后发送应答,或是在接收到1个分段但在200毫秒内没有接收到任何其他分段的情况下发送应答;如果值为3,那么系统将在接收到3个分段之后发送应答,或是在接收到1个或2个分段但在200毫秒内没有接收到任何其他分段的情况下发送应答,以此类推。如果要通过消除应答延迟来缩短响应时间,那么建议将该
值设为1。在此情况下,系统会⽴即发送对每个分段的应答;如果连接主要⽤于传输⼤量数据,⽽200毫秒的延迟并不重要,那么可以减⼩该值以降低应答的开销。
缺省情况下,系统将该值设为2,即每隔⼀个分段应答⼀次。该值的有效范围是0到255,其中0表⽰使⽤缺省值2,可以根据具体需求修改,具体操作:
浏览⾄HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\TCPIP\Parameters\Interfaces\xx(xx由⽹络适配器决定)注册表⼦键,在xx⼦键下创建或修改名为TcpAckFrequency的REG_DWORD值,该值的范围是从1到13,缺省值为2,根据希望每发送⼏个分段返回⼀个应答⽽设置该值,建议百兆⽹络设为5,千兆⽹络设为13。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论