浅析TCP原理(窗口控制,三次握手四次挥手)

  • 1-TCP简述:

TCP协议是一种面向连接的、可靠的、基于字节流的传输层通信协议。

面向连接:TCP只能一对一连接,不能像UDP一样一对多,一对一,多对多的连接方式;

可靠性:TCP的可靠性可以说是因为他的三次握手,四次挥手

字节流:数据一般都是不可确认大小的,一般多大都是可以进行有序传输。

  • 2-TCP连接和断开:

在我们讲三次握手的时候前,我们首先要知道如何确定一个TCP连接,要确定一个TCP连接必须要知道源地址,源端口,目的地址,目的端口我们才能保障一个TCP连接。

2.1  首先我们说三次握手,如下图所示

1-首先客户端和服务端都处于closed状态,服务端主动监听某个端口,处于监听状态

2-客户端开始发送第一个SYN报文给服务端:客户端会随机产生一个序列号置于TCP头部的序列号字段中,同时将SYN置于1

3-服务端发送SYN+ACK报文:服务端接收到客户端的SYN报文,服务端也会随机产生一个序列号放置到序列号中,同时将客户端发过来报文中的序列号+1写入确认应答号字段中,TCP头部的SYN和ACK置于1,服务端的状态变为等待接收

4-客户端发送ACK报文:客户端接收到服务端的SYN+ACK报文后,将TCP头部的确认应答号字段填入服务端的序列号+1,并将ACK置于1发送给服务端,两者就此建立连接,双方的状态都变成建立连接

注意:序列号ISN(Initial Sequence Number)是随机产生的

TCP头部结构示图如下:

2.2什么是半连接队列,如图所示

半连接队列:服务器第一次收到客户端的 SYN 之后,就会处于 SYN_RCVD 状态,此时双方还没有完全建立其连接,服务器会把此种状态下请求连接放在一个队列里

全连接队列:已经完成三次握手,建立起连接的就会放在全连接队列中

2.3  为什么握手需要三次

 1-避免历史连接:

当客户端发送多个SYN报文的时候,不一定是按前后顺序的,有时候网络阻塞导致旧的报文比新的报文早到服务端,客户端可以根据服务端返回的SYN+ACK报文,基于自身的上下文来判断是否是一个历史连接,由此来中断连接。

2-同步客户端和服务端双方的序列号:

TCP是通过序列号和确认应答来提高可靠性的,他的作用:接收双方可以取出重复数据,也可以确认发出的数据包中那些对方收到

2.4  未收到确认应答数据一定丢失吗?

未收到确认应答有两种可能性,第一种就是发送到服务端途中数据包丢失,这种情况客户端在特定的时间间隔内没有收到服务端确认应答,则会对数据进行重发;第二种是服务端接收到数据,但是在再返回应答的途中丢失,这种情况客户端会再次发送报文,但服务端已经收到数据了,当再有相同数据送达他会放弃

2.5  SYN攻击

1- SYN简介:

服务器端的资源分配是在二次握手时分配的,而客户端的资源是在完成三次握手时分配的,所以服务器容易受到SYN洪泛攻击。SYN攻击就是Client在短时间内伪造大量不存在的IP地址,并向Server不断地发送SYN包,Server则回复确认包,并等待Client确认,由于源地址不存在,因此Server需要不断重发直至超时,这些伪造的SYN包将长时间占用未连接队列,导致正常的SYN请求因为队列满而被丢弃,从而引起网络拥塞甚至系统瘫痪。SYN 攻击是一种典型的 DoS/DDoS 攻击。如图所示

2- 解决方法:

  1.通过修改linux内核参数,控制队列大小

  2.SYN cookies技术

2.6  四次挥手:

   1-客户端发送FIN报文:当客户端需要关闭时,发送一个FIN报文,TCP头部FIN位置标位1,客户端进入FIN_WAIT_1状态

   2-服务端发送ACK应答报文:当服务端收到客户端的FIN报文后,服务端向客户端发送ACK应答报文,服务端进入CLOSED_WAIT状态

   3-客户端接收到来自于服务端的ACK报文后进入FIN_WAIT_2状态,当服务端处理完数据后,也向客户端发送FIN报文,服务端进入LAST_ACK状态

   4-客户端收到服务端的FIN报文后,也回一个ACK报文给客户端,客户端进入TIME_WAIT状态

   5-服务端收到来自于客户端的报文后,进入CLOSED状态,到这一步服务端完成连接关闭

   6-客户端经历2MSL后,也进入CLOSED状态,到这里客户端也完成连接关闭

