TCP 个人理解

一、简介

1.TCP 的特点

  TCP 是面向连接的运输层协议;每一条TCP连接只能是点对点的(一对一);提供全双工通信,提供可靠交付的服务,并且还拥有流量控制和拥塞控制。

2.TCP 的特点简述

  (1)面向连接:就是在传输数据之前要建立连接,传输完毕之后要关闭连接。建立连接的目的是为通信双方接下来的数据传递做好准备,初始化各种状态变量(状态机?),分配缓存等资源。关闭连接,就是要释放资源,如果不能正常关闭,就会导致一些资源无法释放。

  (2)全双工:两端主机的进程可以同时收发数据

  (3)可靠交付:就是传输的数据无错误,按序,不丢失,不重复。比如说发送方发送了 12345,那么接收方接收到也是 12345

  无错误:主要是不发错给其他的主机进程,比如说A是和B通信,但A却发送给了C,这就是出错了。

  按序:就是接收方最后从缓冲区得到的数据的顺序是和发送方想要发送的数据的顺序是一样的。比如 A 想发送的是 12345,B最后得到的数据的顺序也应该是 12345,不能是21345 等等。

  不丢失:主要是当数据分成几组去发送,每个分组不会丢失,比如说A 将 12345 分为了两个部分 123 和 45 ,123丢失了,B最后收到了45.这就是丢失。

  不重复:A 发送 12345 ,B 收到了112345 ,这就是重复了。

  (4)流量控制:控制发送方的发送速率。

  (5)拥塞控制:防止过多的数据注入到网络中。

3.TCP 报文首部格式

  同时也要给那些标志安排在合理的位置,有个统一的格式,方便解读。
在这里插入图片描述

二、TCP的功能

  TCP 拥有上面那么多而且复杂的功能,那么要如何实现呢?基于TCP的通信,是诸多通信方式中的一种,那么本质上也是通信,通信的本质是什么?

  说简单点就是双方收发信息,信息本身没有任何意义,只是一些文字,是人共同协商之后,赋予文字意义,信息才有意义。TCP 在收发信息的基础上增加了一些功能,并不是我说它是TCP通信,那些信息就自带了可靠服务,拥塞控制,流量控制的功能。其实是接收方收到信息后,看到大家协商好的文字后,做出的一些动作。

比如说A在信息里面写了“1”,发送给B,B收到了信息,看见里面写了一个“1”,那么B给A发送“干得漂亮!”。“1”本身没有任何意义,为什么B会给A发送这个呢,因为这是通信的双方规定好的。

  扯了那么多,想要说什么呢?TCP的可靠交付功能,拥塞控制,流量控制功能也是像A和B一样,是根据对方发送的信息中的内容去做出的一些行为。 要实现TCP的功能,就需要在发送给对方的报文中写有那些功能的标志。对方收到了信息后,将那些标志解析出来,然后去做对应的事情。

  那些标志是大家互相协商好了,看到了某个标志就要做出规定的动作。那问题来了,基于TCP的通信方式的话,报文中要有什么内容,什么标志,或者说大家协商的标志是什么。

