【计算机网络6】运输层#TCP协议

在这里插入图片描述

一、TCP基础

1、tcp的有哪些主要特点?

(1)面向连接的运输层协议

应用程序使用TCP协议之前要先建立连接,传送数据完毕后必须释放建立的链接。

(2)一条TCP链接只能有两个端点

也就是说每条TCP链接只能是点对点(一对一)的。

(3)TCP提可靠交付的服务。

TCP传送的数据无差错、不丢失、不重复、按顺序到达。

(4)TCP提供全双工通信

  • TCP允许通信双方的进程在任何时候都能发送数据,全双工通信的双方既是发送方也是接收方。
  • TCP两端设有发送缓存,接收缓存。用来临时存放双向通信的数据。
  • 发送时,应用程序吧数据传送给TCP的缓存中,TCP在合适的时候发送出去。
  • 接收时、TCP吧数据放入缓存,上层应用进程在合适时读取缓存。

(5)面向字节流

  • 流入到应用进程或者从应用进程流出的是字节序列。
  • 虽然应用程序和TCP交互为一个个大小不等数据块,但是TCP吧每个数据块都看作一段段字节流。
  • TCP不保证接收方应用程序所收到的数据块和发送方应用程序所发出的数据块具有对应大小的关系,但是接收方应用程序收到的字节流必须和发送方应用程序发出的字节流完全一样。
  • 接收方的应用程序必须有能力识别收到的字节流,把它还原成有意义的应用层数据

在这里插入图片描述

注意,TCP和UDP在发送报文时所采用的方式完全不同:

1、TCP并不关心应用进程一次把多长的报文发送到TCP的缓存中,而是根据对方给出的窗口值和当前网络拥塞的程度来决定一个报文段应包含多少个字节
2、如果应用进程传送到TCP缓存的数据块太长,TCP就可以把它划分短一些再传送。如果应用进程一次只发来一个字节,TCP也可以等待积累有足够多的字节后再构成报文段发送出去
3、UDP发送的报文长度是应用进程给出的

2、TCP的链接

每一条TCP连接有两个端点,那么TCP链接的端点到底是啥呢?

其实TCP链接的端点既不是主机,不是主机的IP地址、不是应用进程、也不是运输层的协议端口。TCP链接的端点叫套接字(或者叫插口)。

(1)套接字(socket)

  • 套接字:RFC 793定义端口号拼接到IP地址就构成了套接字。
  • 表示方法:点分十进制的IP地址之后写上端口号,中间用冒号隔开即可。
  • 表示栗子栗子: 192.23.23.23:8080

(3)TCP链接

  • 每一条TCP链接唯一的被通信两端的两个端点(两个套接字)所确定
  • 同一个IP地址可以有多个不同的TCP连接,而同一个端口号也可以出现在多个不同的TCP连接中

二、可靠传输的工作原理基础

TCP发送的报文会交付给下层的IP层,而IP层只提供尽最大努力服务,不保证传输的可靠性。这时TCP需要采取适当的措施才能保证传输的可靠。

假如理想的传输条件有以下也即:传输信道不产生差错、不管发送发以多块的速度发送数据,接收方总是来得及处理收到的数据。在这样的理想传输条件下,不需要采取任何措施就能够实现可靠传输。

理想的情况在实际生活中是不可能存在的,但是我们可以采取一些可靠的协议进行控制:当数据出现差错时,让发送方重传差错的数据。当接收方来不及接收数据时告诉发送方适当降低发送的速度。这样一来,本来是不可靠的传输信道就能够实现可靠传输了。

1、停止等待协议

为了方便讨论下图中A我们定为发送方B为接收方。

什么是停止等待协议?

停止等待协议:发送方每发完一个分组就停止发送,等待接收方确认,接收方收到分组后发送确认,在收到接收方的确认后发送方再发送下一个分组。

(1)接收方检验分组无差错
在这里插入图片描述

A发送分组M1,发完就暂停发送,等待B的确认。B收到了M1就向A发送确认。A在收到了对M1的确认后,就再发送下一个分组M2。同样,在收到B对M2的确认后,再发送M3。

(2)接收方检验分组有差错

什么是超时重传机制?

