TCP协议分析:通信建立、可靠性(确认机制、重传机制、流量控制、拥塞窗口)、滑动窗口

 这是一个很有意思的问题~  

  首先,我们要知道TCP是全双工的,即客户端在给服务器端发送信息的同时,服务器端也可以给客户端发送信息。而半双工的意思是A可以给B发,B也可以给A发,但是A在给B发的时候,B不能给A发,即不同时,为半双工。 单工为只能A给B发,B不能给A发; 或者是只能B给A发,不能A给B发。

  我们假设A和B是通信的双方。我理解的握手实际上就是通信,发一次信息就是进行一次握手

  • 第一次握手: A给B打电话说,你可以听到我说话吗?
  • 第二次握手: B收到了A的信息,然后对A说: 我可以听得到你说话啊,你能听得到我说话吗?  
  • 第三次握手: A收到了B的信息,然后说可以的,我要给你发信息啦!

  在三次握手之后,A和B都能确定这么一件事: 我说的话,你能听到; 你说的话,我也能听到。 这样,就可以开始正常通信了。

  注意: HTTP是基于TCP协议的,所以每次都是客户端发送请求,服务器应答,但是TCP还可以给其他应用层提供服务,即可能A、B在建立链接之后,谁都可能先开始通信。

    

  如果两次,那么B无法确定B的信息A是否能收到,所以如果B先说话,可能后面的A都收不到,会出现问题 。

  如果四次,那么就造成了浪费,因为在三次结束之后,就已经可以保证A可以给B发信息,A可以收到B的信息; B可以给A发信息,B可以收到A的信息。

  


  那么三次握手在正式情况下都做了什么呢? 

第一次握手:

客户端发送一个TCP的SYN标志位置1的包指明客户打算连接的服务器的端口,以及初始序号X,保存在包头的序列号(Sequence Number)字段里

第二次握手

服务器发回确认包(ACK)应答。即SYN标志位和ACK标志位均为1同时,将确认序号(Acknowledgement Number)设置为客户的I S N加1以.即X+1。

第三次握手

客户端再次发送确认包(ACK) SYN标志位为0,ACK标志位为1.并且把服务器发来ACK的序号字段+1,放在确定字段中发送给对方.并且在数据段放写ISN的+1

即SYN就是询问: 你能听得到吗?  ACK就是回到: 我能听得到啊。 


TCP四次挥手的过程:

四次挥手:
A:“喂,我不说了 (FIN)。”A->FIN_WAIT1

B:“我知道了(ACK)。等下,上一句还没说完。Balabala…..(传输数据)”B->CLOSE_WAIT | A->FIN_WAIT2

B:”好了,说完了,我也不说了(FIN)。”B->LAST_ACK

A:”我知道了(ACK)。”A->TIME_WAIT | B->CLOSED

A等待2MSL,保证B收到了消息,否则重说一次”我知道了”,A->CLOSED

这样,通过四次挥手,可以把该说的话都说完,并且A和B都知道自己没话说了,对方也没花说了,然后就挂掉电话(断开链接)了 。 

 TCP协议栈的弱点

TCP连接的资源消耗,其中包括:数据包信息、条件状态、序列号等。通过故意不完成建立连接所需要的三次握手过程,造成连接一方的资源耗尽。

通过攻击者有意的不完成建立连接所需要的三次握手的全过程,从而造成了C机器的资源耗尽。序列号的可预测性,目标主机应答连接请求时返回的SYN/ACK的序列号时可预测的。

 TCP可靠性保证:

· 确认应答机制 
· 超时重传机制 
· 流量控制 
· 拥塞窗口

确认应答机制
在将这部分的内容之前我们应该首先知道的一点就是,在TCP中,TCP将每个字节的数据都进行了编号,即为序列号(对每一个数据的编号)。
 
 这里写图片描述这里写图片描述
由图分析:当主机1给主机2发送了1~1000这么多数据时,主机2如果收到了就会给主机1应答(ACK报文段,每一个ACK都带有对应的确认序列号),表示你给我发的1~1000的数据我已经全部收到了(收到哪些数据),下次你再给我发就给我从1001数据开始发(下次从哪里开始发)。那么主机1收到应答之后就知道对方已经收到了1~1000的全部数据,所以再一次发送数据的时候他就会从1001开始发,后面都是依此类推的情况。

当然了,当我们的主机1给主机2发送了数据之后,经过一端时间主机1并没有收到主机2的应答的情况也是有的,所以这个时候为了确保数据的准确到达,TCP就有了超时重传机制。
超时重传机制
主机1没有收到主机2的确认应答有以下两种情况:
1、数据根本就没有传送到达主机2,因此主机2就不会回传一个确认应答的报文。
 这里写图片描述
