TCP协议


TCP协议

学习《计算机网络》

TCP是面向连接的传输层协议,需建立连接,数据传输完毕后必须释放已建立的连接

每条TCP连接只能有两个端点,点对点。连接的端点叫做套接字(socket),由IP+端口和冒号组成。

TCP提供可靠交付的服务,无差错、不丢失、不重复、并且按序到达。

提供全双工通信,TCP连接的两端都设有发送和接收缓存,应用程序只需要把数据传送给TCP,具体数据发送由TCP来决定,接收时,TCP把收到的数据放入缓存,
上层应用在合适的时候读取缓存中的数据。

面向字节流(stream),流入进程或从进程流出的字节序列。TCP把应用程序交下拉的数据看成仅仅是一串无结构的字节流,并不要知道其中的含义,
不保证接收应用收到的数据块和发送方应用程序所发出的数据块具有对应大小的关系。

停止等待协议

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

自动重传请求ARQ(Automatic Repeat Request)

这里讨论由A向B发送数据,B回复确认的单向通信。

  • 无差错

假定数据传输只在一个方向进行。
A发送分组M1,发送完就暂停,等待B的确认,B收到M1就向A发送确认。

  • 出差错

B接收M1是检测出了差错,就丢弃M1,其他什么都不做。因为A只要超过一段时间没有收到B的确认,就认为刚发送的分组丢失,
因而重传前面发送过的分组,这叫超时重传。要实现超时重传,需要在每发送一个分组就设置一个超时计时器
如果在超时计时器到期之前收到了对方的确认,就撤销已经设置的超时计时器。

A在发送完一个分组后,须暂时保留以发送的分组副本(重传可能需要使用),收到确认后才能清除副本。

分组和确认分组都必须进行编号,这样才能明确是哪一个分组收到了确认。

超时计时器设置的重传时间应当比数据在分组传输的平均往返时间更长一些,如果设置的很长,那么通信效率就会很低,如果设置很短,就会产生很多不必要的重传,浪费网络资源

  • 确认丢失和确认迟到

A在设定的超时重传时间内没有收到确认,但这时并无法确定是自己发送的分组出错、丢失,还是B发送的确认丢失。因此A要重传此分组。

确认丢失,假设B又收到了重传的分组M1,则B应丢弃这个分组,并向A发送确认M1,不能认为已经发送过确认就不再发送,
因为A之所以重传M1,就是表示A没有收到M1的确认。

确认迟到,A会收到重复的确认,A只需要丢弃这个重复的确认

流水线传输

发送方可以连续发送多个分组,不必没发完一个就停下来等待对方的确认,这样可以提供信道利用率。

TCP报文段首部格式

TCP是面向字节流的,但TCP传输的数据单元是报文段。TCP报文首部的前20个字节是固定的,后面4n字节是动态增加。

TCP报文段的首部格式

1、源端口目的端口各2个字节。

2、序号4个字节,0 - 2^32 - 1,每个字节都按按顺序编号,保存本报文第一个字节的序号。

3、确认号4个字节,是期望收到对方下一个报文的第一个数据字节的序号。若确认号=N,则表明:到序号N-1为止的所有数据都已正确收到。

4、数据偏移4位,TCP报文的数据起始距离TCP保报文的起始处有多远,是值TCP报文段的首部长度,单位是32位字(4个字节为单位),1111 = 15,15*4=60字节,
这也就是TCP首部的最大长度,可选的长度不超过40字节。

5、保留6位,暂未使用,目前为0

6、 紧急URG(URGent)

URG=1时,字段有效,此报文需紧急传输,不需要按原来的排队顺序,如用户从键盘发送的中断命令(Control+C),
把紧急数据插到本报文的最前面,后面接着普通数据,与紧急指针(Urgent Pointer)配合使用。

7、确认ACK(Ackonwlegment)

ACK=1时,字段有效,TCP规定,在建立连接后的所有传输报文段都必须把ACK置1。

8、推送PSH(Push)

希望在键入一个命令后,立即就能够收到对方的响应,发送方把PSH置1,并立即创建一个报文发送出去;接收方TCP收到PSH=1的报文段,
就尽快交付接收应用进程,不用等到缓存都填满才上向上交付。

9、复位RST(Reset)

表明TCP立即中出现严重差错(如主机奔溃等),必须释放连接,然后再重新建立连接,RST置1还用来拒绝一个非法的报文段或拒绝打开一个连接。

10、同步SYN(Synchronization)

建立连接是用来同步序号,当SYN=1 ACK=0时表明这是一个连接请求报文,若对方同意建立连接则响应的报文 SYN=1 ACK=1

11、终止FIN()finish

用来释放连接,FIN=1 表明此报文段的发送方的数据已经发送完毕,并要求释放连接

12、窗口2字节,0 - 2^16 -1 的整数