超时重传机制:发送方只要超过了一段时间仍然没有收到确认,就认为刚才发送的分组丢失了,因而重传前面发送过的分组。

超时重传机制如何实现?

要实现超时重传,就要在每发送完一个分组设置一个超时计时器。如果在超时计时器到期之前收到了对方的确认,就撤销已设置的超时计时器。

如下栗子A为每一个已发送的分组都设置了一个超时计时器。但A只要在超时计时器到期之前收到了相应的确认,就撤销该超时计时器。

超时重传时需要留意点:

  • A发送完一个分组后需要暂时保留已发送的分组副本,因为在发生超时重传时可以继续使用,只有在收到相应的确认后才删除分组副本。
  • 分组和确认分组要进行编号。这样可以明确哪一个发出的分组收到了确认。哪一个发出的分组没有收到确认。
  • 超时计时器设置的重传时间应当比数据在分组传输的平均往返时间更长一些。

在这里插入图片描述

出现差错的可能情况:这两种情况下B什么也不会做的,也不会通知A收到有差错的分组。A的计时器判定为超时就会重新发送分组。

  • B在接收到M1分组后检测分组错误,丢弃M1
  • M1在发送过程中发生了丢失。

(3)确认分组丢失
在这里插入图片描述

可能出现的情况:
B收到M1分组后向A发动确认分组。但分组发送过程中丢失。A在超时计时器到达后就要重传分组M1。这时B又收到了A发送的M1这时B要采取如下两个动作:

1、丢弃这个重复的分组,不向上层交付。
2、向A发送确认分组(每次收到分组时都要发送确认分组,不能认为收到过这个分组就不发送了。况且A之所以重传M1就是因为没有收到M1的确认)

(4)确认分组迟到

在这里插入图片描述

可能出现的情况:
B收到A发送的M1,这时开始发送确认分组。但是发送确认分组时,这个分组由于某些原因传递的很慢,A的M1的超时计时器事件到了还没收到确认,这时A再发个M1,B收到M1发现这个M1重复,丢弃这个重复的M1,发送确认分组。这时A收到确认分组。继续发送分组M2…Mn这时这个龟速的M1分组终于收到了。。。这时A、B如何处理呢?

A收到迟到的确认分组直接丢弃这个迟到的分组即可。B仍然会收到重复的M1,并且同样要丢弃重复的M1,并重传确认分组。

(5)总结

通常A最终总是可以收到对所有发出的分组的确认。如果A不断重传分组但总是收不到确认,就说明通信线路太差,不能进行通信

使用上述的确认和重传机制,我们就可以在不可靠的传输网络上实现可靠的通信

上述的这种可靠传输协议常称为自动重传请求ARQ (Automatic Repeat reRuest)。意思是重传的请求是自动进行的。接收方不需要请求发送方重传某个出错的分组。

停止等待协议优点简单,缺点信道利用率低。为了提高传输效率,发送方可以不使用低效率的停止等待协议,而是采用流水线传输

流水线传输就是发送方可连续发送多个分组,不必每发完一个分组就停顿下来等待对方的确认。这样可使信道上一直有数据不间断地在传送。显然,这种传输方式可以获得很高的信道利用率。

当使用流水线传输时就要使用连续ARQ协议和滑动窗口协议

2、连续的ARQ协议基础和滑动窗口初识

(1)滑动窗口简介

在这里插入图片描述

如上a所示:
1、表示发送方维持的发送窗口这个表示发送方维持的滑动窗口,位于发送窗口内的5个分组都可连续发送出去,而不需要等待对方的确认。这样,信道利用率就提高了。
2、上图有个时间坐标t,我们认为向前为时间增大的方向,向后为时间减小方向。分组发送是按照分组序号从小到大发送。

(2)连续的ARQ协议

连续ARQ协议规定,发送方每收到一个确认分组,就把发送窗口向前滑动一个分组的位置。

如上图b,表示发送方收到了对第1个分组的确认,于是把发送窗口向前移动一个分组的位置。如果原来已经发送了前5个分组,那么现在就可以发送窗口内的第6个分组了。