由图分析:主机1给主机2发送了数据,可能因为其他的原因数据无法到达主机2.(比如网络拥堵)。这个时候主机1等待了一个特定的时间间隔之后发现主机2还没有确认应答,于是就再一次将上一次的数据重新发送过去。

2、主机2收到了数据,也回传了确认应答报文,但是该报文丢失了。
 这里写图片描述
由图分析:主机2收到了主机1发来的数据,但是发给主机1的确认应答并没有准时到达主机1,所以主机1也会因为没有收到确认应答而再次重新将数据发送过去。但实际情况却是我们的主机2第一次就已经收到了主机1的数据。但是主机1依旧会重发数据已确保主机2已经收到数据,从而进行下一次的数据转发。可想而知主机2就会收到很多的重复数据,但是重复的数据显然是不需要的,那么TCP协议就需要能够识别那些重复的数据并且要将冲符的数据丢弃掉,这个时候序列号就发挥他的一项作用了——去重。每一个数据都有自己的序列号,如果主机2收到重复的数据那么必然机会产生多个序列号相同的数据,那么序列号相同的数据就必然是重复的数据。

我们提到一个特定的时间间隔,这个时间又是如何规定的?


  最理想的情况下,找到一个最小的时间保证确认应答一定能在这时间内返回
  但是这个时间的长短,随着网络环境的不同,也是有差异的。
  如果超时时间设得太长,会影响整体的重传效率
  如果超时时间设的太短,有可能平凡的发送冲符的数据包。
  TCP为了抱枕个无论在何种环境下都能比较高性能的通信,因此会动态计算这个最大超时时间:
  Linux中,超时以500ms为一个单位进行控制,每次判定超时重发的超时时间都是500ms的整数倍。
  如果重发一次,任然得不到应答,就等待2*500ms后在进行重传
  如果还得不到应答,等待4*500ms再重传,一次类推,以指数形式递增。
  累积到一定的重传次数,TCP认为网络或者对端主机出现异常,就会强制关闭连接。


流量控制
接收端处理数据的速度是优先的,如果发送端发的太快,导致接收端的缓冲区被打满,这个时候如果发送端继续发送就会造成丢包,继而引起丢包重传等一系列连锁反应。因此TCP支持根据接收端的处理能力,来决定发送端的发送速度,这个机制就叫做流量控制。


  接收端将自己可以接受的缓冲区大小放入TCP首部中的“窗口大小”字段,通过ACK段通知发送端;
  窗口大小字段越大,说明网络的吞吐量越高
  接收端一旦发现自己的缓冲区快满了就会将窗口大小设置成一个更小的值通知发送端。
  发送端接收到窗口大小以后,就会减慢自己的发送速度。
  如果接收缓冲区满了,就会将窗口置为0,这时发送方不再发送数据。
  但是需要定期的发送一个试探窗口,,目的是为了取探测数据段,是接收端把窗口大小告诉发送端。

这里写图片描述


接收端是如何把窗口大小告诉发送端的呢?现在,我们回过头去看一看,在上一篇博客中我们给出了TCP的报头格式,在TCP的首部中有一个16位的窗口大小的字段,就是存放的窗口大小的信息。另外在TCP的首部中的40字节选项中还包含了一个窗口扩大因子M,实际的窗口大小是窗口字段的值左移M位。

拥塞窗口
在后面会讲到TCP提高性能的滑动窗口,滑动窗口能够高效可靠的发送大量的数据,但是如果在一开始就发送大量的数据任然可能引发问题。要知道在网络上有很多的计算机,有可能当前的网络状态已经很拥堵,在不清楚当前的网络状态下,贸然发送大量的数据,这样对于已经很拥堵的网络来说无疑是雪上加霜。
由此,TCP引入了慢启动机制:先发送少量的数据,由此取探测当前的网络的拥堵状态,在决定按照多大的速度传输数据。

这里写图片描述

  拥塞窗口:
  发送开始的时候定义拥塞窗口大小为1
  每当收到一个ACK应答以后拥塞窗口加1
  每次发送数据包的时候,将拥塞窗口和接收端主机反馈的窗口大小作比较,取较小值作为实际发送的窗口。
  如图,拥塞窗口的增长速度呈指数形式增长,我们提到说慢启动,只是说出事的时候慢而已,但是增长速度非常的快。为了增长的不呢么快,因此我们不能让拥塞窗口单纯的加倍,这里引入一个慢启动的阈值,当同色窗口超过这个阈值的时候,不再按照指数方式增长,而是改为按照线性的方式增长。
  当TCP开始启动的时候,慢启动阈值等于窗口最大值,在每次超时重发的时候,慢启动阈值会变成原来的一半,同时拥塞窗口置为1。


少量的丢包,仅仅只会触发超时重传,而大量的丢包就认为是网络拥堵,当TCP通信开始后,网络吞吐量会逐渐的上升,随着网络发生拥堵,吞吐量会立刻下降,拥塞控制说到底就是TCP协议想尽可能快的将数据传输给对方,但又要避免给网络造成太大的压力的折中解决办法。