2.7  为什么需要等待2MSL(MSL: Maximum Segment Lifetime    报文最大生存时间

2MSL的原因:

网络中可能存在来自发送方的数据包,当这些发送方的数据包被接收方处理后又会向对方发送响应,所以一来一回需要等待 2 倍的时间。

等待2MSL原因:

1 -保证客户端发送的最后一个ACK报文段能够到达服务端:

这个ACK报文段有可能丢失,使得处于LAST-ACK状态的服务端收不到对已发送的FIN+ACK报文段的确认,服务端超时重传FIN+ACK报文段,而客户端能在2MSL时间内收到这个重传的FIN+ACK报文段,接着客户端重传一次确认,重新启动2MSL计时器,最后客户端和服务端都进入到CLOSED状态,若客户端在TIME-WAIT状态不等待一段时间,而是发送完ACK报文段后立即释放连接,则无法收到服务端重传的FIN+ACK报文段,所以不会再发送一次确认报文段,则服务端无法正常进入到CLOSED状态。

2- 防止“已失效的连接请求报文段”出现在本连接中:

客户端在发送完最后一个ACK报文段后,再经过2MSL,就可以使本连接持续的时间内所产生的所有报文段都从网络中消失,使下一个新的连接中不会出现这种旧的连接请求报文段

  • 3-重发超时

      3.1 TCP是以段(片)为单位发送的

            TCP在传送大量的数据时,是以MSS的大小将数据进行分割传输(重发时也是以MSS为单位),在传输过程中最大的消息长度刚好时等于MTU,这样IP层就不会进行分割。

MTU(Maximum  Transmission  Unit):一个网络包最大的数据长度
MSS(Maximum  Segment Size):除去IP头部,TCP头部,一个网络所容纳最大的TCP数据长度。MSS是在三次握手的时候写入TCP头部
MSS选项中

     3.2  IP层有分片,TCP为什么还需MSS

     如果TCP 的整个报文(头部 + 数据)交给 IP 层进行分片,会有什么异常呢?

当 IP 层有一个超过 MTU 大小的数据(TCP 头部 + TCP 数据)要发送,那么 IP 层就要进行分片,把数据分片成若干片,保证每一个分片都小于 MTU。把一份 IP 数据报进行分片以后,由目标主机的 IP 层来进行重新组装后,在交给上一层 TCP 传输层。这看起来井然有序,但这存在隐患的,那么当如果一个 IP 分片丢失,整个 IP 报文的所有分片都得重传。因为 IP 层本身没有超时重传机制,它由传输层的 TCP 来负责超时和重传。当接收方发现 TCP 报文(头部 + 数据)的某一片丢失后,则不会响应 ACK 给对方,那么发送方的 TCP 在超时后,就会重发「整个 TCP 报文(头部 + 数据)」。因此,可以得知由 IP 层进行分片传输,是非常没有效率的。所以,为了达到最佳的传输效能 TCP 协议在建立连接的时候通常要协商双方的 MSS 值,当 TCP 层发现数据超过 MSS 时,则就先会进行分片,当然由它形成的 IP 包的长度也就不会大于 MTU ,自然也就不用 IP 分片了。

   3.3 重发超时

    TCP数据包的分段是经过不同的线路到达的,所以在网络环境的不同的往返使劲啊可能产生大幅度的摇摆。在Unix和widows系统中,超时都是以0.5秒为单位进行控制,所以重发超时一般都是0.5秒的倍数。最初数据包还不知道往返的时间,所以重发超时也一般设置为6秒左右。如果数据被重发后还是收不到确认应答,则再次进行发送,等待确认应答的时间也会以2倍,4倍的指数函数延长。

  • 4- 窗口控制

    1- 为什么需要窗口控制

    在上面讲到TCP没发送一个段都需要一次确认应答的处理,这种处理是有一个缺点的:包往返的时间(RTT)越长通行能力越差。解决这个问题TCP采用了窗口,每次发送不再是以每个分段了,而是以更大的单位(假设每次4个段,可以了解为批量操作)

   2-窗口控制与重发机制

    在之前每个段发送的时候会出现丢失数据,那么在窗口控制中如果出现数据丢失怎么办?

    第一种情况:客户端发送数据到服务端,服务端接收到数据但是服务端再给客户端返回ACK时丢失,这种情况无需重发

    第二种情况:客户端发送数据到服务端,在发送的途中把数据(某些报文数据丢失)给丢失了,客户端会多次接收到服务端的确认应答,如果连续三次收到同个确认应答,则会将对应的数据进行重发,这种机制称为高速重发控制。

  3- 流量控制

      3.1-可能出现的问题

      服务端接收到客户端发来一个数据包,这个数据包可能在处理其他的问题上需要花费一定的时间。有时候会在这个数据包处理的时候会花费一定的时间,甚至在高负荷的情况下无法接受其他的数据包。如果将数据包丢失那就回促发重发机制,导致网络流量的浪费。

      3.2-解决这个问题

       在TCP头部中,有一个字段用来通知窗口大小(字段越大说明网络的吞吐量越大)。服务端将自己可以接收的缓冲区大小放入这个字段通知客户端,另外注意的是客户端也会时不时发送一个窗口探测的数据段,这个数据段就只有一个字节,用来获取最新的窗口大小信息。当服务端的缓冲区一旦面临数据溢出的时候,窗口大小的值也会随之被设置一个更小的值通知客户端,从而控制数量发送的量。客户端根据服务端的指示来进行对发送数据的量进行控制,这个就是流量控制。

   4- 拥塞控制

       4.1 出现的问题

             在网络出现拥堵的时候,如果突然发送一个较大的数据包,那么极有可能会导致网络瘫痪

       4.2  解决问题

              为了防止上述的问题出现,TCP会在通信开始的时候会通过一个慢启动的算法得出数据,对发送的数据量进行控制。

              定义一个拥塞窗口来调节客户端要发送的数据量,在慢启动的时候将拥塞窗口设置为1一个数据段(1MSS)发送数据,之后发送数据的时候将拥塞窗口的大小与服务端通知的窗口大小做比较,取他们的较小的值来做发送的数据量。

             拥塞窗口的大小随着每次数据包的往返,也会以1,2,4等指数函数增长,为了防止出现拥堵状况激增甚至导致网络拥塞,引入慢启动阈值。只要拥塞窗口的值大于这个阈值,在每次收到一次确认应答的时候,只允许按一下公式进行放大拥塞窗口:

            TCP窗口变化:

  • 5- 学习链接:

         知乎TCP 拥塞控制原理

   作者寄语:

   有空还是自己买本图解TCP/ip看看,这本书讲的还是很好的。很多时候自己先看一遍,等到后面才看你就会发现其实也没有难理解,加油吧

猜你喜欢

转载自blog.csdn.net/lin_keys/article/details/105444779
今日推荐