接收方一般都是采用累积确认的方式。这就是说,接收方不必对收到的分组逐个发送确认,而是在收到几个分组后,对按序到达的最后一个分组发送确认,这就表示:到这个分组为止的所有分组都已正确收到了。

例如,如果发送方发送了前5个分组,而中间的第3个分组丢失了。这时接收方只能对前两个分组发出确认。发送方无法知道后面三个分组的下落,而只好把后面的三个分组都再重传一次。这就叫做Go-back-N(回退N),表示需要再退回来重传已发送过的N个分组。可见当通信线路质量不好时,连续ARQ协议会带来负面的影响。

(3)总结

累积确认有优点也有缺点。

优点是:容易实现,即使确认丢失也不必重传。

缺点是:不能向发送方反映出接收方已经正确收到的所有分组的信息。

三、TCP报文的首部格式

TCP虽然是面向字节流的,但TCP传送的数据单元却是报文段。一个TCP报文段分为首部和数据两部分,而TCP的全部功能都体现在它首部中各字段的作用。

TCP的首部十分重要,其前20个字节是固定的。首部的后面有4n(n为整数)个字节是根据需要而增加的可选项。因此TCP首部的最小长度玩为20字节。

在这里插入图片描述

TCP报文段图

(1)源端口、目的端口

各占两个字节,分别写入源端口号和目的端口号。和UDP类似TCP的分用功能也是通过端口实现的。

(2)序号
字段的名称也叫做“报文段序号”,占四个字节,TCP是面向字节流的,首部中的序号字段值则指的是本报文段所发送的数据的第一个字节的序号。

(3)确认号

占四字节,表示期望收到的下一个报文中第一个字节号的序号。

若确认号 = N,则表明:到序号N - 1为止的所有数据都已正确收到。

(4)数据偏移

占4位,它指出TCP报文段的数据起始处距离TCP报文段的起始处有多远。这个字段实际上是指出TCP报文段的首部长度。由于首部中还有长度不确定的选项字段,因此数据偏移字段是必要的。

(5) 紧急URG (URGent)

当URG = 1时,表明紧急指针字段有效。它告诉系统此报文段中有紧急数据,应尽快传送(相当于高优先级的数据),而不要按原来的排队顺序来传送。

当URG置1时,发送应用进程就告诉发送方的TCP有紧急数据要传送。于是发送方TCP就把紧急数据插入到本报文段数据的最前面,而在紧急数据后面的数据仍是普通数据。这时要与首部中紧急指针(Urgent Pointer)字段配合使用。

(6)确认ACK (ACKnowlegment)

仅当ACK = 1时确认号字段才有效。当ACK = 0时,确认号无效。TCP规定,在连接建立后所有传送的报文段都必须把ACK置1

(7)推送 PSH (PuSH)

当两个应用进程进行交互式的通信时,有时在一端的应用进程希望在键入一个命令后立即就能够收到对方的响应。在这种情况下,TCP就可以使用推送(push)操作。

这时,发送方TCP把PSH置1,并立即创建一个报文段发送出去。接收方TCP收到PSH = 1的报文段,就尽快地(即“推送”向前)交付接收应用进程,而不再等到整个缓存都填满了后再向上交付。

(8) 复位RST (ReSeT)

当RST = 1时,表明TCP连接中出现严重差错(如由于主机崩溃或其他原因),必须释放连接,然后再重新建立运输连接。RST置1还用来拒绝一个非法的报文段或拒绝打开一个连接。RST也可称为重建位或重置位。

(9)同步SYN (SYNchronization)

在连接建立时用来同步序号。当SYN = 1而ACK = 0时,表明这是一个连接请求报文段。对方若同意建立连接,则应在响应的报文段中使SYN = 1和ACK =1。因此,SYN置为1就表示这是一个连接请求或连接接受报文。

(10)终止FIN

用来释放一个连接。当FIN = 1时,表明此报文段的发送方的数据已发送完毕,并要求释放运输连接。

(11)窗口

1、占两个字节,取值范围[0,2^16-1]
2、窗口:指的是发送本段报文的接收窗口(非自己的发送窗口)
3、窗口值告诉对方:从本报文段首部中的确认号算起,接收方目前允许对方发送的数据量,之所以要有这个限制,是因为接收方的数据缓存空间是有限的。总之,窗口值作为接收方让发送方设置其发送窗口的依据。