1.基于通信过程分析TCP 报文首部包含信息

  在想报文中要有内容,有什么标志,下来看看通信的过程,下面用 A和B 来简述一下。这个是从普遍的通信过程角度出发,来分析报文需要什么标志和格式。

  1、B要给A发信息,需要知道A在哪,才能将信息送到那里。所以需要A的目的端口

  2、B将信息发送给A,自然要告诉A你是谁,不然别人怎么要不要接收。所以需要B的源端口号

  3、在信息中B要说明自己发送信息的目的,比如来找A是来请求连接的。所以需要请求连接或者接收连接的标志 SYN。A 看到了 SYN 的标志就知道是要请求连接的了。

  4、在同意与B建立连接之前,A需要对B的信息进行检验,是否可以进行连接,防止是发错的或者不怀好意的请求。这个需要检验和

  5、当检验到B是非法的,那么A可以拒绝连接。拒绝连接可以使用RST

  6、如果检验到B是合法的,A同意连接,就回复B:确认自己收到请求信息了,回复确认需要ACK。当B看到回信中有ACK,就知道A收到了。

  A在回复B的信息中,还要告诉B自己能接收多少东西,防止B发得太多溢出。这个需要到窗口。将窗口发送给B。

  7、B收到了A发过来的信息,要回复确认,同时将数据发过去,为了减少交互的次数,就把确认和数据发送过去。

  由于A告诉了B能接收多少数据,由于B要发送的数据太大,所以要将数据分割划分。为了防止数据分割了之后数据的顺序乱了,要给数据中的每个字节安排一个序号,B每次发送数据的时候要将分组中的第一个字节的序号告诉A,这个需要到序号seq

  8、A收到了B发过来的数据,要告诉B真正收到数据了(ACK),并且要告诉B自己收到了什么数据,好让B知道A是不是真正的完全收到发送过去的数据了。但是为了节省资源,不是把收到的数据的序号都发送给B,而是发送所收到的数据的最后一个字节的序号加1,表示这个这序号之前的数据A都收到了,B下次还要发送数据的话,就从这个序号开始。这个需要到确认号ack

  9、发送数据,接收数据一般是先放在一片缓冲区中的,如果数据足够多了就开始发送或者将数据拿出来,这样就可以减少发送拿出来的次数,如果每次有一点数据就开始发送或者就拿出来,那么就要发很多次和拿很多次,就引入了缓冲区的机制。

  但是也会有一些很紧急的数据要发送过去,就要将数据标志为紧急数据,这个需要紧急标志URG。有时候紧急数据和不紧急的数据是放在一起的,那么B要指出紧急数据在哪,这个需要紧急指针,紧急指针是有紧急数据才有用,也就是URG等于1才有用。

  A收到了B的紧急数据,就赶紧拿出来,这个需要优先取出的标志PSH

  10、B数据发送完了,就发条信息给A发完了,这个需要结束标志FIN

  11、从上面的步骤来看,A和B通信,那么他们发送的数据报文中要有上面标黄的标志。但是如果只是将他们简单地放在数据报文中,报文中有可能有与这些标志的值相同的数据,这样就会导致对方处理数据的时候出现错误。

  所以我们需要在数据报文中指定一片位置来存放那些标志,并且通信的双方协议好哪个位置对应哪个标志,这些标志一共有多长。通常将那些标志放在数据报文的头部,并且注明头部有多长,这个就是数据偏移(报文头部长度)

2.基于TCP特点分析TCP 报文首部包含信息

2.1 TCP 是面向连接的

http://dwz.date/aUfm 好文章
https://blog.csdn.net/liuxl57805678/article/details/106526270?utm_medium=distribute.pc_relevant.none-task-blog-2defaultbaidujs_baidulandingword~default-0.no_search_link&spm=1001.2101.3001.4242.1

  在传输数据之前要建立连接,传输完毕之后要关闭连接。在收发的报文中要怎么实现建立连接和释放连接?比如说A收到了B的报文,查看了报文信息,就知道B要和我建立或者释放连接,那么就要规定建立和释放连接的标志。

  (1)在 TCP 规定的格式中,建立连接的标志是SYN,当报文中SYN=1 就代表请求连接或者接收连接。

  (2)释放连接的标志是FIN,FIN(final),当FIN=1代表请求释放连接。

2.1.1 三次握手

  第一次:客户端发送请求到服务器,服务器知道客户端发送,自己接收正常。SYN=1,seq=x。如果没有数据要发,为什么还要有随机发送一些数据呢?一来是为了,检测自己的发送能力,二来是检测对方的接收能力。

  第二次:服务器发给客户端,客户端知道自己发送、接收正常,服务器接收、发送正常。ACK=1,ack=x+1,SYN=1,seq=y

  第三次:客户端发给服务器:服务器知道客户端发送,接收正常,自己接收,发送也正常.seq=x+1,ACK=1,ack=y+1

上面分析过程可以看出,握手两次达不到让双方都得出自己、对方的接收、发送能力都正常的结论的。
在这里插入图片描述

