即使端口处于2MSL状态,使用该选项,仍然能够在该端口建立连接。
服务器常会设置该选项,以防服务器重启。
如果在TIME_WAIT时间内,收到了对端发送来的数据报(不是重置报文段都行),那么该状态将被破坏,称为 时间等待错误 。原因是,当收到报文段以后,通常Seq是旧的,所以本端就会发送ACK,对端已经关闭或者是别的连接,就会发送RST,导致TIME_WAIT状态被破坏。
但是许多系统规定,TIME_WAIT状态是不对重置报文段做出反应。
两端同时发送FIN,两端又同时ACK。又同时进入TIME_WAIT
当处于TIME_WAIT的主机崩溃以后,重启,然后需要等待相当与一个MSL的时间才能建立新的连接。
这段时间成为静默时间。
当一段发现到达的报文段对相关连接(也就是进程,套接字对)而言不正确的时候,TCP就会发送一个重置报文段,从而导致对端的连接快速拆卸(也就是结束吧!)。
重置报文段的ACK位必须有,而且ACK的值必须在正确的窗口范围内,这样可以防止被攻击。
FIN正常关闭一条连接成为 有序释放 ,通常不会出现丢失数据的情况。
重置报文段终止一条连接成为 终止释放 。重置报文段在任何时候都可以发送,代替FIN来终止连接,且不学校对端ACK
终止报文段特性:
当该数值设置为0,那么也意味着,不会再连接终止之前为了确保本端缓存中的数据都发送出去而等待。
TCP在发送数据时会设置计时器,如果计时器超时认为受到数据确认信息,就会引发相应的超时,或给予计时器的重传 *** 作,计时器超时时成为重传超时( RTO )。
TCP累计确认无法返回新的ACK,或者当ACK包含选择确认信息(SACK)时,表明出现书序数据报,空洞。就会引起 快速重传 。
若RTO短与RTT,那么没分都会重传,反之,整个网络利用率就会随之下降。
RTT样本 :TCP在收到数据后会返回确认信息ACK,该信息中携带一个字节的数据,测量传输该确认需要的时间,该测量结果成为RTT样本。
每个连接的RTT军独立计算。
如何根据RTT来设置RTO,有如下的方法
公式: SRTT=aSRTT+(1-a)RTT ,a取 08-09 。
当TCP运行在RTT变化较大的网络中,无法取得期望的结果。
以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补
因为丢失ACK,或者实际RTT显著增长,可能出现伪超时的现象。
以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补
每个包可以选择各自的传送路径。某些高级路由器的采用多个并行数据链路,不同的处理演示也会导致包的离开顺序和到达顺序不匹配
包的失序会造成重传,很近单嘛,前面一个小号的Seq没到达,后面的先到达,那么ACK就会 重复
当TCP超时重发是,循序执行重新租宝,发送送一个更大的报文段提高性能,不超过MSS和MTU。
出现在每次传送的包较小,又丢包的情况
每个交互键通常会生成一个单独的数据报,也就是每个按键是独立传输的。
ssh调用一个shell,对客户端输入的字符做出辉县,因此,每个字符生成4个tcp数据段,客户端的交互按键输入,服务器对按键的ACK,服务器生成的辉县,客户端对回显的ACK。通常第二段和第三段合并,成为 捎带延时确认 。
PSH位设置,意味着发送端的缓存为空,也就是没什么可以发送了。
许多情况下,TCP并不是对每个到来的包都单独的ACK,利用累计ACK可以确认之前的ACK。累计确认可以允许TCP延时一段时间发送ACK,以便将ACK和相同方向上需要传输的数据结合发。这种捎带传输的方法常用于批量数据传输。
不能任意的延迟ACK,会造成重传。同时当失序发生时,必须立刻传送ACK。
系统可以设置,一般延时为200-600毫秒。
该算法要求,当TCP连接中有在传数据(那些已发送,但是未确认的数据)时,小的报文段就不能被发送,知道所有的数据都受到ACK。并且受到ACK后,TCP收集这些小的数据,整合到一个报文段中发送。
这种方法破事TCP遵循等停规程,只有收到所有传送数据的ACK后才能继续发送新数据。
该算法的不同之处在于他实现了自时钟控制,ACK返回越快,传输也越快。在相对高延迟的广域网中,更需要减小小报文的数目,该算法使得单位时间内发送的报文数目更少,RTT控制发包速率。
该算法减少小包数目的同时,也增大了传输时延,也就是总的发送时间。
窗口大小表明本端可用缓存大小,对端传送的数据不应该超过改大小。
也表明对端发送的数据的最大大小为TCP头部ACK号和窗口大小字段之和。
也就是Seq = ACK+MSS
TCP活动的两端都维护一个发送窗口结构和接受窗口结构。
TCP以 字节 为单位维护窗口结构。
每个TCP报文段都包含ACK号和窗口通告信息,TCP发送端可以据此调节窗口结构。
窗口左边界不能左移。
窗口的动作分为,关闭(收到ACK,左边右移),打开(MSS扩大,右边右移),收缩(MSS减小,右边左移)
当收到ACK号增大,而MSS不变时窗口向前 滑动
当当左边界与右边界相等时,成为 零窗口 ,此时发送端不能在发送新的数据,这种情况下,TCP开始探测对端窗口,伺机增大窗口。
当接受窗口值变为0是,可以邮箱的组织发送端继续发送,知道窗口大小回复为非0值。当接收端窗口得到可用空间是,就会给发送端传输一个窗口更新,告知器可以继续发送数据,这样的这样的窗口更新通常不包含数据,成为纯ACK,因此不能保证传输的可靠性。
如果一端的窗口更新ACK丢失,通信双方就会处于等待状态。为避免这种情况发生。发送端会采用一个持续计时器间歇性的查询接收端,看其窗口是否已经增长。
持续计时器会触发窗口探测的传输,强制要求对端返回ACK。 窗口探测包 包含一个字节数据,采用TCP传输,因此可以避免窗口更新丢失导致的死锁。因为包含一个字节数据Seq改变,接受端必须处理,如果接受就会ACK。窗口大小还是0,那么就会丢弃该报,没有响应。这时候发送端会持续的发送窗口探测包。
当接收端通告窗口较小,或者发送端发送的数据较小。这样数据报的有效携带率小,耗费网络资源多。
避免方法
以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补
TCP握手是建立一个可靠的数据传输连接的过程,一次完整的TCP握手需要3个步骤:SYN、SYN-ACK和ACK。假设网络延迟为RTT(Round Trip Time),那么TCP握手需要的时间可以分成以下几个步骤:1 发送SYN包。客户端向服务器发送一个SYN包,请求建立连接。这个包往返时间需要RTT。
2 接收SYN包并发送SYN-ACK包。服务器接收到客户端的SYN包后,会发送一个SYN-ACK包作为响应。这个包往返时间也需要RTT。
3 接收SYN-ACK包并发送ACK包。客户端接收到服务器的SYN-ACK包之后,发送一个ACK包作为最后的确认。这个包往返时间同样需要RTT。
因此,一次TCP握手需要的时间最少是3倍RTT。同时,考虑到网络拥塞、路由器处理等因素,实际的时间可能会更长。如果要优化TCP握手的时间,可以采用一些技术手段,如TCP Fast Open、TCP Keepalive等谁说有200ms延时的?没有的。
但是TCPIP使用了延迟确认的技术来减小ACK确认包的数量。
即收到对方发送的数据之后,并不立即发送ACK确认,而是等待本方向对方发送数据时将ACK捎带过去。如果在指定时间内(一般使用200ms定时器,RFC要求不超过500ms)本方未向对方发送数据,则发送ACK确认包。在定时器中发送的确认包不一定是接到对方的数据的200ms之后,因为是定时器,所以有可能距上一次定时器触发已经过去了199ms,那么这个确认包将在1ms内发送。
重点在于这一句:等待本方向对方发送数据时将ACK捎带过去问题现象 :
在高并发的压力测试时候,有时候会TPS不稳定或者上不去的现象,同时观察到队列产生大量的TIME_WAIT。
基本的分析思路:
使用netstat -an|find "TCP",发现大量的TIME_WAIT状态的队列。以至于部分客户端连接不上去,导致TPS不稳定或者上不去,成功率下降。
发现这种情况表示有较多的队列在等待,原因是服务器端或者客户端的连接数有限制。
可能的情况有:服务器系统端口数量不够。
我们先来看一张图:
TCP连接的建立可以简单的称为三次握手,而连接的中止则可以叫做四次握手。
建立连接
在TCP/IP协议中,TCP协议提供可靠的连接服务,采用三次握手建立一个连接。
第一次握手:建立连接时,客户端发送syn包(syn=j)到服务器,并进入SYN_SEND状态,等待服务器确认;
第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态;
第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手。
完成三次握手,客户端与服务器开始传送数据,也就是ESTABLISHED状态。
结束连接
TCP有一个特别的概念叫做half-close,这个概念是说,TCP的连接是全双工(可以同时发送和接收)连接,因此在关闭连接的时候,必须关闭传和送两个方向上的连接。客户机给服务器一个FIN为1 的TCP报文,然后服务器返回给客户端一个确认ACK报文,并且发送一个FIN报文,当客户机回复ACK报文后(四次握手),连接就结束了。
LISTEN: 表示监听状态。服务端调用了listen函数,可以开始accept连接了
SYN_SENT:表示客户端已经发送了SYN报文。当客户端调用connect函数发起连接时,首先发SYN给服务端,然后自己进入SYN_SENT状态,并等待服务端发送ACK+SYN。
SYN_RCVD:表示服务端收到客户端发送SYN报文。服务端收到这个报文后,进入SYN_RCVD状态,然后发送ACK+SYN给客户端。
ESTABLISHED:表示连接已经建立成功了。服务端发送完ACK+SYN后进入该状态,客户端收到ACK后也进入该状态。
FIN_WAIT_1:表示主动关闭连接。无论哪方调用close函数发送FIN报文都会进入这个这个状态。
CLOSE_WAIT:表示被动关闭方等待关闭。当收到对方调用close函数发送的FIN报文时,回应对方ACK报文,此时进入CLOSE_WAIT状态。
FIN_WAIT_2:表示被动关闭方同意关闭连接。主动关闭连接方收到被动关闭方返回的ACK后,会进入该状态。
LAST_ACK:表示被动关闭方发送FIN报文后,等待对方的ACK报文状态,当收到ACK后进入CLOSED状态。
TIME_WAIT:表示收到对方的FIN报文并发送了ACK报文,就等2MSL后即可回到CLOSED状态了。如果FIN_WAIT_1状态下,收到对方同时带FIN标志和ACK标志的报文时,可以直接进入TIME_WAIT状态,而无须经过FIN_WAIT_2状态。
CLOSED:结束
TCP要保证在所有可能的情况下使得所有的数据都能够被投递。当你关闭一个socket时,主动关闭一端的socket将进入TIME_WAIT状态,而被动关闭一方则转入CLOSED状态,这的确能够保证所有的数据都被传输。当一个socket关闭的时候,是通过两端互发信息的四次握手过程完成的,当一端调用close()时,就说明本端没有数据再要发送了。这好似看来在握手完成以后,socket就都应该处于关闭CLOSED状态了。
但这有两个问题:
首先,我们没有任何机制保证最后的一个ACK能够正常传输。
第二,网络上仍然有可能有残余的数据包(wandering duplicates),我们也必须能够正常处理。
我们再来看看TIME_WAIT:
TIME_WAIT是TCP连接断开时必定会出现的状态。是没有办法避免掉的。
TCP连接是全双工的,因此每个方向必须单独进行关闭。客户端与服务器端建立TCP/IP连接后关闭socket,服务端连接的端口状态未TIME_WAIT主动关闭的一方在发送最后一个ACK后,就会进入TIME_WAIT状态。
总结主要的原因有两点:
1、防止上一次连接中的包,迷路后重新出现,影响新的连接
2、可靠的关闭TCP连接: 在主动关闭方发送最后一个ACK(FIN),有可能会丢失,这个时候被动方会重新发送FIN,如果这时主动方处于closed状态,就会响应RST而不是ACK。所以主动方要处于TIME_WAIT状态,而不是CLOSED。
修改的方法:
增加服务器端口数量或者增加服务器的数量
缩短超时时间
具体修改方法:
运行:regedit
系统注册表:\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters下,新建2个DWORD值:
MaxUserPort设置为:65534,缺省为5000;
TcpTimedWaitDelay设置为:30, 缺省为240。 ----缩短该时间 (单位:s)
>
欢迎分享,转载请注明来源:内存溢出
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)