传输控制协议TCP学习笔记

TCP (Transmission Control Protocol)

重要特点:

  • 面向连接
  • 面向字节流
  • 每一条连接只能有两个端点,只能是一对一的
  • 提供可靠交付的服务
  • 提供全双工通信

面向报文和面向字节流的区别:https://blog.csdn.net/ce123_zhouwei/article/details/8976006

TCP根据对方给出的窗口值和当前网络拥塞的程度来决定一个报文段应包含多少个字节(UDP发送的报文长度是应用进程给出的)。

TCP具有发送缓冲区和接收缓冲区,它可把太长的数据划分短一些再传送,也可以等待缓冲区积累有足够多的字节后再构成报文段发送出去。

TCP连接的端点不是主机,不是IP,不是应用进程,也不是运输层的协议端口。TCP连接的端点叫做Socket或插口。端口号拼接到IP地址即构成了Socket。

套接字 Socket = (IP地址:端口号)

每一条TCP连接唯一地被通信两端的两个Socket所确定。

可靠传输的工作原理

理想的传输条件:

  • 传输信道不产生差错
  • 不管发送方以多快的速度发送数据,接收方总是来得及处理收到的数据

实际网络中,我们可以使用一些可靠传输协议,当出现差错时让发送方重传,同时在接收方来不及处理收到的数据时,及时告诉发送方适当降低发送数据的速度。这样,本来不可靠的信道就能够实现可靠传输了。

停止等待协议

“停止等待”就是每发送完一个分组就停止发送,等待对方的确认。在收到确认后再发送下一个分组。

超时重传

在发送方A超过一段时间仍然没有收到确认,就认为刚发送的分组丢失了,因而重传前面发送过的分组。这就叫做超时重传。

确认丢失

接收方丢弃重复的报文,并重传相应的确认报文。

确认迟到

收下迟到的确认但什么也不做。

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

停止等待协议的优点是简单,但缺点是信道利用率太低了。使用流水线传输可以大大提高信道利用率。流水线传输需要连续ARQ协议滑动窗口协议的支持。

连续ARQ协议

连续重发请求ARQ方案是指发送方可以连续发送一系列信息帧,即不用等前一帧被确认便可继续发送下一帧,效率大大提高。但在这种重发请求方案中,需要在发送方设置一个较大的缓冲存储空间(称作重发表),用以存放若干待确认的以及待发送信息帧。当发送方收到对某信息帧的确认帧后,便可从重发表中将该信息帧删除。所以,连续重发请求ARQ方案的链路传输效率大大提高,但相应地需要更大的缓冲存储空间。

连续ARQ协议规定,发送方维持一个发送窗口,发送方每收到一个确认,就把发送窗口向前滑动一个分组的位置。接收方一般都是采用累积确认的方式。就是说,接收方不必对收到的分组阻隔发送确认,而是在和搜到几个分组后,对按序到达的最后一个分组发送确认。这样做的优点是实现容易,节省带宽;缺点是容易发生Go-back-N问题。

TCP可靠通信的具体实现

  • TCP连接的每一端都必须设有两个窗口——一个发送窗口和一个接收窗口。
  • TCP的可靠传输机制用字节的序号进行控制。TCP所有的确认都是基于字节序号而不是基于报文段
  • TCP两端的四个窗口经常处于动态变化之中
  • TCP连接的往返时间RTT也不是固定不变的。需要使用特定的算法估算较为合适的重传时间。

TCP报文段首部格式

TCP