例如,设确认号是701,窗口字段是1000。这就表明,从701号算起,发送此报文段的一方还有接收1000个字节数据(字节序号是701~1 700)的接收缓存空间

4、窗口字段明确指出了现在允许对方发送的数据量。窗口值是经常在动态变化着

(12)检验和

占2字节。检验和字段检验的范围包括首部和数据这两部分。

和UDP类似,应把伪首部第4个字段中的17改为6 (TCP的协议号是6),把第5字段中的UDP长度改为TCP长度。

接收方收到此报文段后,仍要加上这个伪首部来计算检验和。若使用IPv6,则相应的伪首部也要改变。

(13)紧急指针

占2字节。紧急指针仅在URG = 1时才有意义,它指出本报文段中的紧急数据的字节数(紧急数据结束后就是普通数据)

(14)选项

1、长度可变,最长可达40字节。当没有使用“选项”时,TCP的首部长度是20字节
2、TCP最初只规定了一种选项,即最大报文段长度 MSS (Maximum Segment Size) [RFC 879]。请注意MSS这个名词的含义。MSS是每一个TCP报文段中的数据字段的最大长度。数据字段加上TCP首部才等于整个的TCP报文段。所以MSS并不是整个TCP报文段的最大长度,而是“TCP报文段长度减去TCP首部长度
3、随着因特网的发展,又陆续增加了几个选项。如窗口扩大选项、时间戳选项等[RFC 1323]。以后又增加了有关选择确认(SACK)选项[RFC 2018]。这些选项的位置都在图所示的“选项”字段中。

四、TCP可靠传输的实现

1、以字节为单位的滑动窗口

TCP的滑动窗口是以字节为单位的,发送方既有发送滑动窗口,发送方也有接收滑动窗口。同理接收方也一样。

(1)滑动窗口的构造

现假定A收到了B 发来的确认报文段,其中窗口是20字节,而确认号是31这表明B期望收到的下一个序号是31,而序号30为止的数据已经收到了。根据这两个数据,A就构造出自己的发送窗口

在这里插入图片描述

1、A的发送窗口:在没有收到B的确认的情况下,A可以连续把窗口内的数据都发送出去。凡是已经发送过的数据,在未收到确认之前都必须暂时保留,以便在超时重传时使用。
2、发送窗口里面的序号:表示允许发送的序号。显然,窗口越大,发送方就可以在收到对方确认之前连续发送更多的数据,因而可能获得更高的传输效率。但接收方必须来得及处理这些收到的数据。
3、发送窗口后沿的后面部分表示已发送且已收到了确认。这些数据显然不需要再保留了。而发送窗口前沿的前面部分表示不允许发送的,因为接收方都没有为这部分数据保留临时存放的缓存空间。
4、发送窗口的位置由窗口前沿和后沿的位置共同确定。
5、发送窗口的后沿特点

(1)发送窗口后沿的变化情况有两种可能,即不动(没有收到新的确认)和前移(收到了新的确认)
(2)发送窗口后沿不可能向后移动,因为不能撤销掉已收到的确认。

6、滑动窗口的前沿特点:

(1)发送窗口前沿通常是不断向前移动,但也有可能不动:

  • 没有收到新的确认,对方通知的窗口大小也不变
  • 收到了新的确认但对方通知的窗口缩小了,使得发送窗口前沿正好不动

7、发送窗口前沿也有可能向后收缩。这发生在对方通知的窗口缩小了。但TCP的标准强烈不赞成这样做。因为很可能发送方在收到这个通知以前已经发送了窗口中的许多数据,现在又要收缩窗口,不让发送这些数据,这样就会产生一些错误。

(2)滑动窗口的描述

假定A发送了序号为31~41的数据。这时,发送窗口位置并未改变,但发送窗口内靠后面有11个字节(灰色小方框表示)表示已发送但未收到确认。而发送窗口内靠前面的9个字节(42~50)是允许发送但尚未发送的。

在这里插入图片描述
要描述一个发送窗口的状态需要三个指针:P1,P2和P3。指针都指向字节的序号。