2.1.2 TCP初始序列号ISN为什么是随机的

  ISN:初始化序列号(initial sequence number),是在建立tcp三次握手的时候,存储在TCP头部的序列号位置中的数字的代称。也就是说,告诉对方我将要开始发送的初始化序列号是多少,两边都要发这个ISN,即tcp三次握手中第一次握手的SYN包和第二次握手的SYN+ACK包中都有这个数值。

  从攻击的角度:
  TCP初始化序列号不能设置为一个固定值,因为这样容易被攻击者猜出后续的序列号,从而遭到攻击。

  从TCP连接稳定角度:
  广域网的随机性,复杂性都很高,假设client与server连接状况不好,不停的断开又重连。那么之前交互的报文很可能在连接已断开时还没到达server。

  如果ISN是固定的,那很可能在新连接建立后,上次连接通信的报文才到达server,这种情况有概率发生上次连接发送的报文的seq序列号正好是server希望收到的新连接的报文seq序列号。这就全乱了。

2.1.3 四次挥手

  第一次挥手:客户端发出释放FIN=1,自己序列号seq=u,进入FIN-WAIT-1状态

  第二次挥手:服务器收到客户端的后,发出ACK=1确认标志和客户端的确认号ack=u+1,自己的序列号seq=v,进入CLOSE-WAIT状态

  第三次挥手:客户端收到服务器确认结果后,进入FIN-WAIT-2状态。此时服务器发送释放FIN=1信号,确认标志ACK=1,确认序号ack=u+1,自己序号seq=w,服务器进入LAST-ACK(最后确认态)

  第四次挥手:客户端收到回复后,发送确认ACK=1,ack=w+1,自己的seq=u+1,客户端进入TIME-WAIT(时间等待)。客户端经过2个最长报文段寿命后,客户端CLOSE;服务器收到确认后,立刻进入CLOSE状态。

在这里插入图片描述

2.1.4 TCP 状态转换

  现态:现在的状态;

  事件:状态转换的前提条件,有事件发生

  次态:事件发生了,向另一个状态转移,称为次态。
在这里插入图片描述

2.2 TCP 提供可靠交付服务——无差错

  这里的无差错主要是信息能到达指定目的地,想要到达指定的目的,就需要目的地地址,因为消息达到目的地需要很多层一起工作的,相当于让其他人传输,要知道目的地地址。为了方便知道接收方知道消息从何而来,要加上源地址。

  接收方接收到了报文,要对报文进行检验,使用到检验和。就相当于A和B通信,A收到了消息,要核对一下这条消息的目的地和源地址,确认是不是B发送过来的。如果不是B发过来的,就将错误的丢掉,一般来说丢掉了之后不发送否认信息。

  所以TCP的报文中要有目的端口源端口检验和

2.3 TCP 提供可靠交付服务——无丢失

  无丢失指的是数据没有丢失,比如说A发送了12345,如果B收到了1345就是丢失了。那么要如何实现无丢失呢?很简单,A在发送报文过去的时候,也在报文中告诉B自己发送了多少个字节的数据。B在接收到数据核对一下就知道了。

  但是使用刚刚说的方法,就会浪费时间去计算。如果A要告诉B发送了多少个字节的数据过去,那么A在发送之前还要去计算发送的报文的长度。并且B在接收到了数据,还有计算实际接收到的数据大小,然后去对比是否接收完。如果数据少,这样是可以的,但是如果数据量大,每次都要这样去计算,就会花大量不必要的时间。

  所以TCP采用这样的方法:让接收方说希望得到什么数据,发送方就从那个数据开始发。 不再去计算是否丢失,这样就减少了计算时间开销。

  例如:A是发送方,B是接收方。A不再去计算发送过去的报文的长度,而是在报文中标出发送的第一个字节数据的序号。比如说A要发送12345,那么在报文中标出1。当B接收到了报文,也不去计算实际接收到的报文长度,而是告诉A下一次自己想要收到什么数据。比如说B收到了123,那么B要告诉A自己确实收到了数据(给发送方回复确认收到数据),并且还发送了一个4,4表示B下一次希望收到的报文的第一个数据,也表示4前面的数据123已经接收到了。那么A收到了B的回复,就从4开始发送报文。这样处理,就不用去核算是否丢失了,反正每次接收方都说下一次想要接收到什么数据。

  综上所述,在TCP的报文中要加上发送的报文的第一个数据的序号seq确认收到数据(ACK)以及下一次想要接收的数据的序号也称为所收到的数据的确认序号ack

