tcp ,基础概念 三次握手,4次挥手

一。为什么建链接要3次握手,断链接需要4次挥手?

  • 对于建链接的3次握手:主要是要初始化Sequence Number 的初始值。通信的双方要互相通知对方自己的初始化的Sequence Number(缩写为ISN:Inital Sequence Number)——所以叫SYN,全称Synchronize Sequence Numbers。也就上图中的 x 和 y。这个号要作为以后的数据通信的序号,以保证应用层接收到的数据不会因为网络上的传输的问题而乱序(TCP会用这个序号来拼接数据)。
  • 对于4次挥手:其实你仔细看是2次,因为TCP是全双工的,所以,发送方和接收方都需要Fin和Ack。只不过,有一方是被动的,所以看上去就成了所谓的4次挥手。如果两边同时断连接,那就会就进入到CLOSING状态,然后到达TIME_WAIT状态。

二。服务器保持了大量TIME_WAIT状态

这种情况比较常见,一些爬虫服务器或者WEB服务器(如果网管在安装的时候没有做内核参数优化的话)上经常会遇到这个问题,这个问题是怎么产生的呢?

从 上面的示意图可以看得出来,TIME_WAIT是主动关闭连接的一方保持的状态,对于爬虫服务器来说他本身就是“客户端”,在完成一个爬取任务之后,他就 会发起主动关闭连接,从而进入TIME_WAIT的状态,然后在保持这个状态2MSL(max segment lifetime)时间之后,彻底关闭回收资源。为什么要这么做?明明就已经主动关闭连接了为啥还要保持资源一段时间呢?这个是TCP/IP的设计者规定 的,主要出于以下两个方面的考虑:

1.防止上一次连接中的包,迷路后重新出现,影响新连接(经过2MSL,上一次连接中所有的重复包都会消失)
2. 可靠的关闭TCP连接。在主动关闭方发送的最后一个 ack(fin) ,有可能丢失,这时被动方会重新发fin, 如果这时主动方处于 CLOSED 状态 ,就会响应 rst 而不是 ack。所以主动方要处于 TIME_WAIT 状态,而不能是 CLOSED 。另外这么设计TIME_WAIT 会定时的回收资源,并不会占用很大资源的,除非短时间内接受大量请求或者受到攻击。

3、通过上面的ISN的描述,相信你也知道MSL是怎么来的了。我们注意到,在TCP的状态图中,从TIME_WAIT状态到CLOSED状态,有一个超时设置,这个超时设置是 2*MSL(RFC793定义了MSL为2分钟,Linux设置成了30s)为什么要这有TIME_WAIT?为什么不直接给转成CLOSED状态呢?主要有两个原因:1)TIME_WAIT确保有足够的时间让对端收到了ACK,如果被动关闭的那方没有收到Ack,就会触发被动端重发Fin,一来一去正好2个MSL,2)有足够的时间让这个连接不会跟后面的连接混在一起(你要知道,有些自做主张的路由器会缓存IP数据包,如果连接被重用了,那么这些延迟收到的包就有可能会跟新连接混在一起)。你可以看看这篇文章《TIME_WAIT and its design implications for protocols and scalable client server systems

三。TCP重传机制

TCP要保证所有的数据包都可以到达,所以,必需要有重传机制。

注意:接收端给发送端的Ack确认只会确认最后一个连续的包,比如,发送端发了1,2,3,4,5一共五份数据,接收端收到了1,2,于是回ack 3,然后收到了4(注意此时3没收到),此时的TCP会怎么办?我们要知道,因为正如前面所说的,SeqNum和Ack是以字节数为单位,所以ack的时候,不能跳着确认,只能确认最大的连续收到的包,不然,发送端就以为之前的都收到了。

四。快速重传机制

于是,TCP引入了一种叫Fast Retransmit 的算法,不以时间驱动,而以数据驱动重传。也就是说,如果,包没有连续到达,就ack最后那个可能被丢了的包,如果发送方连续收到3次相同的ack,就重传。Fast Retransmit的好处是不用等timeout了再重传。

比如:如果发送方发出了1,2,3,4,5份数据,第一份先到送了,于是就ack回2,结果2因为某些原因没收到,3到达了,于是还是ack回2,后面的4和5都到了,但是还是ack回2,因为2还是没有收到,于是发送端收到了三个ack=2的确认,知道了2还没有到,于是就马上重转2。然后,接收端收到了2,此时因为3,4,5都收到了,于是ack回6。

五。D-SACK,有这么几个好处:
 

  • 1)可以让发送方知道,是发出去的包丢了,还是回来的ACK包丢了。
  • 2)是不是自己的timeout太小了,导致重传。
  • 3)网络上出现了先发的包后到的情况(又称reordering)
  • 4)网络上是不是把我的数据包给复制了。


知道这些东西可以很好得帮助TCP了解网络情况,从而可以更好的做网络上的流控。Linux下的tcp_dsack参数用于开启这个功能(Linux 2.4后默认打开)

 

1:滑动窗口

2:流量控制
3:拥塞控制
4:Nagle算法
5:捎带ACK的发送方式
这个策略是说,当主机收到远程主机的TCP数据报之后,通常不马上发送ACK数据报,而是等上一个短暂的时间,如果这段时间里面主机还有发送到远程主机的TCP数据报,那么就把这个ACK数据报“捎带”着发送出去,把本来两个TCP数据报整合成一个发送。一般的,这个时间是200ms。可以明显地看到这个策略可以把TCP数据报的利用率提高很多。

6.白痴综合征

滑窗机制有可能犯病,比如白痴窗口综合症(Silly Window Syndrome)。假设这样一种情形:接收方发布(advertise)一个小的窗口。发送方根据发布的窗口大小,发送一个小的片段。接收方的小窗口被填满,经过处理,接收方再宣布一个小的窗口…… 这就是“白痴窗口综合症”:TCP通信的片段中包含的数据量很小。在这样的情况下,TCP通信的片段所含的信息都很小,网络流量主要是TCP片段的头部,这样头重脚轻的TCP片段,会造成网络流量的浪费。
如果发送方不断发送小的片段,也会造成白痴窗口。为了解决这个问题,需要从两方面入手。TCP中有相关的规定,要求:

1》. 接收方宣告的窗口必须达到一定的尺寸,否则等待。
2》. 除了一些特殊情况,发送方发送的片段必须达到一定的尺寸,否则等待。特殊情况主要是指需要最小化延迟的TCP应用,比如命令行互动。

7. 重传

接收方(receiver)可以通过校验TCP片段头部中校验(checksum)区域来检验TCP片段是否出错。校验区域所在位置如下图所示。我们已经接触过了IP协议详解的校验算法。TCP片段的校验算法与之类似。IP协议只校验头部,TCP片段头部的校验会校验包括IP头部、TCP头部和TCP数据在内的整个序列,确保IP地址、端口号和其他相关信息正确。如果TCP片段出错,接收方可以简单的丢弃改TCP片段,也就相当于TCP片段丢失。

 

 

 

tcp ,基础概念 三次握手,4次挥手

tcp ,基础概念 三次握手,4次挥手

 

转载于:https://my.oschina.net/u/1388024/blog/375276