下面是一些重要字段的说明:

  • 源端口、目的端口:各占两个字节,写入源端口和目的端口
  • 序号:TCP连接中传送的字节流中的每一个字节都按顺序编号,该字段写入本报文段所发送的数据的第一个字节的序号
  • 确认号:期望收到对方下一个报文段的第一个数据字节的序号。
  • 数据偏移:占4位,实际指出了TCP报文段的首部的长度
  • 保留:占6位,保留为今后使用,目前应置为0.
  • URG(URGent)紧急:当URG=1时,表示紧急指针字段有效。他告诉系统此报文中有紧急数据,应尽快送达。
  • ACK(Acknowledgment):仅当该字段ACK=1时“确认号”字段才有效。TCP规定,在连接建立后所有传送的报文段都必须把ACK置1.
  • PSH(PUSH)推送:接收方TCP收到PSH=1的报文段,就尽快地交付接收应用进程,而不再等到整个缓存都填满了后再向上交付。推送操作很少使用。
  • RST(ReSet)复位:当RST=1时,表明TCP连接中出现严重差错,必须释放连接,然后再重新建立运输连接。
  • SYN(Synchronization)同步:在连接建立时用来同步序号。当SYN=1而ACK=0时,表明这个是一个连接请求报文。对方若同意建立连接,则应在响应的报文段中使SYN=1和ACK=1.因此。
  • FIN(Finish)终止:用来释放一个连接。当FIN=1时,表明此报文段的发送方的数据已发送完毕,并要求释放运输连接。
  • 窗口:占2字节。窗口值是0 ~ 216-1之间的整数。窗口是指发送本报文段的一方的接收窗口,它告诉对方,自己缓冲区还能够接受的字节数。
  • 检验和:占2字节。检验和字段检验的范围包括伪首部、TCP首部和数据这三个部分(UDP也是,但IP只检验头部而不检验数据部分,因为数据部分在上层协议中已经检验过了)。
  • 紧急指针:占2字节。紧急指针仅在URG=1时有效,它指出本报文段中的紧急数据的字节数(紧急数据结束后就是普通数据)。因此,紧急指针指出了紧急数据的末尾在报文段中的位置。
  • 选项:长度可变,最长可以达到40个字节

缓存与窗口的区别

发送/接收缓存与发送/接收窗口并不是同一个概念,窗口通常只是缓存的一部分。

发送缓存用来暂时存放:

  • 发送应用程序传送给发送方TCP准备发送的数据;
  • TCP已发送出但尚未收到确认的数据(以备重传需要)

send

已被确认的数据应当从发送缓存中删除,因此发送缓存和发送窗口的后沿是重合的。

接收缓存用来暂时存放:

  • 按序到达的、但尚未被接收应用程序读取的数据;
  • 未按序到达的数据

recv

接收缓存必须要为接收窗口中的字节预留位置,因此接收缓存和接收窗口的前沿重合。按序到达的数据不在接收窗口中,但是接收缓存必须保存它们,直至接收应用程序读取它们。

流量控制

流量控制就是让发送方的发送速率不要太快,要让接收方来得及接收。

利用滑动窗口机制可以很方便地在TCP连接上实现对发送方的流量控制。

持续计时器(Persistence Timer)

针对的问题:A和B是一个TCP连接的两端。B向A发送了零窗口(接收缓冲区没有空间了)的报文段不久,B的接收缓存又有了一些存储空间。于是B向A发送了rwnd=400的报文段。然而这个报文段在传送过程中丢失了。A一直等待收到B发送的非零窗口的通知,而B也一直等待A发送的数据。如果没有其他措施,这种相互等待的死锁局面将一直延续下去。

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

作用范围:TCP为每一个连接设有一个持续计时器。

TCP的传输效率

TCP的发送方有发送缓冲区,应用程序将要发送的数据交给TCP的发送缓冲区就不管了。那么TCP应该何时将数据发送出去呢?有3种机制:

  1. TCP维持一个最大报文长度MSS的变量,当缓冲区中存放的数据达到MSS字节时,就组装成一个TCP报文段发送出去。
  2. 由发送方的应用进程指明要求发送报文段,即TCP支持的推送(PUSH)操作
  3. 发送方的一个计时器期限到了,这时就把当前已有的缓存数据装入报文段(长度不能超过MSS)发送出去。
情形一、发送方应用程序逐字节发送到TCP的发送缓存

在TCP的实现中广泛使用Nagle算法来解决这个问题:
若发送应用程序把要发送的数据逐字节地发送到TCP的发送缓存,则发送方就把第一个数据字节先发送出去,把后面达到的数据字节都缓存起来。当发送方收到对第一个数据字符的确认后,再把发送缓存中的所有数据组装成一个报文段发送出去,同时继续对随后到达的数据进行缓存。只有在收到对前一个报文段的确认后才继续发送下一个报文段。

当数据到达较快而网络速率较慢时,用这种方法可以明显减少所用的网络带宽。

情形二、接收方应用程序逐个字节读取TCP接收缓存

情形描述:TCP接收方的缓存已满,而交互式的应用进程一次只从接受缓存中读取一个字节,然后向发送方发送确认,并把窗口设置为1字节(但发送的数据报是40字节长)。接着,发送方发来1个字节的数据(但发送方的数据报长度为41)。这样,在网络中流通的数据中,只有1/41是有效的,这大大浪费了网络带宽。