2.4 TCP 提供可靠交付服务——无重复

  TCP如何实现的呢?首先TCP采用的是累积确认——无丢失里面采取的措施:接收方回复发送方,回复的是希望下一次接收到的数据的序号,这个序号前面的数据我已经接收到了,不用再发了。这个措施能在一定的程度上避免收到重复的数据。如果真的收到了重复的数据就丢弃,但要发回确认信息,这点很重要。

2.5 TCP 提供可靠交付服务——按序

  如果收到的报文段没有差错,只是未按序号顺序到达,在GDB协议(停止等待协议)中,会丢弃所有未按序到达的分组,但是TCP没有做此规定,而是让TCP的实现者自行确定。(所有说,TCP的实现,本质上就是在报文段里面加上一些标志,然后将标志解析出来做对应的事)

  那么现在没有现成的标志可以用了要实现按序,需要我们自己去加,如果开发中有这个需求。其实可以将发过来的数据放在缓冲区中,取出来的时候,按顺序取就行了,因为每个报文段都有序号(seq),这个问题就可以解决。

  如果使用封装好TCP,这些功能都可以使用了。

3.超时重传

3.1超时重传含义

  TCP 的发送方在规定的时间内没有到发送出去的报文段的确认就要重传已经发送的报文段。

3.2超时重传时间选择

  这个时间如何选?TCP采用了一个自适应算法,这个算法记录每一个报文段发出的时间,以及收到相应的确认报文段的时间。这两个时间之差就是报文段的往返时间RTT

  超时的时间就选择所有报文段的往返时间的平均值。每得到一个报文段的RTT,就重新计算一次。

4.快速重传

4.1快速重传的改进

  超时触发重传 存在一个问题:超时时间可能相对较长,意思就是要等太久了。快速重传就是希望能够缩短时间,尽早重传丢失的报文段。

  我们知道接收方会给发送方发送一个确认报文,当收到了一个报文段以后。接收方发送的报文里面有希望发送方下一次发送的数据序号(ack),当接收方一直接收不到希望收到的序号的数据,就会一直给发送方发送这个确认报文。

所以可以利用这个机制,当发送方收到了接收方三个重复的确认,就立即重传丢失的报文段。快速重传不是要取消重传计时器,而是尽早重传丢失的报文段。

4.2为什么需要接收到三个重复的确认才重传

  比如说A 发送 12345,B收到了1,就会回复一个确认号ack=2(希望下一次接收到的是2),注意这个不是冗余的ack

  如果接下来是3 先到了B,那么B回复A的也是 ack=2,这是收到的第一个重复的ack也叫冗余ack。如果A收到了第一个冗余ack就重传,那么一旦数据出现乱序就会重传,但是乱序是经常发生的,所以收到一个冗余的ack就重传不可取。万一待会2就来到了B,然而A又重传了2,浪费时间。

  那为什么不是收到了一个冗余ack就重传呢?因为乱序有时候不只是与一个数据乱序,可能是多个。比如说3到了之后,B给A发一个冗余ack,接下里4到了,又给A发送一个冗余ack。如果收到了两个冗余的重发,在A重发之前,2就刚刚好到了。就是说要考虑到不只是与一个数据乱序。

  综上选择了收到三个冗余的ack才重传。

5.选择重传

  在前面的讨论中,对TCP 报文段的确认是一种累积确认,就是说它只通告最后一个按序到达的字节,而没有通告所有收到的失序到达的那些字节,虽然这些字节已经被接收方接收并暂存在接收缓存中。

  比如说:A给B发送12345,B收到了12,45,B只会告诉A它收到了2已经2前面的数据,因为这才是有序的,而不会告诉A也收到了45。如果超过了一定的时间,A收不到B对45的确认,那么A就会重传45,但是45已经在B那里了。

  所以为了防止A重传已经在B那里的45,就推出了一个可选的功能选择确认来解决这个问题。

  选择确认运行接收方通知发送方所有正确接收了的但是失序的字节块,发送方可以根据这些信息只重传那些接收方还没有收到的字节块。TCP 的固定首部中没有选择重传的字段,就将这个字段放在“选项”这个字段中。所以这也说明了TCP的首部是变长的,需要一个字段来存放TCP的首部长度。

6.流量控制