1、小于P1的是已发送并已收到确认的部分,而大于P3的是不允许发送的部分
2、P3 - P1 = A的发送窗口(又称为通知窗口)
3、P2 - P1 = 已发送但尚未收到确认的字节数
4、P3 - P2 = 允许发送但尚未发送的字节数(又称为可用窗口或有效窗口)

如图,B的接收窗口大小是20。在接收窗口外面,到30号为止的数据是已经发送过确认,并且已经交付主机了。因此在B可以不再保留这些数据。接收窗口内的序号(31~50)是允许接收的。

如图,B收到了序号为32和33的数据。这些数据没有按序到达,因为序号为31的数据没有收到(也许丢失了,也许滞留在网络中的某处)B只能对按序收到的数据中的最高序号给出确认,因此B发送的确认报文段中的确认号仍然是31(即期望收到的序号),而不能是32或33。

(3)窗口和TCP缓存的关系

发送方的应用进程把字节流写入TCP的发送缓存,接收方的应用进程从TCP的接收缓存中读取字节流。发送方维持的发送缓存和发送窗口,以及接收方维持的接收缓存和接收窗口如下图:

在这里插入图片描述

1、发送缓存用来暂时存放:

  • 发送应用程序传送给发送方TCP准备发送的数据
  • TCP已发送出但尚未收到确认的数据
    ps:发送窗口通常只是发送缓存的一部分。已被确认的数据应当从发送缓存中删除,因此发送缓存和发送窗口的后沿是重合的。发送应用程序最后写入发送缓存的字节减去最后被确认的字节,就是还保留在发送缓存中的被写入的字节数。发送应用程序必须控制写入缓存的速率,不能太快,否则发送缓存就会没有存放数据的空间。

2、接收缓存用来暂时存放:

  • 按序到达的、但尚未被接收应用程序读取的数据
  • 未按序到达的数据
    ps:如果收到的分组被检测出有差错,则要丢弃。如果接收应用程序来不及读取收到的数据,接收缓存最终就会被填满,使接收窗口减小到零。反之,如果接收应用程序能够及时从接收缓存中读取收到的数据,接收窗口就可以增大,但最大不能超过接收缓存的大小

强调:

  • 虽然A的发送窗口是根据B的接收窗口设置的,但在同一时刻,A的发送窗口并不总是和B的接收窗口一样大。因为通过网络传送窗口值需要经历一定的时间滞后(这个时间还是不确定的)

  • 对于不按序到达的数据应如何处理,TCP标准并无明确规定。如果接收方把不按序到达的数据一律丢弃,那么接收窗口的管理将会比较简单,但这样做对网络资源的利用不利(因为发送方会重复传送较多的数据)。因此TCP通常对不按序到达的数据是先临时存放在接收窗口中,等到字节流中所缺少的字节收到后,再按序交付上层的应用进程。

  • TCP要求接收方必须有累积确认的功能,这样可以减小传输开销。接收方可以在合适的时候发送确认,也可以在自己有数据要发送时把确认信息顺便捎带上。但请注意两点,一是接收方不应过分推迟发送确认,否则会导致发送方不必要的重传,这反而浪费了网络的资源。TCP标准规定,确认推迟的时间不应超过0.5秒。若收到一连串具有最大长度的报文段,则必须每隔一个报文段就要发送一个确认[RFC1122]。二是捎带确认实际上并不经常发生,因为大多数应用程序不同时在两个方向上发送数据。

2、超时重传的时间选择

TCP的发送方在规定的时间内没有收到确认就要重传已发送的报文段。这种重传的概念是很简单的,但重传时间的选择却是TCP最复杂的问题之一。

如果把超时重传时间设置得太短,就会引起很多报文段的不必要的重传,使网络负荷增大。但若把超时重传时间设置得过长,则又使网络的空闲时间增大,降低了传输效率。

运输层的超时计时器的超时重传时间究竟应设置为多大呢?

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

TCP保留了RTT的一个加权平均往返时间 RTTS,又称为平滑的往返时间,S表示Smoothed。因为进行的是加权平均,因此得出的结果更加平滑。

每当第一次测量到RTT样本时,RTTS值就取为所测量到的RTT样本值。但以后每测量到一个新的RTT样本,就按下式重新计算一次RTTS