解决方案:可以让接收方等待一段时间,使得接收缓存已有足够空间容纳一个最长的报文段,或者等到接收方缓存已有一半空闲的空间。只要出现这两种情况之一,接收方就发出确认报文,并向发送方通知当前的窗口大小。

TCP的拥塞控制

所谓拥塞控制就是防止过多的数据注入到网络中,这样可以使网络中的路由器或链路不致过载。

拥塞控制是一个全局性的过程,涉及到所有的主机、所有的路由器,以及与降低网络传输性能有关的所有因素。相反,流量控制往往是指点到点通信量的控制,是个端到端的问题。流量控制所要做的就是抑制发送端发送数据的速率,以便接收端来得及接收。

tcp
(拥塞控制图)

拥塞控制是一个动态问题,它是很难设计的。从大的方面看,拥塞控制可以分为开环控制和闭环控制两种方法:

  1. 开环控制:在设计网络时事先将有关发生拥塞的因素考虑周到,力求网络在工作时不产生拥塞。但一旦整个系统运行起来,就不再中途进行更正了。
  2. 闭环控制:闭环控制是基于反馈环路的概念,主要有以下几种措施:
    1. 检测网络系统以便检测到拥塞在何时、何处发生。
    2. 把拥塞发生的信息传送到可采取行动的地方。
    3. 调整网络系统的运行以解决出现的问题。

TCP拥塞控制的方法

TCP进行拥塞控制的算法有四种,即慢开始(slow-start)、拥塞避免(congestion avoidence)、快重传(fast retransmit)和快恢复(fast recovery)。他们都是基于拥塞窗口的控制方法,发送方维持一个叫做拥塞窗口cwnd(congestion window)的状态变量。拥塞窗口的大小取决于网络的拥塞程度,并且动态地在变化。发送方让自己的发送窗口等于拥塞窗口。

发送方控制拥塞窗口的原则是:只要网络没有出现拥塞,拥塞窗口就可以再增大一些,以便把更多的分组发送出去。只要网络出现拥塞或有可能出现拥塞,就必须把拥塞窗口减小一些,以缓解网络出现的拥塞。

判断网络拥塞的依据就是出现了超时。

慢开始(slow-start)

由小到大逐渐增大发送窗口,也就是说,由小到大逐渐增大拥塞窗口数值。关于拥塞窗口的初始值大小,RFC5681文档中是这样描述的:

IW, the initial value of cwnd, MUST be set using the following
 guidelines as an upper bound.
 If SMSS > 2190 bytes:
 IW = 2 * SMSS bytes and MUST NOT be more than 2 segments
 If (SMSS > 1095 bytes) and (SMSS <= 2190 bytes):
 IW = 3 * SMSS bytes and MUST NOT be more than 3 segments
 if SMSS <= 1095 bytes:
 IW = 4 * SMSS bytes and MUST NOT be more than 4 segments

根据SMSS的不同,初始窗口大小介于2~4倍SMSS之间。

慢开始规定,在每收到一个对引得报文段的确认后,就可以把拥塞窗口增加最多一个SMSS的数值。这样,在理想情况下,发送方发送窗口的值会呈现1、2、4、8的增长规律,即每经过一个传输伦次(transmission round),拥塞窗口cwnd就加倍。

特别注意:慢开始的“慢”并不是指cwnd的增长速率慢,而是指在TCP开始发送报文段时,发送窗口的初始值很低(目的是试探一下网络的拥塞情况),然后再逐渐增大cwnd。

ssthresh(慢开始门限):使用慢开始所能达到的最大发送方拥塞窗口大小。

  • 当cwnd < ssthresh时,使用慢开始算法。
  • 当cwnd > ssthresh时,改用拥塞避免算法。
  • 当cwnd = ssthresh时,使用两者均可。
拥塞避免(congestion avoidence)

思想:让拥塞窗口cwnd缓慢地增大,即每经过一个往返时间RTT就把发送方的拥塞窗口cwnd加1,而不是像慢开始那样成倍增长。这个阶段是“加法增大”,比慢开始的增长速率慢得多。

slow-start