窗口指的是发送本报文段的一方的接收窗口(不是自己的发送窗口),告诉对方从本报文段首部中的确认号算起,接收方目前
允许对方发送的数据数量。因为接收方的数据缓存空间时有限的。
窗口字段明确指出了现在允许对方发送的数据量,窗口值是经常动态变化

13、检验和checksum 2字节

检验和字段检验的范围包括首部和数据这两部分,和UDP数据一样,在计算检验和时,要在TCP报文的前面加上12字节的伪首部。
伪首部的数据都是从IP数据报头获取。
伪首部中4个字节保存源IP信息,4个字节目的IP信息,一个字节的保留位置,一个字节保存协议号(6代表TCP,17代表UDP),2个字节保存TCP的真正首部和数据。
根据伪首部的信息通过位运算,得到了一个校验和数据,保存在TCP报文的checksum字段。
接收端接收到TCP报文后,也按照特定算法计算出一个校验和,与checksum保存的校验和比较,如果相同,则完成此报文的接收。如果不相同,则丢弃此报文,让发送端重传

TCP校验和与IP校验和的区别是:TCP和UDP检验和覆盖首部和数据,而IP首部中的检验和只覆盖IP的首部,不覆盖IP数据报中的任何数据。

TCP校验和和UDP校验和的区别是:TCP的检验和是必需的,而UDP的检验和是可选的。

校验和算法:
首先,把伪首部、TCP报头、TCP数据分为16位的字,如果总长度为奇数个字节,则在最后增添一个位都为0的字节。
把TCP报头中的校验和字段置为0(否则就陷入鸡生蛋还是蛋生鸡的问题)。
其次,用反码相加法累加所有的16位字(进位也要累加),最后,对计算结果取反,作为TCP的校验和。

发送方:原码相加,并将高位叠加到低位,取反 ,得到反码求和结果,放入校验和
接收方:将所有原码 相加,高位叠加, 如全为1,则正确

14、紧急指针2个字节,URG=1时有效,指出紧急数据的末尾在报文段中的位置,窗口为0也可以发生紧急数据。

15、选项长度可变,最长40个字节。

最初TCP只规定了一种选项,即最大报文段长度MSS(Maximum Segment Size),MSS是每一个TCP报文段中的数据字段的最大长度。
MSS太小,网络利用率低,太大的话,在IP层就可能被分片,因此在IP层不分片的前提下,尽可能的大。
在建立连接的过程中,双方都把自己能够支持的MSS写入这一字段,以后安装这个数值进行传递,两个方向可以有不同的MSS值。
默认为536字节,536+20=556,主机都应支持这一报文长度。

窗口扩大选项3个字节,窗口长度为2字节,最大为64k,对于带宽很大的网络不够用,其中一个字节为位移值S,位移值允许使用的最大值是14位,
最大窗口为 2^(16+14),窗口扩大选项在建立连接时协商,当不需要时可以发生S=0的选项关闭

时间戳选项10字节,时间戳字段4字节、时间戳回送回答字段4字节,用于计算往返时间RTT和处理TCP序号超过2^32的情况,防止序号绕回。

、时间戳选项、选择确认(SACK)

连续ARQ协议

发送方每收到一个确认,就把发送窗口向前滑动一个分组的位置,接收方可以采用积累确认的方式,对按序到达的最后一个分组进行确认,
这就表示,到这个分组为止的所有分组都已正确收到。

积累确认的优点是容易实现,缺点是不能向发送方反映出接收方已正确收到的所有分组信息。例如,如果发送方发送了5个分组,
中间的第3个分组丢失,这时接收方只能多前2个分组发出确认,发送方无法置顶第3个分组的下落,只好把3-5分组都进行重传。
所以在通信线路质量不好时,连续ARQ协议会带来负面影响。

滑动窗口协议

位于发送窗口的分组都可以连续发送出去,不需要等待对方的确认。

滑动窗口是以字节为单位的,描述一个发生窗口的状态需要3个指针:P1、P2、P3
小于 P1 已经发送并收到确认的
P1 - P2 已发送但未收到
P2 - P3 允许发送但尚未发送的,可用窗口
大于 P3 不允许发送的部分

窗口与缓存空间

缓存是循环使用的,类似圆环结构

发送缓存:发送应用程序传输给发送方TCP准备发送的数据,TCP已发送但尚未收到确认的数据

接收缓存:按序到达的、尚未被接收应用程序读取的数据、未按序到达的数据

A的发送窗口并不一定总是和B的接收窗口一样大,因为网络会滞后

对于不按序到达数据怎么处理,统一丢弃管理简单但是对网络利用不利,一般是临时缓存在接收窗口

TCP要求接收方必须有积累确认的功能,接收方可以在合适的时候发送确认,也可以在自己有数据要发送的时候把确认信息捎带上。
接收方不应过分推迟确认,TCP规定不应超过0.5s,若接收一连串很大的报文段,需每隔一个报文段就发送一个确认。

超时重传时间

