一、TCP概述
TCP连接
- 点对点(一个发送方,一个接收方)
- 可靠的,按序的字节流
- 流水线机制(拥塞控制机制和流量控制机制 窗口尺寸)
- 发送方,接收方的缓存
- 全双工特性:同一连接中可以传送双向字节流。应用层数据从进程B流向进程A的同时也从进程A流向进程B。
- 面向连接:
- 发送数据前必须建立连接(握手)。且是三次握手。
- 前两次不包含应用层数据 (客户首先发送一个TCP特殊报文段,服务器用另一个特殊的TCP报文段作为相应,客户再用第三个特殊报文段作为相应)
- 连接状态只在连接的两端维护,在沿途结点中并不更改状态
- 在这两台主机之间的网络元素(路由器,交换机和中继器)没有为该连接分配任何缓存和变量
- 包括两个主机间的缓存,连接状态变量和socket等信息
- 发送数据前必须建立连接(握手)。且是三次握手。
- MTU:最大链路层帧长度(最大传输单元)。
- MSS:最大报文段长度,受限于MTU,指的是报文段中应用层数据的最大长度,而不包含首部;
TCP报文段结构
-
当TCP发送一个大文件时,该文件被划分为若干长度为MSS的若干块。但交互式应用通常传送长度小于MSS的数据块
-
包括源端口号和目的端口号(多路复用。分解)
-
检验和字段(checksum)
-
32bits的序号字段(seq number),32bit的确认号字段(ackowledge number)。用于发送方和接收方实现可靠数据传输。
-
16bits的接收窗口(recieve window):用于流量控制
-
4bits的首部长度字段。(header length field)单位是32比特的字。TCP首部典型长度为20字节
-
选项字段(option field):发送方和接收方协商最大报文段长度
-
6bits标志字段(UAPRSF)
- ACK比特:包括一个对已经被成功接收报文段的确认
- RST,SYN,FIN用于连接的建立和拆除。
- CWR,ECE
- PRH比特:指示接收方立刻将数据交付给上层
- URG比特:知识报文段里存在被发送端的上层实体置为紧急的数据。紧急数据的最后一个字节由16bits的紧急数据指针字段(urg data pnter)指出。
-
报文段序号(seqnum for a segment)是该报文段首字节的字节流编号。而不是报文段的编号。如图所示:
-
确认号:期望收到的下一个字节的序列号。累计确认机制,该号之前所有都已成功接收(注意不包括该号)
案例学习
-
假设客户和服务器的起始序号分别为42和79
-
客户端用户输入字符’C’,发送的第一个报文段序号为42,服务器发送的第一个报文段序号为79;ACK确认号就是等待的下一个字节的序号。
-
第二个报文段,服务器将序号为79的报文段发给客户。在ACK中填入43告诉客户已经成功收到42字节及其之前的所有字节,现在期望43字节的出现。
-
第三个报文段用于确认已经从服务器收到的数据。报文段中没有数据但是仍然有序号,这是因为TCP存在序号字段报文段中需要填入某个序号
二、TCP可靠数据传输
超时-重传机制解决报文段丢失问题。
- 超时间隔必须大于该连接的往返时间(RTT)
估计往返时间
- 为一个已经发送但是目前未被确认的报文段估计SAMPLE_RTT,从而产生接近每个RTT的新RTT;绝不为已经重传的报文段计算sample_rtt
- 维护一个RTT的均值,由如下式子给出
E s t i m a t e d R T T = 0.875 ∗ E s t i m a t e d R T T + 0.125 ∗ S a m p l e R T T EstimatedRTT = 0.875*EstimatedRTT + 0.125*SampleRTT EstimatedRTT=0.875∗EstimatedRTT+0.125∗SampleRTT
称为指数移动加权平均 - 测量RTT的变化。定义RTT的偏差DevRTT,估算SampleRTT偏离ESTIMATEDRTT的程度 D e v R T T = ( 1 − β ) ∗ D e v R T T + β ∣ S a m p l e R T T − E s t i m a t e d R T T ∣ DevRTT = (1 - \beta)*DevRTT + \beta |SampleRTT - EstimatedRTT| DevRTT=(1−β)∗DevRTT+β∣SampleRTT−EstimatedRTT∣即差值的指数加权平均.why:当变化较大时给出较大的安全边界
- 重传间隔时间由下面的式子给出 T i m e o u t I n t e r v a l = E s t i m a t e d R T T + 4 ∗ D e v R T T TimeoutInterval = EstimatedRTT + 4*DevRTT TimeoutInterval=EstimatedRTT+4∗DevRTT.当出现超时时即加倍。更新estimatedrtt后再次计算。
TCP发送方事件
从上层应用收到数据
- 每个报文段包含一个序号,(即第一个字节流的编号)接收数据并封装在报文段
- 启动定时器(当定时器还没有为其他报文段而运行的时候)。与最早未被确认的报文段相互关联
- 设置超时时间
超时
- 重新发送引起超时的报文段来相应超时事件。重启定时器。(attention:只传送那一个报文段)
收到ACK(包含有效ACK字段的报文段)
- 将ACK的值与他的sendbase相比较。 注意上周学的滑动窗口,sendbase时最早未被确认的字节的序号。
- 于是sendbase-1时接收方已经按需接收到的数据的最后一个字节的序号。
- 设ACK的值为
y
y
y:
- 于是 y y y确认了字节编号在y之前的所有字节都已经被收到,不包括y本身的
- 因此当y > sendbase时,需要令sendbase = y
- 如果当前存在未被确认的报文段还需要重启定时器
TCP接收方事件
超时间间隔加倍
- TCP重传具有最小序号的还未确认的报文段,只是每次TCP重传时都会将下一次的超时间隔设置为先前值的两倍。而不是从上述公式中推算出来的值
- 但是,在收到上层应用的数据和收到ACK中的任意一个启动时,由上述公式推算得到。
- (拥塞控制的因素)
快速重传
使用冗余ACK检测丢包情况:即再次确认某个报文段的ACK,发送方先前已经收到了对于该报文段的确认。
- 下表给出了接受方ACK的生成策略。
- 当TCP接收方收到一个其序号大于下一个所期望的,按顺序的报文段,证明报文段有丢失。于是TCP接收方确认已经接收到的最后一个按序到达的字节(不是那个收到的不期望的序列号的数据报)。
快速重传:如果sender收到对同一数据的3个ACK,则假定该数据之后
的段已经丢失。在定时器过期之前进行 快速重传。算法如图所示:
- 当TCP接收方收到一个其序号大于下一个所期望的,按顺序的报文段,证明报文段有丢失。于是TCP接收方确认已经接收到的最后一个按序到达的字节(不是那个收到的不期望的序列号的数据报)。
三、流量控制
- 也许不是数据已到达就读取数据。如果接收方读取较慢,发送方发送较快则很容易使得该连接的接收缓存溢出
- 需要使得发送方发送速率和接收方的接收速率相匹配。
- 与拥塞控制区分(后者-IP的网络拥塞)
假设TCP接收方丢弃失序的报文段。
- TCP通过让发送方维护一个接收窗口。指示接收方还有多少可用的缓存空间。
- 全双工:连接两端的发送方各自维护一个接收窗口
-
设主机A通过一条TCP连接向主机B发送一个大文件。主机B用REVBUFFER作为缓存。应用进程不断从中读取数据。
-
定义变量:
- LastByteRead:主机B上的应用进程从缓存中读出的数据流的最后一个字节的编号
- LastByteRcvd:从网络中到达的并且已经放入主机B接收缓存中的数据流的最后一个字节的编号。
于是,buffer中可用空间:
且不允许缓存溢出,有以下的式子成立:
L a s t B y t e R c v d − L a s t B y t e R e a d ≤ R c v B u f f e r LastByteRcvd - LastByteRead \leq RcvBuffer LastByteRcvd−LastByteRead≤RcvBuffer
-
接收方通过在Segment 的头部字段将RcvWindow 告诉Sender
-
Sender限制自己已经发送的但还未收到ACK的数据不超过接收方的空闲
RcvWindow尺寸- 主机A跟踪两个变量Lastbytesent和LastbyteAcked。
- 在整个连接的生命周期里保证 L a s t b y t e s e n t − L a s t b y t e A c k e d ≤ r e c v w i n d o w r Lastbytesent - LastbyteAcked \leq recvwindowr Lastbytesent−LastbyteAcked≤recvwindowr
-
Receiver告知Sender RcvWindow=0,会出现什么情况(假设此时主机B没有任何数据要发送给主机A)?:TCP并不向主机A发送带有recvbuffer新值得报文段。
- 主机A不可能指导主机B得接收缓存已经具有了全新得空间
- 于是规范要求当B得接收窗口为0时,A还要发送一个1B得报文得到接收方得确认(回复报文中含有非0的值)
四、连接管理
建立TCP连接
- 客户端的TCP向服务器端的TCP发送一个特殊的TCP报文段
- 不包含应用层数据
- SYN比特为1
- 随机选择一个初始序号,放置于该报文段的序号字段
- 服务器提取出SYN报文段,为该TCP分配缓存和变量。并向客户发送允许连接的报文段
- 不包含应用层数据
- SYN比特置为1
- 确认序号为上述初始序号+1
- 服务器选择自身的初始序号,放在该报文的序号首部字段中
- 称为SYNACK报文段
- 客户端收到SYNACK报文段
- 给该连接分配缓存和变量
- 发送另外一个报文段,对服务器的的SYNACK进行确认
- SYN为0,且今后的每一个报文段都被设置为0
- 可以携带应用层数据
- 攀岩者和保护者的关系(三次握手)
拆除TCP连接
客户发起关闭连接命令
- 客户应用进程发送一个关闭连接命令。引起向服务器发送一个特殊的TCP报文段。
- 首部中的FIN比特被设置为1
- 服务器收到报文段后,就向发送方回送一个确认报文段ACK
- 服务器发送自己的终止报文段
- ACK比特被设置为1
- 客户端对这个服务器的终止进行确认
客户的生命周期
- 注意TIMEWAIT状态:假定发送的ACK丢失,该状态使得TCP重传最后的确认报文。
服务器生命周期
五、拥塞控制原理
- 太多发送主机发送了太多数据或者发送速度太快,以至于网络无法处理
表现为分组丢失(路由器缓存溢出)和分组延迟过大(在路由器中缓存排队)
两个发送方+一台无穷大缓存的路由器
- 主机A和主机B的发送速率都是
λ
i
n
\lambda _{in}
λin字节每秒。在一段容量为R的共享式链路上传输。路由器具有无穷大的缓存。
- 该图描绘了接收方每秒接收的字节数与该连接发送速率之间的函数关系;
- 当发送速率在0-R/2时接收方的吞吐量=发送方的发送速率。
- 当发送速率超过R/2时由于两条连接之间的共享链路容量限制接收方接收速率不能超过R/2
- 当发送速率超过R/2时,路由器中平均排队的分组数就会无限增长
- 导致源于目的地之间的平均时延变为无穷大
- 从时延的角度看,这不是一个理想状态
- 当分组到达速率接近链路容量时,分组经历着巨大的排队延迟
两个发送方+一台具有有限缓存的路由器
- 路由器的缓存容量是有限的
- 即分组到达一个已经满了的缓存时会被丢弃
- 如果一个包含有运输层报文段的分组在路由器中被丢弃,那么它终将被重传。
- 分组重传意味着有了两个“”发送速率“:
- λ i n \lambda_{in} λin字节每秒表示应用程序将初始数据发送到套接字中的速率
- λ i n ’ \lambda_{in}^’ λin’表示运输层向网络中发送报文段的速率(初始数据和重传数据)。称为网络的供给载荷
- 如果主机A能够以某种方式确定路由器中的缓存是否空闲(仅当缓存空闲时才传一个分组):
- 不会丢包
- λ i n \lambda_{in} λin和 λ i n ’ \lambda_{in}^’ λin’相等
- 连接的吞吐量就等于 λ i n \lambda_{in} λin
- 发送的每个分组都能够被接收到
- 发送方仅当在确定了一个分组丢失了后才重传。
- 考虑供给载荷
λ
i
n
’
\lambda_{in}^’
λin’等于R/2的情形。
- 在所发送的的0.5R单位数据中,0.333R/s是初始数据,0.166R/s是重传数据。(发送方必须执行重传以步长因为缓存溢出而丢失的分组)
- 发送方提前发生超时并重传在队列中已经被推迟的分组。
- 接收方只需要一个这样的分组。重传的分组被丢弃。
- 于是转发重传的初始副本是做无用功。而路由器本可以利用链路的传输能力取发送另一个没有必要的分组。
- 下图给出当每个分组被路由器平均转发2次的变化情况。
4个发送方+具有有限缓存的多台路由器+多跳路径
- 4台主机发送分组,每台都通过交叠的两跳路径传输
- 假设采用超时-重传机制。主机都有相同的
λ
i
n
\lambda_{in}
λin,所有路由器的链路容量都是R b/s
- 对于极小的 λ i n \lambda_{in} λin值,路由器的缓存溢出很少见。吞吐量大致接近供给载荷。对于较小的 λ i n \lambda_{in} λin增大会导致 λ o u t \lambda_{out} λout的增大。
- 当
λ
i
n
\lambda_{in}
λin很大(
λ
i
n
’
\lambda_{in}^’
λin’)的情况下:考虑路由器R2;
- 不管其大小,经路由器R1转发到达R2的到达速率至多是R
- 在R2上B-D的流量到达速率可能会比A-C的流量到达速率大得多
- A-C流量与B-D流量在R2上必须为有限缓存空间而竞争,所以当来自B-D连接的供给载荷增大时,A-C连接上通过R2(由于缓存溢出而丢失)的流量会越来越小。极限情况下,R2的空闲缓存会被B-D连接的分组占满。导致A-C连接在R2上的吞吐量趋近于0如图所示:
- 当分组被drop时,任何用于该分组的“上游”传输能力全都被浪费掉
- 第一跳路由器的容量用于传输不同的分组可能更有益处
- 第一跳路由器的容量用于传输不同的分组可能更有益处
六、两种主要的拥塞控制方法
分类依据:网络是否为运输层拥塞控制提供了显式的帮助
- 端到端拥塞控制(无):
- 通过对网络行为的观察来推断
- 网络辅助的拥塞控制(有):
- 路由器向发送方显式地反馈网络拥塞信息
- 实例:ATM可用比特率拥塞控制。
- 显式的通知发送方它(路由器)能在输出链路上支持的最大主机发送速率。
- 网络路由器告知发送方”我阻塞了“
- 路由器通过标记发送方给接收方的信息,委托接收方给发送方发送(至少一个完整的往返时间)
七、TCP拥塞控制
- 让每一个发送方根据所感知到的网络拥塞程度来限制发送速率
- 发送方感知没什么拥塞,增加发送速率
- 发送方感知该路经有阻塞,降低发送速率
TCP发送方是如何限制向其连接发送流量的
-
运行在发送方的控制机制跟踪一个额外的变量,拥塞窗口congestion window
-
于是发送方未被确认的数据量满足下列式子(第二个式子已经在上部分给出)
L a s t B y t e S e n t − L a s t B y t e A c k e d ≤ m i n { c o n g w i n , r e c v w i n } LastByteSent - LastByteAcked \leq min\{congwin,recvwin\} LastByteSent−LastByteAcked≤min{congwin,recvwin}
后面的分析假设TCP接收缓存足够大,以忽略接收窗口的限制。 -
上面的式子约束了发送方未被确认的数据量。
- 粗略地说,在每个RTT的起始点,限制条件允许发送方向该连接发送congwin个字节的数据。在该RTT阶数是发送方接收对数据的确认报文
- 因此congwin动态调整就可以改变向连接放的发送速率
TCP发送方是如何感知在他与目的地之间的路径上出现了拥塞的
TCP发送方的丢包事件:
- 出现超时
- 收到来自接收方的三个冗余的ACK
没有拥塞的情况
- 收到对于以前未确认报文段的确认
- 将这些确认作为一切正常的指示
- 如果确认以相对较慢的速度到达,则拥塞窗口以相对较慢的速率增加
- 否则以相对较快的速率增加。(自计时)
控制发送速率的机制的指导原则
- 一个丢失的报文段意味着拥塞。
- 一个超时事件或四个确认(一个初始ACK和其后的三个冗余ACK)被解释为跟随该四个ACK的报文段的丢包事件的一种隐含暗示
- 应当减小拥塞窗口长度,减小发送速率
- 一个确认报文段意味着发送正常:对当前未确认的报文段的确认到达时,能够增加发送方的速率。
- 带宽探测:增加其速率以相应到达的ACK除非出现丢包事件此时才减小传输速率。
TCP拥塞控制算法
一般原则AIMD:加性增,乘性减!
慢启动
- 当一条TCP连接开始时,congwin的值通常置为一个MSS的较小值。
- 初始发送速率为MSS/RTT
- congwin以1个MSS开始并且每当传输的报文段首次被确认就增加一个MSS。
慢启动的例子:
- TCP向网络发送第一个报文段并等待一个确认
- 当该确认到达时,TCP发送方拥塞窗口增加一个MSS。发送出两个最大长度的报文段
- 这两个报文段被确认,则发送方对每个确认的报文段将拥塞窗口增加一个MSS。使得拥塞窗口变为4MSS.
- 每过1个RTT,发送速率就翻一倍
- 指数增长的形式
拥塞避免
- 进入该状态congwin的值大约是上次遇到拥塞时值的一半
- 不能每过一个RTT将cwnd的值翻倍
- 而是每个RTT只将cwnd的值增加一个MSS
- 一种通用的方法时对于TCP发送方无论何时到达一个新的确认就将congwin增加MSS。例如,如果MSS时1460字节并且congwin时14600字节,则在一个RTT发送10个报文段。每个到达ACK(假设每个报文段一个ACK)增加1/10个MSS。
何时结束指数增长为拥塞避免模式 + LOSS event的处理
-
使用变量threhold,当超过threhold时切换为线性增长(拥塞避免)
-
对于每种loss event,冗余ACK或超时事件发生时(统称为LOSS事件),threhold被设置为该事件前congwin的一半
-
更细致的,对于每种loss事件处理方式如下:
- 如果存在一个由超时指示的丢包事件
- 将congwin设置为1并重新启动慢启动过程(指数增长)
- 将状态变量threhold设置为该种事件前congwin的一半
- 当congwin的值等于threhold时,结束慢启动并且转移到拥塞避免模式。(线性增长)
- 如果检测到3个冗余ACK:
- threhold被设置为该事件前congwin的一半
- congwin切到一半的位置(即threhold改变后的位置)
- 然后进入线性增长模式(TCP SERIES2 RENO)
- 如果存在一个由超时指示的丢包事件
Summary of the algorithm
- 当 CongWin 低于阈值时,发送方处于慢启动阶段,窗口
呈指数增长。 - 当 CongWin 高于 Threshold 时,发送方处于拥塞避免状态阶段,窗口线性增长。
- 当三重重复 ACK 发生时,阈值设置为 CongWin/2 和CongWin 设置为阈值。
- 当超时发生时,阈值设置为 CongWin/2,CongWin 设置为 1 MSS。
八、性能分析
吞吐率
给定拥塞窗口大小和RTT,TCP的平均吞吐率是多少?
-
忽略慢启动
-
假定超时时congwin的大小为W(以MSS为单位的),吞吐率为W/RTT。发生超时后,(注意忽略了慢启动),变为W/2RTT
- 所以平均吞吐率为0.75W/RTT
举例:每个Segment有1500个byte, RTT是100ms,希望获得
10Gbps的吞吐率
throughput = WMSS8/RTT, 则 : W=throughputRTT/(MSS8)
则:throughput=10Gbps, 则W=83,333
吞吐率和丢包率的关系
- 设L为丢包率,W和上述定义一致
- CongWin从W/2增加至W时出现第一个丢包,那么一共发送的分组数为
W / 2 + ( W / 2 + 1 ) + ( W / 2 + 2 ) + ⋯ + W = 3 W 2 / 8 + 3 W / 4 W/2 + (W/2+1)+(W/2+2) + \cdots +W = 3W^2/8 + 3W/4 W/2+(W/2+1)+(W/2+2)+⋯+W=3W2/8+3W/4 - throuphput为平均吞吐量,带入上面的式子可以得到:
公平性的讨论
- 如果K个TCP Session共享相同的瓶颈带宽R,那么每个Session的平均速率为R/K
- TCP是公平的:
- 最后收敛到带宽相同的线上
公平性与UDP
- 多媒体应用通常不使用TCP,以免被拥塞控制机制限制速率
- 使用UDP:以恒定速率发送,能够容忍丢失
- 而TCP会降低速率
- 所以UDP源可能压制TCP流量。