1 TCP
1.1 简介
TCP是一个传输层协议,提供可靠传输,支持全双工,是一个连接导向的协议。
1.1 双工/单工
在任何一个时刻,如果数据只能单向发送,就是单工。
如果任何时刻数据都可以双向收发,这就是全双工,全双工需要大于 1 条线路。
TCP 是一个双工协议,数据任何时候都可以双向传输。这就意味着客户端和服务端可以平等地发送、接收信息。
1.2 主要特点
-
TCP是面向连接的传输层协议;所谓面向连接就是双方传输数据之前,必须先建立一条通道,例如三次握手就是建议通道的一个过程,而四次挥手则是结束销毁通道的一个其中过程。
-
每一条TCP连接只能有两个端点(即两个套接字),只能是点对点的;
-
TCP提供可靠的传输服务。传送的数据无差错、不丢失、不重复、按序到达;
-
TCP提供全双工通信。允许通信双方的应用进程在任何时候都可以发送数据,因为两端都设有发送缓存和接受缓存;
-
面向字节流。虽然应用程序与TCP交互是一次一个大小不等的数据块,但TCP把这些数据看成一连串无结构的字节流,它不保证接收方收到的数据块和发送方发送的数据块具有对应大小关系,例如,发送方应用程序交给发送方的TCP10个数据块,接收方的TCP可能只用收到的4个数据块字节流交付给上层的应用程序。
1.3 可靠性原理
可靠传输有如下两个特点:
- 传输信道无差错,保证传输数据正确;
- 不管发送方以多快的速度发送数据,接收方总是来得及处理收到的数据;
首先,采用三次握手来建立TCP连接,四次握手来释放TCP连接,从而保证建立的传输信道是可靠的。
其次,TCP采用了连续ARQ协议(Automatic Repea ReQuest)来保证数据传输的正确性,使用滑动窗口协议来保证接方能够及时处理所接收到的数据,进行流量控制。
最后,TCP使用慢开始、拥塞避免、快重传和快恢复来进行拥塞控制,避免网络拥塞。
1.2 ARQ
ARQ协议,即自动重传请求(Automatic Repeat-reQuest),是OSI模型中的错误纠正协议之一。它通过使用确认和重传这两个机制,在不可靠服务的基础上实现可靠的信息传输。如果发送方在发送后一段时间之内没有收到确认帧,它通常会重新发送。重传的请求是自动进行的,接收方不需要请求发送方重传某个出错的分组。
ARQ包括停止等待ARQ协议和 连续ARQ协议。
1.2.1 停止等待ARQ
1.2.1.1 正常传输
- “停止等待”就是每发送完一个分组就停止发送,等待对方的确认。在收到确认后再发送下一个分组。
- 全双工通信的双方既是发送方也是接收方。
- 为了讨论问题的方便,我们仅考虑 A 发送数据,而 B 接收数据并发送确认。因此 A 叫做发送方,而 B 叫做接收方
1.2.1.2 传输出现差错
在接收方 B 会出现两种情况:
- B 接收 M1 时检测出了差错,就丢弃 M1,其他什么也不做(不通知 A 收到有差错的分组)。
- M1 在传输过程中丢失了,这时 B 当然什么都不知道,也什么都不做。
在这两种情况下,B 都不会发送任何信息。A都必须重发分组,直到B正确接收为止,这样才能实现可靠通信。
超时重传
A怎么知道 B 是否正确收到了 M1 呢?
- A 为每一个已发送的分组都设置了一个超时计时器。
- A 只要在超时计时器到期之前收到了相应的确认,就撤销该超时计时器,继续发送下一个分组 M2 。
若A在超时计时器规定时间内没有收到B的确认ACK,就重发该分组。无论是自己发送的分组出错、丢失了,或者 是 B 发送的确认丢失了。
假定 B 又收到了重传的分组 M1。这时 B 应采取两个行动:
- 丢弃这个重复的分组 M1,不向上层交付。
- 向 A 发送确认。不能认为已经发送过确认就不再发送,因为 A 之所以重传 M1 就表示 A 没有收到对 M1 的确认
若分组正确到达B,但B回送的确认ACK丢失或延迟了,A未收到B的确认,会超时重发。B 可能会收到重复的 M1 。B如何知道收到了重复的分组,需要丢弃呢?
A为每一个发送的分组都进行编号。若B收到了编号相同的分组,则认为收到了重复分组,丢弃重复的分组,并回送确认(之所以会收到重复的分组就是因为发送端没有正常收到确认)。
B为发送的确认也进行编号,指示该确认是对哪一个分组的确认。
A根据确认及其编号,可以确定它是对哪一个分组的确认,避免重发发送。若为重复的确认,则将其丢弃。
1.2.1.3 信道利用率低
1.2.2 连续ARQ
1.2.2.1 流水线传输
为了提高传输效率,发送方可连续发送多个分组,不必每发完一个分组就停顿下来等待对方的确认。这样可使信道上一直有数据不间断地传送。
流水线传输通常要求 :
必须增加序号范围,因为每个输送中的分组(不计算重传的)必须有一个唯一的序号,因为可能存在有多个在输送中未确认的报文。
协议的发送方和接收方要能缓存多个分组。发送方至少要能缓存那些已发送但没有确认的分组,接收方可能要缓存那些已正确接收的分组。
所需序号范围和对缓冲的要求取决于数据传输协议如何处理丢失、损坏及延时过大的分组。
解决流水线传输的差错有两种滑动窗口协议:回退N(Go-Back- N,GBN) 和选择重传(Selective Repeat,SR) 。
累积确认
即接收方不必对收到的分组逐个发送确认,而是对按序到达的最后一个分组发送确认。
因此,接收方不必对中间某个确认包的丢失进行重传,因为累积确认的效果,一旦一个较大序号的ACK被接收到,则表示这个包之前的包都已经成功收到。如果接受方收到了这个确认,则表示到这个分组为止之前的所有分组都已正确收到了。
但同时累积确认也有缺陷,例如发送方传送了5个包,但是第3个包丢失了,第4和第5个正常。这时根据累积确认,接收方只能传送前两个包的ACK(按序到达的最后一个)。在接收到第2个包ACK的发送方不知道后面3个包是否到达,就会将后3个包全部进行重传。即:Go-back-N。
优点:容易实现,即使部分确认丢失也不必重传。
缺点:不能向发送方反映出接收方已经正确收到的所有分组的信息。
1.2.2.2 滑动窗口
滑动窗口协议(Sliding Window Protocol)以基于分组的数据传输协议为特征。因此该协议适用于对按顺序传送分组的可靠性要求较高的环境,例如在数据链路层(OSI模型)以及传输控制协议(TCP)中。
提供TCP的可靠性(最基本的传输可靠性来源于“确认重传”机制),避免丢包
提供TCP的流控特性,用于网络数据传输时的流量控制,以避免拥塞的发生。
滑动窗口协议在发送方和接收方之间各自维持一个滑动窗口,发送方是发送窗口,接收方是接收窗口(两个窗口大小不一定相同)。使用滑动窗口协议控制发送方和接收方所能发送和接收的分组的数量和编号
它允许发送方发送多个分组而不需等待确认,TCP的滑动窗口是以字节为单位的。每收到一个确认,发送方就把发送窗口向前滑动。
发送窗口中有四个概念:
- 已发送并收到确认的数据(不在发送窗口和发送缓冲区之内)
- 已发送但未收到确认的数据(位于发送窗口之内)
- 允许发送但尚未发送的数据(位于发送窗口之内)
- 发送窗口之外的缓冲区内暂时不允许发送的数据
接收窗口中也有四个概念:
- 已发送确认并交付主机的数据(不在接收窗口和接收缓冲区之内)
- 未按序收到的数据(位于接收窗口之内)
- 允许接收的数据(位于接收窗口之内)
- 不允许接收的数据(位于发送窗口之内)
当A 的发送窗口内的序号都已用完,但还没有再收到确认时,必须停止发送。为了解决流水线传输的差错,TCP协议提供两种滑动窗口:回退N(Go-Back- N,GBN) 和选择重传(Selective Repeat,SR) 来解决这个问题
回退N帧
如果发送方发送了前 5 个分组,而中间的第 3 个分组丢失了。这时接收方只能对前两个分组发出确认。发送方无法知道后面三个分组的下落,而只好把后面的三个分组都再重传一次。这就叫做 Go-back-N(回退 N),表示需要再退回来重传已发送过的 N 个分组。可见当通信线路质量不好时,连续 ARQ 协议会带来负面的影响。
如果下面的网络层协议丢失了很多分组,那么返回N协议的效率就会很低。因为每当一个分组损坏,发送方就需要重传所有待确认的分组,虽然其中有些分组实际上已经完整地被接收了
选择重传
- 发送方维持着一个窗口,包含可发送或已发送但未被确认的序号。
- 接收方维持着一个窗口,包含可接收的序号,每个序号还保留一个缓冲区。与每个缓冲区项相关联的还有一个标志位,用来指明缓冲区是满的还是空的。
- 每到达一个帧,接收方通过检查它的序号,看是否落在窗口内。如果确实落在窗口内且之前没有接收过,则接收该分组然后保存在缓冲区并返回一个确认。等前面这些帧都到达后一起交付给上层
- 发送端每个发送缓冲都设有一个超时一个超时计时器,一个超时事件发生后相应缓冲区的帧就会被重发
1.2 报文
TCP虽面向字节流,但传送的数据单元为报文段
报文段 = 首部 + 数据2部分
TCP的全部功能体现在它首部中各字段的作用。首部前20个字符固定、后面有4n个字节是根据需而增加的选项。故 TCP首部最小长度 = 20字节。
「端口」:源端口号和目地端口各占16位两个字节,也就是端口的范围是2^16=65535。另外1024以下是系统保留的,从1024-65535是用户使用的端口范围
「seq序号」:占4字节,TCP连接中传送的字节流中的每个字节都按顺序编号。
例如:一段报文的序号字段值是107,携带的数据是100个字段,下一个报文段序号从107+100=207开始。
「ack确认号」:4个字节,是期望收到对方下一个报文段的第一个数据字节的序号。
例如:B收到A发送的报文,其序号字段是301,数据长度是200字节,表明B正确收到A发送的到序号500为止的数据(301+200-1=500),B期望收到A下一个数据序号是501,B发送给A的确认报文段中把ack确认号置为501。
「数据偏移」:头部有可选字段,长度不固定,指出TCP报文段的数据距离报文段的起始处有多远。
「保留」:保留今后使用的,被标为1。
「控制位」:由8个标志位组成。每个标志位表示一个控制功能。
其中主要的6个:
- 「URG紧急指针标志」,为1表示紧急指针有效,为0忽略紧急指针。
- 「ACK确认序号标志」,为1表示确认号有效,为0表示报文不含确认信息,忽略确认号字段,上面的确认号是否有效就是通过该标识控制的。
- 「PSH标志」,为1表示带有push标志的数据,指示接收方在接收到该报文段以后,应尽快将该报文段交给应用程序,而不是在缓冲区排队。
- 「RST重置连接标志」,重置因为主机崩溃或其他原因而出现错误的连接,或用于拒绝非法的报文段或非法的连接。
- 「SYN同步序号」,同步序号,用于建立连接过程,在连接请求中,SYN=1和ACK=0表示该数据段没有使用捎带的确认域,而连接应答捎带一个确认,即SYN=1和ACK=1。。
- 「FIN终止标志」,用于释放连接,为1时表示发送方没有发送了。
「窗口」:滑动窗口大小,用来告知发送端接收端缓存大小,以此控制发送端发送数据的速率,从而达到流量控制。
「校验和」:奇偶校验,此校验和是对整个的TCP报文段(包括TCP头部和TCP数据),以16位进行计算所得,由发送端计算和存储,接收端进行验证。
「紧急指针」:只有控制位中的URG为1时才有效,指出本报文段中的紧急数据的字节数。
「选项」:其长度可变,定义其他的可选参数。
1.3 粘包与拆包
TCP是面向字节流的协议,把上层应用层的数据看成字节流,所以它发送的不是固定大小的数据包,TCP协议也没有字段说明发送数据包的大小。而且TCP不保证接受方应用程序收到的数据块和发送应用程序发送的数据块具有对应的大小关系。
比如发送方应用程序交给发送方TCP 10个数据块,接受方TCP可能只用了4个数据块就完整的把接受到的字节流交给了上层应用程序。
TCP底层并不了解上层业务数据的具体含义,它会根据TCP缓冲区的实际情况进行包的划分,所以在业务上认为,一个完整的包可能会被TCP拆分成多个包进行发送,也有可能把多个小的包封装成一个大的数据包发送,这就是所谓的TCP粘包和拆包问题
「解决策略」
由于TCP无法理解上一层的业务数据特点,所以TCP是无法保证发送的数据包不发生粘包和拆包,这个问题只能通过上层的协议栈设计来解决,解决思路有一下几种:
- 消息定长:每个发送的数据包大小固定,比如100字节,不足100字节的用空格补充,接受方取数据的时候根据这个长度来读取数据
- 消息末尾增加换行符来表示一条完整的消息:接收方读取的时候根据换行符来判断是否是一条完整的消息,如果消息的内容也包含换行符,那么这种方式就不合适了。
- 将消息分为消息头和消息尾两部分,消息头指定数据长度,根据消息长度来读取完整的消息,例如UDP协议是这么设计的,用两个字节来表示消息长度,所以UDP不存在粘包和拆包问题。
1.4 三次握手
「第一次握手」:
客户端将TCP报文标志位SYN置为1,随机产生一个序号值seq=J,保存在TCP首部的序列号字段里,指明客户端打算连接的服务器的端口,并将该数据包发送给服务器端,发送完毕后,客户端进入SYN_SENT状态,等待服务器端确认。
「第二次握手」:
服务器端收到数据包后由标志位SYN=1知道客户端请求建立连接,服务器端将TCP报文标志位SYN和ACK都置为1,ack=J+1,随机产生一个序号值seq=K,并将该数据包发送给客户端以确认连接请求,服务器端进入SYN_RCVD状态。
「第三次握手」:
客户端收到确认后,检查ack是否为J+1,ACK是否为1,如果正确则将标志位ACK置为1,ack=K+1,并将该数据包发送给服务器端,服务器端检查ack是否为K+1,ACK是否为1,如果正确则连接建立成功,客户端和服务器端进入ESTABLISHED状态,完成三次握手,随后客户端与服务器端之间可以开始传输数据了。
「上面写的ack和ACK,不是同一个概念:」
- 小写的ack代表的是头部的确认号Acknowledge number, 缩写ack,是对上一个包的序号进行确认的号,
ack=seq+1。 - 大写的ACK,则是我们上面说的TCP首部的标志位,用于标志的TCP包是否对上一个包进行了确认操作,如果确认了,则把ACK标志位设置成1。
「TCP为什么三次握手而不是两次握手」
- 为了实现可靠数据传输, TCP 协议的通信双方, 都必须维护一个序列号, 以标识发送出去的数据包中, 哪些是已经被对方收到的。三次握手的过程即是通信双方相互告知序列号起始值, 并确认对方已经收到了序列号起始值的必经步骤
- 如果只是两次握手, 至多只有连接发起方的起始序列号能被确认, 另一方选择的序列号则得不到确认
1.5 四次挥手
挥手请求可以是Client端,也可以是Server端发起的,我们假设是Client端发起:
- 第一次挥手:Client端发起挥手请求,向Server端发送标志位是
FIN报文段,设置序列号seq,此时,Client端进入FIN_WAIT_1状态,这表示Client端没有数据要发送给Server端了。 - 第二次挥手:Server端收到了Client端发送的
FIN报文段,向Client端返回一个标志位是ACK的报文段,ack设为seq加1,Client端进入FIN_WAIT_2状态,Server端告诉Client端,我确认并同意你的关闭请求。 - 第三次挥手:Server端向Client端发送标志位是
FIN的报文段,请求关闭连接,同时Client端进入LAST_ACK状态。 - 第四次挥手 :Client端收到Server端发送的
FIN报文段,向Server端发送标志位是ACK的报文段,然后Client端进入TIME_WAIT状态,Server端收到Client端的ACK报文段以后,就关闭连接,此时,Client端等待2MSL的时间后依然没有收到回复,则证明Server端已正常关闭,那好,Client端也可以关闭连接了。
「为什么连接的时候是三次握手,关闭的时候却是四次握手?」
由于TCP协议是一种面向连接的、可靠的、基于字节流的运输层通信协议,TCP是全双工模式。
这就意味着,关闭连接时,当Client端发出FIN报文段时,只是表示Client端告诉Server端数据已经发送完毕了。当Server端收到FIN报文并返回ACK报文段,表示它已经知道Client端没有数据发送了,但是Server端还是可以发送数据到Client端的,所以Server很可能并不会立即关闭SOCKET,直到Server端把数据也发送完毕。
当Server端也发送了FIN报文段时,这个时候就表示Server端也没有数据要发送了,就会告诉Client端,我也没有数据要发送了,之后彼此就会愉快的中断这次TCP连接。
「为什么TIME_WAIT要等待2MSL?」
MSL:报文段最大生存时间,它是任何报文段被丢弃前在网络内的最长时间。
有以下两个原因:
- 第一点:保证TCP协议的全双工连接能够可靠关闭:由于IP协议的不可靠性或者是其它网络原因,导致了Server端没有收到Client端的ACK报文,那么Server端就会在超时之后重新发送FIN,如果此时Client端的连接已经关闭处于
CLOESD状态,那么重发的FIN就找不到对应的连接了,从而导致连接错乱,所以,Client端发送完最后的ACK不能直接进入CLOSED状态,而要保持TIME_WAIT,当再次收到FIN的时候,能够保证对方收到ACK,最后正确关闭连接。 - 第二点:保证这次连接的重复数据段从网络中消失 如果Client端发送最后的ACK直接进入
CLOSED状态,然后又再向Server端发起一个新连接,这时不能保证新连接的与刚关闭的连接的端口号是不同的,也就是新连接和老连接的端口号可能一样了,那么就可能出现问题:如果前一次的连接某些数据滞留在网络中,这些延迟数据在建立新连接后到达Client端,由于新老连接的端口号和IP都一样,TCP协议就认为延迟数据是属于新连接的,新连接就会接收到脏数据,这样就会导致数据包混乱,所以TCP连接需要在TIME_WAIT状态等待2倍MSL,才能保证本次连接的所有数据在网络中消失。
1.6 流量控制
「RTT和RTO」
RTT:发送一个数据包到收到对应的ACK,所花费的时间
RTO:重传时间间隔(TCP在发送一个数据包后会启动一个重传定时器,RTO即定时器的重传时间)
开始预先算一个定时器时间,如果回复ACK,重传定时器就自动失效,即不需要重传;如果没有回复ACK,RTO定时器时间就到了,重传。
RTO是本次发送当前数据包所预估的超时时间,RTO不是固定写死的配置,是经过RTT计算出来的。
「滑动窗口」
TCP的滑动窗口主要有两个作用:
保证TCP的可靠性
保证TCP的流控特性
TCP报文头有个字段叫Window,用于接收方通知发送方自己还有多少缓存区可以接收数据,发送方根据接收方的处理能力来发送数据,不会导致接收方处理不过来,这便是流量控制。
发送方都维持了一个连续的允许发送的帧的序号,称为发送窗口;同时,接收方也维持了一个连续的允许接收的帧的序号,称为接收窗口。发送窗口和接收窗口的序号的上下界不一定要一样,甚至大小也可以不同。不同的滑动窗口协议窗口大小一般不同。
发送方窗口内的序列号代表了那些已经被发送,但是还没有被确认的帧,或者是那些可以被发送的帧。
滑动窗口由四部分组成每个字节的数据都有唯一顺序的编码,随着时间发展,未确认部分与可以发送数据包编码部分向右移动,形式滑动窗口
绿色:发送成功并已经ACK确认的数据黄色:发送成功等待ACK确认的数据(占用滑动窗口大小)紫色:滑动窗口剩余大小可以发送的字节数量(滑动窗口可用大小)灰色:后续数据编码
接收窗口的大小就是滑动窗口的最大值,数据传输过程中滑动窗口的可用大小是动态变化的。
但是还有这么一点,滑动窗口的设计仅仅是考虑到了处理方的处理能力,但是没有考虑到道路的通畅问题 就好像服务端可以处理100M数据,但是传输的数据99M都堵在路上了,这不就是导致道路阻塞了么?这就需要另外一个设计拥塞避免
「流量控制的目的」
如果发送者发送数据过快,接收者来不及接收,那么就会有分组丢失。
为了避免分组丢失,控制发送者的发送速度,使得接收者来得及接收,这就是流量控制。
流量控制根本目的是防止分组丢失,它是构成TCP可靠性的一方面。
「如何实现流量控制」
由滑动窗口协议(连续ARQ协议)实现。滑动窗口协议既保证了分组无差错、有序接收,也实现了流量控制。主要的方式就是接收方返回的 ACK 中会包含自己的接收窗口的大小,并且利用大小来控制发送方的数据发送。
「流量控制引发的死锁」
当发送者收到了一个窗口为0的应答,发送者便停止发送,等待接收者的下一个应答。
但是如果这个窗口不为0的应答在传输过程丢失,发送者一直等待下去,而接收者以为发送者已经收到该应答,等待接收新数据,这样双方就相互等待,从而产生死锁。
为了避免流量控制引发的死锁,TCP使用了持续计时器。每当发送者收到一个零窗口的应答后就启动该计时器。时间一到便主动发送报文询问接收者的窗口大小。若接收者仍然返回零窗口,则重置该计时器继续等待;若窗口不为0,则表示应答报文丢失了,此时重置发送窗口后开始发送,这样就避免了死锁的产生。
1.7 拥塞控制
「为什么要进行拥塞控制」
假设网络已经出现拥塞,如果不处理拥塞,那么延时增加,出现更多丢包,触发发送方重传数据,加剧拥塞情况,继续恶性循环直至网络瘫痪。
拥塞控制与流量控制的适应场景和目的均不同。
拥塞发生前,可避免流量过快增长拖垮网络;拥塞发生时,唯一的选择就是降低流量。
主要使用4种算法完成拥塞控制:
- 慢启动
- 拥塞避免
- 快重传算法
- 快速恢复算法
算法1、2适用于拥塞发生前,算法3适用于拥塞发生时,算法4适用于拥塞解决后(相当于拥塞发生前)。
「rwnd与cwnd」
rwnd(Receiver Window,接收者窗口)与cwnd(Congestion Window,拥塞窗口):
- rwnd是用于流量控制的窗口大小,主要取决于接收方的处理速度,由接收方通知发送方被动调整。
- cwnd是用于拥塞处理的窗口大小,取决于网络状况,由发送方探查网络主动调整。
同时考虑流量控制与拥塞处理,则发送方窗口的大小不超过min{rwnd, cwnd}。
「慢启动算法」
慢开始算法的思路就是,不要一开始就发送大量的数据,先探测一下网络的拥塞程度,也就是说由小到大逐渐增加拥塞窗口的大小。
这里用报文段的个数作为拥塞窗口的大小举例说明慢开始算法,实际的拥塞窗口大小是以字节为单位的。
一个传输轮次所经历的时间其实就是往返时间RTT,而且每经过一个传输轮次,拥塞窗口cwnd就加倍。
为了防止cwnd增长过大引起网络拥塞,还需设置一个慢开始门限ssthresh状态变量。
- cwnd<ssthresh时,使用慢开始算法。
- 当cwnd>ssthresh时,改用拥塞避免算法。
- 当cwnd=ssthresh时,慢开始与拥塞避免算法任意
注意,这里的慢并不是指cwnd的增长速率慢,而是指在TCP开始发送报文段时先设置cwnd=1,然后逐渐增大,这当然比按照大的cwnd一下子把许多报文段突然注入到网络中要慢得多。
「拥塞避免算法」
让拥塞窗口cwnd缓慢地增大,即每经过一个往返时间RTT就把发送方的拥塞窗口cwnd加1,而不是加倍。
这样拥塞窗口cwnd按线性规律缓慢增长,比慢开始算法的拥塞窗口增长速率缓慢得多
无论是在慢开始阶段还是在拥塞避免阶段,只要发送方判断网络出现拥塞(其根据就是没有按时收到确认,虽然没有收到确认可能是其他原因的分组丢失,但是因为无法判定,所以都当做拥塞来处理),就把慢开始门限ssthresh设置为出现拥塞时的发送窗口大小的一半(但不能小于2)。
然后把拥塞窗口cwnd重新设置为1,执行慢开始算法。
这样做的目的就是要迅速减少主机发送到网络中的分组数,使得发生拥塞的路由器有足够时间把队列中积压的分组处理完毕。
「整个拥塞控制的流程:」
假定cwnd=24时,网络出现超时(拥塞),则更新后的ssthresh=12,cwnd重新设置为1,并执行慢开始算法。
当cwnd=12=ssthresh时,改为执行拥塞避免算法
注意:拥塞避免并非完全能够避免了阻塞,而是使网络比较不容易出现拥塞。
「快重传算法」
快重传要求接收方在收到一个失序的报文段后就立即发出重复确认(为的是使发送方及早知道有报文段没有到达对方,可提高网络吞吐量约20%)而不要等到自己发送数据时捎带确认。
快重传算法规定,发送方只要一连收到三个重复确认就应当立即重传对方尚未收到的报文段,而不必继续等待设置的重传计时器时间到期
「快恢复算法」
快重传配合使用的还有快恢复算法,有以下两个要点:
- 当发送方连续收到三个重复确认时,就把ssthresh门限减半(为了预防网络发生拥塞)。
- 但是接下去并不执行慢开始算法
考虑到如果网络出现拥塞的话就不会收到好几个重复的确认,所以发送方现在认为网络可能没有出现拥塞。
所以此时不执行慢开始算法,而是将cwnd设置为ssthresh减半后的值,然后执行拥塞避免算法,使cwnd缓慢增大。
2 UDP
2.1 简介
-
UDP是无连接的传输层协议;
-
UDP使用尽最大努力交付,不保证可靠交付;
-
UDP是面向报文的,对应用层交下来的报文,不合并,不拆分,保留原报文的边界;
-
UDP没有拥塞控制,因此即使网络出现拥塞也不会降低发送速率;
-
UDP支持一对一 一对多 多对多的交互通信;
-
UDP的首部开销小,只有8字节
2.2 报文段
UDP的报文段共有2个字段:数据字段 + 首部字段
-
源端口:这个字段占据 UDP 报文头的前 16 位,通常包含发送数据报的应用程序所使用的 UDP 端口,接收端的应用程序利用这个字段的值作为发送响应的目的地址,这个字段是可选的,所以发送端的应用程序不一定会把自己的端口号写入该字段中,如果不写入端口号,则把这个字段设置为 0,这样,接收端的应用程序就不能发送响应了。
-
目的端口:接收端计算机上 UDP 软件使用的端口,占据 16 位。
-
长度:该字段占据 16 位,表示 UDP 数据报长度,包含 UDP 报文头和 UDP 数据长度,因为 UDP 报文头长度是 8 个字节,所以这个值最小为 8。
-
校验值:该字段占据 16 位,可以检验数据在传输过程中是否被损坏。
2.3 UDP / TCP
-
TCP是可靠传输,UDP是不可靠传输;
-
TCP面向连接,UDP无连接;
-
TCP传输数据有序,UDP不保证数据的有序性;
-
TCP不保存数据边界,UDP保留数据边界;
-
TCP传输速度相对UDP较慢;
-
TCP有流量控制和拥塞控制,UDP没有;
-
TCP是重量级协议,UDP是轻量级协议;
-
TCP首部较长20字节,UDP首部较短8字节;
2.4 协议
HTTP、HTTPS、FTP、TELNET、SMTP(简单邮件传输协议)协议基于可靠的TCP协议。
TFTP、DNS、DHCP、TFTP、SNMP(简单网络管理协议)、RIP基于不可靠的UDP协议