采用一种自适应算法,记录一个报文的发出时间,以及收到相应的确认时间,这两个时差就是报文的往返时间RTT。
TCP保留了RTT的一个加权平均往返时间 RTTs

新RTTs = (1-α) * 旧RTTs + α * 新RTT,推荐α=1/8=0.125

超时重传时间RTO应略大于RTTs,建议
RTO = RTTs + 4 * RTTd

RTTd 是RTT的偏差的加权平均值

第一次测量时,RTTd值取RTT的一半
新RTTd = (1-β) * 旧RTTd + β * |RTTs - 新RTT|,推荐β=1/4=0.25

如果重传报文也计算的话,会导致数值偏大,所以报文重传了就不采用此RTT样本,这样得出的加权平均RTTs RTO比较准确。

报文段时延突然增大,出现重传,如果不计算,那么超时重传时间就得不到更新,所以报文每重传一次RTO就增大一些,典型的是取2倍旧RTO

选择确认SACK

若收到的报文段无差错,只是未按序号,中间缺少一些序号的数据,那就可以使用SACK,不重传已经正确接收的数据。
如果要使用SACK,那么在建立TCP连接时就要在TCP首部选项中加上允许SACK选项
目前SACK并不常用,大多数实现还是重传所有未被确认的数据。

TCP的流量控制

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

传输效率

Nagle算法:若发生应用进程把发送数据逐个字节的送到TCP发送缓存,则发送方就把第一个数据字节先发出去,把后面到达的数据缓存起来。
当发送方收到对第一个字节的确认后,再把发送缓存中所有数据组装成一个报文段发送出去,同时继续对随后到达的数据进行缓存。
当到达的数据已达到发送窗口大小的一半或已达到报文段的最大长度时,就立即发送一个报文段。

糊涂窗口综合征:TCP接收缓存已满,而交互式应用进程一次只从接收缓存中读取1个字节,然后向发送方发送确认,并把窗口设为1字节,
接着对方又发来1个字节,整个数据报却要41个字节,这样网络的效率就会很低。

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

TCP的拥塞控制

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

拥塞控制:防止过多的数据注入到网络中,这样可以使网络中的路由器或者链路不致过载。
拥塞控制的前提:网络能够承受现有的网络负荷

拥塞控制是一个全局性过程,涉及到所有主机、路由器、以及与降低网络传输性能有关的所有因素。

在许多情况下,甚至拥塞控制机制本身成为引起网络性能恶化甚至发生死锁的原因。

拥塞控制方法:慢开始(slow start)、拥塞避免(congestion avoidance)、快重传(fast retransmit)、快恢复(fast recovery)

  • 慢开始和拥塞避免

发送方维持一个拥塞窗口(cwnd)的状态变量,拥塞窗口的大小取决于网络的拥塞程度,动态变化。发送方让自己的发送窗口等于拥塞窗口

发送方控制拥塞窗口的原则是:只要网络没有出现拥塞,拥塞窗口就增大一些,只要网络出现拥塞,就把拥塞窗口减小一些。

慢开始:由小到大增大发送窗口,也就是从小到大逐渐增大拥塞窗口数值,通常开始把拥塞窗口设置为一个最大报文段MSS的数值,
在每收到一个对新报文段的确认后,把拥塞窗口增加,每经过一个传输轮次(RTT),拥塞窗口就加倍。

为了防止拥塞窗口增长过大,需要设置一个慢开始门限(ssthresh)

当 cwnd < ssthresh 使用上面的算法

当 cwnd > ssthresh 停止使用慢开始算法而改用拥塞避免算法

拥塞避免算法的思路是让拥塞窗口缓慢增大,每经过一个RTT就把拥塞窗口加1,而不是加倍。

乘法减少 加法增大

  • 快重传和快恢复

如果发送方设置的超时计时器时限已到但是还没收到确认,那么很可能网络出现拥塞,TCP马上把拥塞窗口减小到1,并执行慢算法,
同时慢开始门限减半

快重传要求接收方每收到一个失序的报文段就就立即发出重复确认,目的是使发送方早知道有报文没有到达对方,而不是等待自己发送数据时才进行捎带确认。
当发送方连续收到三个重复确认就应当立即重传对方尚未收到的报文段,而不必继续等待重传计时器到期

拥塞控制

网络层策略:路由器的分组丢弃策略

路由器的队列通常是FIFO,如果队列满了,后续到达的分组都将被丢弃。
不过这样会引起全局同步,也就是丢掉的这些分组,可能会引起许多的TCP连接在同一时间突然进入到慢开始状态。
路由器采用随机早检测RED(Random Early Detection)措施,路由器的队列维持两个参数,既队列长度最小门限、最大门限,
若平均队列长度小于最小门限,则把达到的分组放入队列;若超过最大门限则,丢弃;两者之间则按照某一概率P将新到达的分组丢弃。

最大门限等于最小门限的两倍是合适的


本文不允许转载。
  目录