根据相关分析得知超时计时器设置的超时重传时间 RTO (RetransmissionTime-Out)应略大于上面得出的加权平均往返时间RTTS。RFC 2988建议使用下式计算RTO

在这里插入图片描述
而RTTD是RTT的偏差的加权平均值,它与RTTS和新的RTT样本之差有关。RFC2988建议这样计算RTTD。当第一次测量时,RTTD值取为测量到的RTT样本值的一半。在以后的测量中,则使用下式计算加权平均的RTTD:
在这里插入图片描述
上面所说的往返时间的测量,实现起来相当复杂,如何判定此确认报文段是对先发送的报文段的确认,还是对后来重传的报文段的确认?

在这里插入图片描述

Karn提出了一个算法Karn算法,Karn算法能够使运输层区分开有效的和无效的往返时间样本,从而改进了往返时间的估测。

3、选择确认SACK

若收到的报文段无差错,只是未按序号,中间还缺少一些序号的数据,那么能否设法只传送缺少的数据而不重传已经正确到达接收方的数据?答案是可以的。选择确认就是一种可行的处理方法。

然而,SACK文档并没有指明发送方应当怎样响应SACK。因此大多数的实现还是重传所有未被确认的数据块。

五、TCP的流量控制

1、利用滑动窗口实现流量控制

一般说来,我们总是希望数据传输得更快一些。但如果发送方把数据发送得过快,接收方就可能来不及接收,这就会造成数据的丢失。所谓流量控制(flow control)就是让发送方的发送速率不要太快,要让接收方来得及接收。

TCP连接建立时是会进行窗口协商的,发送方的发送窗口不能超过接收方给出的接收窗口的数值。请注意,TCP的窗口单位是字节,不是报文段。利用滑动窗口机制可以很方便地在TCP连接上实现对发送方的流量控制。

(1)死锁僵局的产生与解决

我们考虑一种情况,B向A发送了零窗口的报文段后不久,B的接收缓存又有了一些存储空间。于是B向A发送了rwnd = 400的报文段。然而这个报文段在传送过程中丢失了。A一直等待收到B发送的非零窗口的通知,而B也一直等待A发送的数据。如果没有其他措施,这种互相等待的死锁局面将一直延续下去。

TCP为每一个连接设有一个持续计时器(persistence timer)。只要TCP连接的一方收到对方的零窗口通知,就启动持续计时器。若持续计时器设置的时间到期,就发送一个零窗口探测报文段(仅携带1字节的数据),而对方就在确认这个探测报文段时给出了现在的窗口值[插图]。如果窗口仍然是零,那么收到这个报文段的一方就重新设置持续计时器。如果窗口不是零,那么死锁的僵局就可以打破了。

2、传输效率的考虑

应用进程把数据传送到TCP的发送缓存后,剩下的发送任务就由TCP来控制了。可以用不同的机制来控制TCP报文段的发送时机:

  • 第一种机制是TCP维持一个变量,它等于最大报文段长度MSS。只要缓存中存放的数据达到MSS字节时,就组装成一个TCP报文段发送出去。
  • 第二种机制是由发送方的应用进程指明要求发送报文段,即TCP支持的推送(push)操作。
  • 第三种机制是发送方的一个计时器期限到了,这时就把当前已有的缓存数据装入报文段(但长度不能超过MSS)发送出去。

如何控制TCP发送报文段的时机仍然是一个较为复杂的问题。

(1)传输效率方面的优化

为了提高传输效率在TCP的实现中广泛使用Nagle算法:
若发送应用进程把要发送的数据逐个字节地送到TCP的发送缓存,则发送方就把第一个数据字节先发送出去,把后面到达的数据字节都缓存起来。当发送方收到对第一个数据字符的确认后,再把发送缓存中的所有数据组装成一个报文段发送出去,同时继续对随后到达的数据进行缓存。只有在收到对前一个报文段的确认后才继续发送下一个报文段。当数据到达较快而网络速率较慢时,用这样的方法可明显地减少所用的网络带宽。

Nagle算法还规定,当到达的数据已达到发送窗口大小的一半或已达到报文段的最大长度时,就立即发送一个报文段。这样做,就可以有效地提高网络的吞吐量。