6.1 流量控制含义

  一条TCP 连接的双方主机都为该连接设置了接收缓存。当该TCP 连接接收到按序的字节后,它就将数据放入缓存。相关联的应用程序会从该缓存中读取数据,但是应用程序不一定能够马上将数据取走。

  事实上,接收方应用也许正忙于其他的事务,需要多很长时间才去读取数据。如果应用程序读取数据比较慢,而发送方发送数据很快、很多,则会导致该连接的接收缓存溢出。也就是会导致接收缓存满了,无法再接收数据。

6.2 流量控制基本方法

  流量控制的基本方法是接收方将自己的接收能力告诉发送方,让发送方调整发送速率。利用滑动窗口机制可以很方便地控制发送方的平均发送速率。在TCP 报文首部的窗口字段的数值就是当前接收方的接收窗口的大小。

6.3 流量控制存在问题及解决

  还存在一个问题,当接收方的大小不再为0时,向发送方发送的窗口更新报文段丢失了会出现什么问题?如果接收方一直没有数据要发给发送方,则发送方将会永远等待下去。为了防止因接收方发送给发送方的窗口变更报文段丢失所导致的死锁状态。

当窗口为0时,如果发送方有数据要发送,则会周期性地(例如60s)发送只包含一个字节数据的窗口探测报文段,以便强制接收方发回确认并通告接收窗口大小。

7.拥塞控制

7.1拥塞控制含义

  在某段时间,若对网络中某一资源的需求超过了该资源所能提供的可用部分,网络性能就要变坏,这种情况就叫做网络拥塞。

  在计算机网络中数位链路容量(即带宽)、交换结点中的缓存和处理机等,都是网络的资源。

  若出现拥塞而不进行控制,整个网络的吞吐量将随输入负荷的增大而下降。那么拥塞控制,要控制什么呢?其实就是控制源点的发送速率,防止过多的数据注入到网络中,让网络去处理。

7.2重要的知识

(1)拥塞的标志:发送分组丢失

(2)拥塞窗口:发生分组丢失那一刻,往网络里面注入的数据量。或者说发生分组丢失那一刻对应的发送的分组数。比如说,某个时刻发送了100个分组,出现了分组丢失,那么拥塞窗口就是100个分组。也可以怎么说,拥塞窗口就是说明了,还可以往网络里面发送多少数据。

(3)发送窗口的值:在接收窗口和拥塞窗口中取最小值。下面的为了方便解释,先假定发送窗口等于拥塞窗口。

(4)慢启动的门限值(ssthresh):就是到了某个值,就不使用慢开始算法了。

(5)慢开始算法:是指一开始向网络中注入的报文段少,并不是值拥塞窗口增长速度慢;

(6)拥塞避免:并非指完全能够避免拥塞,而是指在拥塞避免阶段将拥塞窗口改为按线性规律增长,这样网络不容易出现拥塞。

7.3 慢开始和拥塞避免算法配合使用

  简单地来说,这个过程如下:

  (1)首先采用慢开始算法向网络中注入少的报文段,向网络中注入的报文段数量呈指数增长,从1开始。

  (2)到了慢开始的门限值,就不用慢开始算法了。采用拥塞避免算法,向网络中注入的报文段数量呈线性增长

  (3)当网络出现拥塞时,就将向注入网络中数据的速率降低,重新采用慢算法,从1开始。同时将慢开始的门限值重新设置,降低为拥塞窗口的一半。

  (4)到了新的慢开始门限值,就采用拥塞避免算法。以此类推
在这里插入图片描述

7.4 快重传和快恢复算法配合使用

  大致过程:

  (1)首先采用慢开始算法向网络中注入少的报文段,向网络中注入的报文段数量呈指数增长,从1开始。

  (2)到了慢开始的门限值,就不用慢开始算法了。采用拥塞避免算法,向网络中注入的报文段数量呈线性增长

  (3)当网络出现拥塞时,就将向注入网络中数据的速率降低。注意了,快恢复,不是再次采用慢开始算法,也就是不从1开始了。而是将慢开始的门限值重新设置,降低为拥塞窗口的一半。然后从新的慢开始的门限值开始采用拥塞避免算法。

就是说慢开始算法只采用了一次,就是开头的那一次,出现了拥塞以后都是采用拥塞避免算法,每轮次发送报文段数量呈线性增长。
在这里插入图片描述

这篇文章写得好:
https://blog.csdn.net/qq_41431406/article/details/97926927

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值