在上图的过程中,慢开始的初始值是1(1处),第一次ssthresh=16,当达到ssthresh后,改为拥塞避免算法(2处)。当拥塞窗口达到24时,出现了网络拥塞(3处),将ssthresh设置为当前拥塞窗口的一半(5处):ssthresh=24/2=12,并重新执行慢开始算法(4处)。

乘法减小:指不论在慢开始还是拥塞避免阶段,只要出现一次超时(即出现一次网络拥塞),就把慢开始门限值ssthresh设置为当前的拥塞窗口值乘以0.5.当网络频繁出现拥塞时,ssthresh值就下降得很快,以大大减少注入到网络中的分组数。

快重传(fast retransmit)

快重传算法的目的是让发送方尽早知道发生了个别报文段的丢失。

它首先要求接收方每收到一个失序的报文段后就立即发出重复确认。发送方只要一连收到三个重复确认就应当立即重传对方尚未收到的报文段。可以看出,快重传并非取消重传计时器,而是在某些情况下可更早地重传丢失的报文段。

快恢复(fast recovery)

当发送端收到连续三个重复的确认时,就执行“乘法减小”,把ssthresh减半。但接下来不执行慢开始算法,而是将拥塞窗口的大小设置为新的ssthresh,并执行拥塞避免算法,进行加法增大

fastRecovery

  • 加性增(AI):x(t+1)=x(t)+A, A>0
  • 加性减(AD):x(t+1)=x(t)-B, B<0
  • 乘性增(MI):x(t+1)=C*x(t), C>1
  • 乘性减(MD):x(t+1)=D*x(t), D<1

AI和AD的轨迹为45度的直线。AI使公平性增加,同时向过载区移动。AD使公平性降低,同时向轻载区移动。

MI和MD的轨迹为过原点的直线。MI和MD在等公平线上移动,故保持公平性不变。MI使轨迹向过载区移动,而MD使轨迹向轻载区移动。

AIMD过程的结果将收敛到效率线和公平线的交点。所以,TCP通过加性增乘性减完成了一种兼顾效率和公平的资源分配。

TCP拥塞控制流程图

congestion-control

主动队列管理AQM(Active Queue Management)

所谓“主动”就是不要等到路由器的队列长度已经达到最大值时才不得不丢弃后面到达的分组,因为这可能会造成全局同步(global synchronization)问题。应当在队列长度达到某个警戒值时,就主动丢弃到达的分组。这样就提醒了发送方放慢发送的速率,因而有可能使网络拥塞的程度减轻,甚至不出现网络拥塞。

AQM有不同的实现方式,其中一种就是流行多年的随机早期检测RED(Random Early Detection),RED的实现方式是这样的:

在路由器中维护两个参数,即队列长度的最小门限和最大门限。当每一个分组到达时,RED就按照规定的算法先计算当前的平均队列长度。

  • 若平均队列长度小于最小门限,则把新到达的分组放入队列进行排队。
  • 若平均队列长度超过最大门限,则把新到达的分组丢弃。
  • 若平均队列长度在最小门限和最大门限之间,则按照某一丢弃概率p把新到达的分组丢弃,这就体现了丢弃分组的随机性。

TCP的连接管理

TCP是面向连接的协议,TCP连接的建立和释放是每一次面向连接的通信中必不可少的过程。TCP的通信过程可以概括为三个阶段:连接建立、数据传输和连接释放。

TCP连接的建立——三次握手

3

TCP连接的释放——四次挥手

4

需要注意的是,在TIME-WAIT状态,需要等待2MSL的时间(MSL:Maximum Segment Lifetime),这么做的原因有以下两点:

  1. 为了保证A发送的最后一个ACK报文能够到达B
  2. 2MSL能够确保本次连接发出的所有报文都已经失效,避免影响下次连接。

客户端消失了怎么办

如果在双方通信过程中,客户端突然消失了(如客户端断电、断网等),服务器端怎么得知呢?

TCP设置了一个保活计时器(keepalive timer)。服务器每收到一次客户的数据,就重新设置保活计时器,时间的设置通常是两个小时。若两个小时没有收到客户的数据,服务器就发送一个探测报文段,以后则每隔75秒钟发送一次。若一连发送10个探测报文段后仍无客户端的响应,服务器就认为客户端出了故障,接着就关闭连接。

猜你喜欢

转载自blog.csdn.net/zhoucheng05_13/article/details/80530854
今日推荐