(2)糊涂窗口综合症的问题解决

糊涂窗口综合症(silly window syndrome)[RFC 813],有时也会使TCP的性能变坏:

设想一种情况:TCP接收方的缓存已满,而交互式的应用进程一次只从接收缓存中读取1个字节(这样就使接收缓存空间仅腾出1个字节),然后向发送方发送确认,并把窗口设置为1个字节(但发送的数据报是40字节长)。接着,发送方又发来1个字节的数据(请注意,发送方发送的IP数据报是41字节长)。接收方发回确认,仍然将窗口设置为1个字节。这样进行下去,使网络的效率很低。

解决方案:

让接收方等待一段时间,使得或者接收缓存已有足够空间容纳一个最长的报文段,或者等到接收缓存已有一半空闲的空间。只要出现这两种情况之一,接收方就发出确认报文,并向发送方通知当前的窗口大小。此外,发送方也不要发送太小的报文段,而是把数据积累成足够大的报文段,或达到接收方缓存的空间的一半大小。

上述两种方法可配合使用。使得在发送方不发送很小的报文段的同时,接收方也不要在缓存刚刚有了一点小的空间就急忙把这个很小的窗口大小信息通知给发送方。

待续。。。

六、TCP的拥塞控制

1、拥塞控制的原理
2、拥塞控制常见方法
3、随机早期检测RED

七、TCP的运输链接管理

TCP是面向连接的协议,所谓的面向连接就是通信双方在进行通信之前需要建立连接,在通信完成之后需要释放连接。

TCP连接的建立采用客户服务器方式。主动发起连接建立的应用进程叫做客户端(client),而被动等待连接建立的应用进程叫做服务器(server)

连接的管理就是使连接的建立和释放都能正常地进行,为了功能正常的进行,在TCP连接建立过程中要解决以下三个问题:

  • 要使每一方能够确知对方的存在
  • 要允许双方协商一些参数(如最大窗口值、是否使用窗口扩大选项和时间戳选项以及服务质量等)
  • 能够对运输实体资源(如缓存大小、连接表中的项目等)进行分配
1、三次握手

建立 TCP 连接前,TCP 客户端、服务端都处于关闭状态,直到客户端主动打开链接,服务端才被动打开链接,等待接受客户端的请求。

在这里插入图片描述

握手描述报文信息状态
第一次握手客户端向服务器发送一个连接请求的报文段同步标识位 SYN = 1,随机选择一个起始序列号 seq = x,不携带数据(因 SYN 位被设置为 1 的报文段不能携带数据,但要消耗一个序号)客户端进入同步已发送状态(SYN_SNED),等待服务器确认
第二次握手服务器收到请求连接报文段后,若同意建立连接,则向服务端发回连接确认的报文段(为该 TCP 连接分配 TCP 缓存、变量)同步标志位 SYN = 1,确认标志位 ACK = 1,随机选择一个起始序号 seq = y,确认号字段设为 ack = x + 1,不携带数据服务器进入同步已接受状态(SYN_RCVD)
第三次握手客户端收到确认报文段后,向服务器再次发出连接确认报文段(为该 TCP 连接分配 TCP 缓存、变量)确认标记位 ACK 设为 1,序号 seq = x +1,确认号字段 ack = y + 1,可携带数据(因 SYN 没有设置为 1,若不携带数据则不消耗序号)客户端、服务端都进入已创建状态(可开始发送数据)
为什么客户端还要发送一次确认呢?

这主要是为了防止已失效的连接请求报文段突然又传送到了服务端,因而产生错误。客户端还要发送一次确认,服务端由于收不到客户端的确认信息,即知道客户端并无要求建立 TCP 连接,故服务器也就不会一直等待客户端发送数据。

啥是已经失效的链接呢?如客户端发出的第一个连接请求报文段无丢失,而是在某个网络节点长时间滞留了,导致延误到连接释放后的某个时间才到达服务器,但是服务端并不知道这是一个早已失效的报文段,于是仍然向客户端发出了确认报文段,同意建立 TCP 连接,这时候服务端就一直等待客户端再次发起请求报文段。但是对于客户端来说,报文已经失效了就不会向服务端发送数据。