总结一下:
为了确保可靠的数据传输,TCP协议通过连接管理机制,确认应答机制,流量控制以及拥塞控制这些方法让可靠性得以很大程度上的保证,另外,序列号保证了数据的按序到达,就知道哪些数据已经收到,那些没有收到需要重传。而校验和通过CRC校验,如果接收端校验不通过则认为数据有问题,此举也保证了数据的可靠性传输。

 

TCP的滑动窗口机制 
      TCP这个协议是网络中使用的比较广泛,他是一个面向连接的可靠的传输协议。既然是一个可靠的传输协议就需要对数据进行确认。TCP协议里窗口机制有2种:一种是固定的窗口大小;一种是滑动的窗口。这个窗口大小就是我们一次传输几个数据。对所有数据帧按顺序赋予编号,发送方在发送过程中始终保持着一个发送窗口,只有落在发送窗口内的帧才允许被发送;同时接收方也维持着一个接收窗口,只有落在接收窗口内的帧才允许接收。这样通过调整发送方窗口和接收方窗口的大小可以实现流量控制。

      TCP滑动窗口技术通过动态改变窗口大小来调节两台主机间数据传输。每个TCP/IP主机支持全双工数据传输,因此TCP有两个滑动窗口:一个用于接收数据,另一个用于发送数据。TCP使用肯定确认技术,其确认号指的是下一个所期待的字节。 假定发送方设备以每一次三个数据包的方式发送数据,也就是说,窗口大小为3。发送方发送序列号为1、2、3的三个数据包,接收方设备成功接收数据包,用序列号4确认。发送方设备收到确认,继续以窗口大小3发送数据。当接收方设备要求降低或者增大网络流量时,可以对窗口大小进行减小或者增加,本例降低窗口大小为2,每一次发送两个数据包。当接收方设备要求窗口大小为0,表明接收方已经接收了全部数据,或者接收方应用程序没有时间读取数据,要求暂停发送。发送方接收到携带窗口号为0的确认,停止这一方向的数据传输。

   


我们可以看下面一张图来分析一下固定窗口大小有什么问题。 
 
这里我们可以看到假设窗口的大小是1,也是就每次只能发送一个数据只有接受方对这个数据进行确认了以后才能发送第2个数据。我们可以看到发送方每发送一个数据接受方就要给发送方一个ACK对这个数据进行确认。只有接受到了这个确认数据以后发送方才能传输下个数据。 这样我们考虑一下如果说窗口过小,那么当传输比较大的数据的时候需要不停的对数据进行确认,这个时候就会造成很大的延迟。如果说窗口的大小定义的过大。我们假设发送方一次发送100个数据。但是接收方只能处理50个数据。这样每次都会只对这50个数据进行确认。发送方下一次还是发送100个数据,但是接受方还是只能处理50个数据。这样就避免了不必要的数据来拥塞我们的链路。所以我们就引入了滑动窗口机制,窗口的大小并不是固定的而是根据我们之间的链路的带宽的大小,这个时候链路是否拥护塞。接受方是否能处理这么多数据了。  
我们看看滑动窗口是如何工作的。我们看下面几张图。 

 

 
首先是第一次发送数据这个时候的窗口大小是根据链路带宽的大小来决定的。我们假设这个时候窗口的大小是3。这个时候接受方收到数据以后会对数据进行确认告诉发送方我下次希望手到的是数据是多少。这里我们看到接收方发送的ACK=3(这是发送方发送序列2的回答确认,下一次接收方期望接收到的是3序列信号)。这个时候发送方收到这个数据以后就知道我第一次发送的3个数据对方只收到了2个。就知道第3个数据对方没有收到。下次在发送的时候就从第3个数据开始发。这个时候窗口大小就变成了2 。 
 

这个时候发送方发送2个数据。 

 
看到接收方发送的ACK是5就表示他下一次希望收到的数据是5,发送方就知道我刚才发送的2个数据对方收了这个时候开始发送第5个数据。 
这就是滑动窗口的工作机制,当链路变好了或者变差了这个窗口还会发生变话,并不是第一次协商好了以后就永远不变了。                 
滑动窗口协议 
滑动窗口协议,是TCP使用的一种流量控制方法。该协议允许发送方在停止并等待确认前可以连续发送多个分组。由于发送方不必每发一个分组就停下来等待确认,因此该协议可以加速数据的传输。 
只有在接收窗口向前滑动时(与此同时也发送了确认),发送窗口才有可能向前滑动。    
收发两端的窗口按照以上规律不断地向前滑动,因此这种协议又称为滑动窗口协议。    
当发送窗口和接收窗口的大小都等于1时,就是停止等待协议。

猜你喜欢

转载自blog.csdn.net/qq_18144747/article/details/86662788
今日推荐