套接字选项SO_RESUEADDR
即使端口处于2MSL状态,使用该选项,仍然能够在该端口建立连接。
服务器常会设置该选项,以防服务器重启。
TIME_WAIT状态时收到数据
时间等待错误
如果在TIME_WAIT时间内,收到了对端发送来的数据报(不是重置报文段都行),那么该状态将被破坏,称为时间等待错误。原因是,当收到报文段以后,通常Seq是旧的,所以本端就会发送ACK,对端已经关闭或者是别的连接,就会发送RST,导致TIME_WAIT状态被破坏。
但是许多系统规定,TIME_WAIT状态是不对重置报文段做出反应。
同时关闭
同时关闭两端同时发送FIN,两端又同时ACK。又同时进入TIME_WAIT
异常连接状态及处理
非常规的11中状态,可能因为进程崩溃或是其他原因之类的
静默时间
当处于TIME_WAIT的主机崩溃以后,重启,然后需要等待相当与一个MSL的时间才能建立新的连接。
这段时间成为静默时间。
重置报文段
当一段发现到达的报文段对相关连接(也就是进程,套接字对)而言不正确的时候,TCP就会发送一个重置报文段,从而导致对端的连接快速拆卸(也就是结束吧!)。
重置报文段要求
重置报文段的ACK位必须有,而且ACK的值必须在正确的窗口范围内,这样可以防止被攻击。
重置报文终止与FIN终止
FIN正常关闭一条连接成为有序释放,通常不会出现丢失数据的情况。
重置报文段终止一条连接成为终止释放。重置报文段在任何时候都可以发送,代替FIN来终止连接,且不学校对端ACK
终止报文段特性:
- 任何排队的数据都将被抛弃,一个重置报文段立即被发出。
- 重置报文段的接收方会说明通信另一端采用了终止连接的方式而不是一次正常关闭。API必须提供一种实现上述终止行为的方式取代正常的关闭连接
发生情况
- 对没有在监听的端口发起连接请求
当连接请求到一端的时候,该端没的端口上没有进程在监听,TCP的话就会发从一个重置报文段。而UDP则会生成一个目标地不可达的ICMP。 -
半开链接
通信一端崩溃又重启,此时如果对端发送信息,那么本端会发送重置报文。
套接字选项SO_LINGER
此选项指定函数close对面向连接的协议如何操作(如TCP)。内核缺省close操作是立即返回,如果有数据残留在套接口缓冲区中则系统将试着将这些数据发送给对方。
参考文章1,参考文章2
当该数值设置为0,那么也意味着,不会再连接终止之前为了确保本端缓存中的数据都发送出去而等待。
TCP超时重传
TCP拥有两套独立鸡翅来完成重传,一、基于时间,二、给予确认信息ACK
TCP在发送数据时会设置计时器,如果计时器超时认为受到数据确认信息,就会引发相应的超时,或给予计时器的重传操作,计时器超时时成为重传超时(RTO)。
TCP累计确认无法返回新的ACK,或者当ACK包含选择确认信息(SACK)时,表明出现书序数据报,空洞。就会引起快速重传。
基于时间的超时重传
超时重传计时器的设置
TCP超时和重传的基础是如何根据给点连接RTT设置RTO。
若RTO短与RTT,那么没分都会重传,反之,整个网络利用率就会随之下降。
RTT样本:TCP在收到数据后会返回确认信息ACK,该信息中携带一个字节的数据,测量传输该确认需要的时间,该测量结果成为RTT样本。
每个连接的RTT军独立计算。
如何根据RTT来设置RTO,有如下的方法
经典方法
平滑RTT估计值SRTT
公式:SRTT=a*SRTT+(1-a)RTT
,a取0.8-0.9
。
当TCP运行在RTT变化较大的网络中,无法取得期望的结果。
标准方法
以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补
快速重传
带选择确认的重传
伪超时与重传
因为丢失ACK,或者实际RTT显著增长,可能出现伪超时的现象。
以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补
包失序与包重复
造成包失序的原因
每个包可以选择各自的传送路径。某些高级路由器的采用多个并行数据链路,不同的处理演示也会导致包的离开顺序和到达顺序不匹配
包的失序会造成重传,很近单嘛,前面一个小号的Seq没到达,后面的先到达,那么ACK就会 重复
包重复
包重组
当TCP超时重发是,循序执行重新租宝,发送送一个更大的报文段提高性能,不超过MSS和MTU。
出现在每次传送的包较小,又丢包的情况
数据流与窗口管理
交互式通信
SSH
每个交互键通常会生成一个单独的数据报,也就是每个按键是独立传输的。
ssh调用一个shell,对客户端输入的字符做出辉县,因此,每个字符生成4个tcp数据段,客户端的交互按键输入,服务器对按键的ACK,服务器生成的辉县,客户端对回显的ACK。通常第二段和第三段合并,成为捎带延时确认。
PSH位设置,意味着发送端的缓存为空,也就是没什么可以发送了。
延时确认
许多情况下,TCP并不是对每个到来的包都单独的ACK,利用累计ACK可以确认之前的ACK。累计确认可以允许TCP延时一段时间发送ACK,以便将ACK和相同方向上需要传输的数据结合发。这种捎带传输的方法常用于批量数据传输。
不能任意的延迟ACK,会造成重传。同时当失序发生时,必须立刻传送ACK。
系统可以设置,一般延时为200-600毫秒。
Nagle算法
该算法要求,当TCP连接中有在传数据(那些已发送,但是未确认的数据)时,小的报文段就不能被发送,知道所有的数据都受到ACK。并且受到ACK后,TCP收集这些小的数据,整合到一个报文段中发送。
这种方法破事TCP遵循等停规程,只有收到所有传送数据的ACK后才能继续发送新数据。
该算法的不同之处在于他实现了自时钟控制,ACK返回越快,传输也越快。在相对高延迟的广域网中,更需要减小小报文的数目,该算法使得单位时间内发送的报文数目更少,RTT控制发包速率。
该算法减少小包数目的同时,也增大了传输时延,也就是总的发送时间。
流量控制与窗口管理
窗口大小表明本端可用缓存大小,对端传送的数据不应该超过改大小。
也表明对端发送的数据的最大大小为TCP头部ACK号和窗口大小字段之和。
也就是Seq = ACK+MSS
滑动窗口
发送窗口
滑动窗口TCP活动的两端都维护一个发送窗口结构和接受窗口结构。
TCP以字节为单位维护窗口结构。
每个TCP报文段都包含ACK号和窗口通告信息,TCP发送端可以据此调节窗口结构。
窗口左边界不能左移。
窗口的动作分为,关闭(收到ACK,左边右移),打开(MSS扩大,右边右移),收缩(MSS减小,右边左移)
当收到ACK号增大,而MSS不变时窗口向前滑动
当当左边界与右边界相等时,成为零窗口,此时发送端不能在发送新的数据,这种情况下,TCP开始探测对端窗口,伺机增大窗口。
接受窗口
接受窗口接受窗口也有左边界和右边界,但窗口内的字节并没有区分,到达序号小于左边便捷,被认为是重复的,丢弃!超过右边界的则超出处理范围,丢弃!只有Seq在窗口内的包才能被确认,SACK的包也能被确认,因为对端发送的包的最大大小为ACK+MSS,因此整个包的大小不会超过MSS,同时MSS一般都不是太小,不会缓冲区溢出。
因此,上面提到那些,不同连接的包因为网络阻塞,最后又到达新连接的包,大概率是要被丢弃的。
接受窗口只有收到左边界序号的数据时才会向右滑动。
零窗口
当接受窗口值变为0是,可以邮箱的组织发送端继续发送,知道窗口大小回复为非0值。当接收端窗口得到可用空间是,就会给发送端传输一个窗口更新,告知器可以继续发送数据,这样的这样的窗口更新通常不包含数据,成为纯ACK,因此不能保证传输的可靠性。
如果一端的窗口更新ACK丢失,通信双方就会处于等待状态。为避免这种情况发生。发送端会采用一个持续计时器间歇性的查询接收端,看其窗口是否已经增长。
持续计时器会触发窗口探测的传输,强制要求对端返回ACK。窗口探测包包含一个字节数据,采用TCP传输,因此可以避免窗口更新丢失导致的死锁。因为包含一个字节数据Seq改变,接受端必须处理,如果接受就会ACK。窗口大小还是0,那么就会丢弃该报,没有响应。这时候发送端会持续的发送窗口探测包。
糊涂窗口SWS
当接收端通告窗口较小,或者发送端发送的数据较小。这样数据报的有效携带率小,耗费网络资源多。
避免方法
- 接收端
不应该通告小的窗口值。这个没看懂啊。 - 发送端
不应发送晓得报文段,而应该采用Nagle算法控制何时发送。直到:数据报到达MSS全场,或者数据段长度超过最大窗口值的一半。
紧急机制
以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补以后再补
网友评论