SYN 洪泛攻击:

从上面可看出,服务端的 TCP 资源分配时刻是在完成第二次握手时,而客户端的 TCP 资源分配是在完成第三次握手时,这就使得服务端容易受 SYN 洪泛攻击,即同时多个客户端发起连接请求,从而需进行多个请求的 TCP 连接资源分配。

2、四次挥手

在通信结束后,双方都可以释放连接,共需四次挥手。

释放 TCP 连接前,客户端和服务端都处于已创建状态,直到客户端主动关闭 TCP 连接。

在这里插入图片描述

挥手描述报文信息状态
第一次挥手客户端向服务端发送一个连接释放的报文段(同时停止发送数据)终止控制位 FIN = 1,报文段序号设为前面传送数据最后一个字节的序号加一:seq = u,可携带数据(FIN = 1 的报文即使不携带数据也消耗一个序号)客户端进入终止等待状态(FIN_WAIT_1)等待服务端的确认
第二次挥手服务端接收到连接释放报文段后,则向客户端发回连接释放确认的报文段确认标记位 ACK = 1,报文序列号设为前面传送数据最后一个字节的序号加一:seq = v,确认号字段 ack = u + 1服务端进入关闭等待状态(CLOSE_WAIT),客户端收到服务端的确认后,进入终止等待 2 状态(FIN_WAIT - 2),等待服务器发出释放连接请求;至此,客户端到服务端的 TCP 连接已经断开,但是服务端到客户端的连接未断开
第三次挥手若服务端已无要向客户端发送数据,则发出释放连接的报文段终止控制位 FIN = 1,确认标记位 ACK = 1,报文段序号 seq = w,重复上次已发送的确认号字段 ack = u + 1,可携带数据服务端进入最后确认状态(LAST-ACK)
第四次挥手客户端收到连接释放报文段后,则向服务端发回连接释放确认的报文段确认标记位 ACK = 1,报文段序号 seq = u + 1,确认号字段 ack = w + 1,可携带数据客户端进入时间等待状态(TIME-WAIT),服务端进入关闭状态(CLOSED);此时 TCP 连接还未释放,须经过时间等待计时器设置的时间 2MSL 后,客户端才进入连接关闭状态(CLOSED),即服务端进入关闭状态比客户端要早一些
为什么 TCP 释放连接需要四次挥手?

这是为了保证通信双方都能通知对方需断开连接,断开连接后,都无法接受或发送消息给对方。

为什么客户端关闭连接前需要等待 2MSL 的时间?即 TIME_WAIT 的作用是什么?

MSL 即最长报文段寿命,它的存在是为了保证客户端发送的最后一个连接释放确认报文能到达服务器,从而使得服务器能正常释放连接。

  • 客户端发送的最后一个连接释放确认报文,可能会丢失,当服务器收不到最后一个连接释放确认报文时则不会进入关闭状态,但是会超时重发连接释放报文。如果客户端不等待 2MSL 时间就直接进入关闭状态,当最后一个连接释放确认报文丢失,服务端重发释放报文时,客户端则无法接受到这个报文,因此也就无法发送连接释放确认报文,最终导致服务端无法进入关闭状态。
  • 2MSL 的时间,还可以防止上文提到的早已失效的连接请求报文出现在本连接中,客户端发送了最后一个连接释放请求确认报文后,再经过 2MSL 时候,则可使本连接持续时间内所产生的所有报文段都从网络中消失,即在下一个新的连接中就不会出现早已失效的连接请求报文
3、有限状态机

为了更清晰地看出TCP连接的各种状态之间的关系,如下给出了TCP的有限状态机。图中每一个方框即TCP可能具有的状态。每个方框中的大写英文字符串是TCP标准所使用的TCP连接状态名。状态之间的箭头表示可能发生的状态变迁。箭头旁边的字,表明引起这种变迁的原因,或表明发生状态变迁后又出现什么动作。请注意图中有三种不同的箭头。粗实线箭头表示对客户进程的正常变迁。粗虚线箭头表示对服务器进程的正常变迁。另一种细线箭头表示异常变迁。

在这里插入图片描述

The End

参考1

参考2

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值