Transport Layer
问答:
- Responsible for reliable in order traffic delivery
3.1传输层服务
传输层提供了在不同主机上运行的应用进程间的逻辑通信 logical communication between app processes
传输层协议在终端系统 end system 中运行
- 发送端 run side : 将app中的message分断break成一个个部分segment 然后传入网络层
- 接收端 rcv side :将segment重新装配 reassemble成整段的message然后传入应用层
- 不止一个传输协议 transport protocol,还有TCP和UCP
- TCP:可靠的、有序的
- 拥塞控制(congestion)、流控制(flow)、连接建立(connection setup)
- UCP:不可靠的无需的
- 只帮助IP实现了最基本的功能(no-frills extension)
- 两者皆无法实现延迟和带宽的保障(guarantee)
网络层和传输层的对比:
- 网络层:主机之间的逻辑连接(logical communication)
- 传输层:进程之间的逻辑链接
3.2MUX和DEMUX
MUX: multiplexing
- 将多个流数据汇聚到一个流中 (serveral streams of data into a single stream)
- e.g.在同一时间内刷新网页、登上微信、打开邮箱,这三个连接会通过相同的链接传输
- 在发送机处理来自多个socket的数据,并加上传输首标transport header
DEMUX: demultiplexing
-
一个数据流会被分成几个独立的部分(separated out into its individual components)
- e.g. 手机接收到的包会被拆分发送到对应的程序中
- 在接收机用首标信息header info将接收到的数据块传输到正确的socket
-
工作机理:
- 主机接受IP datagrams
- 每一份携带源IP地址和目标IP地址(source IP address, destination IP address)
- 每一份携带一个传输层的segment
- 每一份segment中都含有源及目标的端口号(source, destination port number)
- 主机利用IP地址以及端口号将segment直接放入合适的socket中
- 主机接受IP datagrams
MUX / DEMUX
multiplexing at sender:
- handle data from multiple sockets, add transport header
demultiplexing at receiver
- use header info to deliver received segment to correct socket
Test
How demultiplexing works
host接收到IP datagram后
- 每一个datagram都有source IP,destination IP
- 每一个datagram携带一个transport layer的segment,每一个segment都有一个source port以及destination port
host利用IP address 以及 Port number来将segment放到相应(appropriate)的socket中
数据表样式👇
无连接的DEMUX
Connectionless demultiplexing
主机接收到UCP segment时,检查dest port并根据这个port引导对应的socket
带有相同dest port,但不同源IP地址和port的数据表会被送到dest的同一socket
面向连接的DEMUX
Connection-oriented demux
TCP socket识别4大决定要素(4-tuple)
- 源IP
- 源端口
- 终IP
- 终端口
以这四个要素(缺一不可)将segment导向正确的socket
One port can connect to many processes
服务器主机会同时(simutaneous)支持多个TCP sockets,每一个socket都以自己的 4-tuple而区分
网络服务器对不同的连接客户端有不同的socket(different sockets for each connecting client)
这样,服务器的接口就是被多路分用成了不同的socket
常见的接口号
Test
3.3无连接传输UDP
User Datagram Protocol(RFC 768)
最简单能用的互联网传输协议
UDP的segment可能会
- 丢失
- 传送到App Layer时乱序(out-of-order)
特点——无连接
- UDP发送机和接收机中没有握手(handshaking)就可以发送(can send immediately without asking first)
- 每个UDP的包都是单独处理的(handled independently of others)意味着有的包丢失了损坏了也不对其他的包产生影响
用途
- 流媒体app (streaming multimedia apps)
- DNS
- SNMP
增加可靠性
- 在应用层增加可靠性
- 特定应用的错误纠正(application-specific error recovery)
segment header
8 bytes
格式:
包含四个部分
- source port
- dest port
- length
- checksum
为什么选择UDP
- 没有连接,可以减低延迟
- 简单,在发送机和接收机没有连接状态(no connection state in sender and receiver)
- 更小的header size
- 没有拥塞控制(no congestion control),传输更快
UDP校验
Checksum
目的:检验错误,例如将segment中原本为0却为1的找出来
作用机制:
- 发送端:
- treat segment contents including header fields, as sequence of 16-bit integers
- 使用one’s complement sum addition of segment contents
- puts checksum value into UDP checksum field
- 接收端:
- compute checksum fo received segment
- check if computed checksum equls checksum field value
在发送机端,将数据段内容(包括首部在内→除了负载以外UDP数据段里全部内容)看作16位整数的序列(16进制),然后将这些整数各位相加(16进制下的加法,超过FF(十进制下的255)用补码代替)。发送机将相加和放到UDP校验和中在接收机端,接收到的数据段会重新计算校验和,并进行验证和错误处理
封装和拆装的过程
Encapsulation/decapsulation
Test UDP
3.4 可靠数据传输法则
(b)为传输层是如何实现可靠传输的
不可靠渠道的特点将决定了rdt可靠传输协议的复杂性
机理
rdt : reliable data transfer
udt : unreliable data transfer
有限状态机 FSM
Finite State Machine
一个在状态和状态间过渡中工作的系统,e.g. 地铁闸门
状态机处于某一状态时,若发生了与此状态无关的事件,则状态机状态不变
坑点:题目会给出一些在这个状态下不会有的情况,则当前状态不会改变
可靠数据传输模式
只考虑单一方向的数据传输 undirectional (控制信息仍会双向传输)
用FSM来说明发送机和接收机,下面是模型说明——
全部的rdt都是在Transport Layer的
rdt总结
假设 | 相比于上一代的改进 | 描述 | |
---|---|---|---|
1.0 | 没有bit error;没有丢包 | ||
2.0 | 有bit error | Error detection; Feedback: ACK,NAK | 包ok回ACK,不ok回NAK |
2.1 | ACK/NAK 也corrupted | 对包进行1与0的标号,等待接收ACK/NAK(无标号) | |
2.2 | 接收机不知道上一个ACK/NAK是否被发送机接收到 | 淘汰NAK,对ACK进行标号 | 接收到不同序号的ACK即为NAK |
3.0 | 有bit error,存在丢包 | 发送机设立Timer | 超过Timeout时间后还没有收到相应的ACK则重发 |
rdt 1.0
以两点为d基础:
- 没有bit error
- 没有丢包
用FSM区分发送机和接收机
触发事件和动作👇
rdt 2.0
通道有bits error,因此我们要检测(detect)并修复(recover)这些由传输而带来的错误
解决方案:
- 引入ACK(acknowlegements)和NAK(negative acknowlegement)
- ack:接收机告诉发送机 包ok
- nak:接收机告诉发送机 包不ok,发送机收到NAK后会重发包
触发事件和动作👇
rdt 2.0 有致命错误:ACK/NAK也损坏了
解决方案:发送机对每个要发送的包标序号;若发现ACK/NAK损坏了,发送机重新将现在的包传送,接收机根据序号得知包是否重复,从而弃用或进行传输;此过程需要发送机每发一个包后等待接收机的响应。(stop and wait)
Test
rdt 2.1
触发事件和动作👇
使用序列号 0和1 来判断包是否重复,有且仅有两个序列号。用0/1已足够,因为会等待,只需要对照与上一个包是否重复即可
用序号表示包,重复的包在接收机进行检查,并将不是对应序号的包忽略不管,并要求发送机继续发送且接收机本身状态不变,这样子的话因为重复的包是在接收机已收到并传输上应用层的情况才发生的,所以接收机会一直向发送机发送ACK,直至发送机能收到ACK并不再发送或发送不同的包
发送机:
- 要检查收到是的ACK/NAK是否Corrupt
- 必须记得哪一个包 0/1 是期待收到的
接收机:
- 必须检查收到的包是否重复(duplicate),即指明哪一包 0/1 是期待收到的
问题:
- 接收机不知道自己发送的上一个ACK/NAK是否被发送机接收到
rdt 2.2
淘汰NAK
- 将ACK标上序号,来表示是否收到响应序号的包
- 接收到了不同序号的ACK即为NAK
触发事件和动作👇
rdt 3.0
通道有bits error,而且还会丢包(loss packet)
解决方案:
- 发送机会在发送后设置一个Timeout,等待接收ACK。如果TImeout时间内没有收到ACK,则会重新发送。如果ACK超时到达了,允许发新包且包的序号会让接受机来判断
触发事件和动作👇
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WBLWYA2E-1640403792189)(https://typorastroage.oss-cn-beijing.aliyuncs.com/img/IMG_1941(20210930-110634)].PNG)
对两种情况的图示说明:
① packet loss
② delayed packet
包延迟情况虽然会一直有重复发包的情况,但是不会使数据产生错误
但是这样就会导致rdt3.0效率(utilization)(发送延迟(用来发送数据的时间dtrans)占发送时间(第一个包发送到第二个包发送的时间间隔)的比值)很低,1个包得要花上很多时间浪费在ack传递确认上
RTT往返时间:从发送到收到ack的时间,结束的时间节点也可放在第二个包开始发送的时间点
Test:
Utilization 利用率
RTT: round-trip-time 发过去再回来的时间
L: length of file (bit)
R: transmission rate (bits/s)
D t r a n s D_{trans} Dtrans: Transimission delay
U
s
e
n
d
e
r
U_{sender}
Usender: utilization 发送方忙发送的时间百分比 (end to end delay) * 2
U
s
e
n
d
e
r
=
L
/
R
R
T
T
+
L
/
R
U_{sender} = \frac{L/R}{RTT+L/R}
Usender=RTT+L/RL/R
Pipelined protocols
什么是pipelining
发送端允许多个还没收到ACK的包发送(相反的一次发一个叫:stop and wait)
- sequence number的范围要增大
- sender和receiver都要有buffer
两个pipelined protocols:go-Back-N, selective repeat
pipelining的好处
提高利用率:
直接将L * 3, 每一个发送的文件长度为原来的M倍
例子:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-S2wD65NG-1640403792193)(https://typorastroage.oss-cn-beijing.aliyuncs.com/img/IMG_2372(20211031-135933)].PNG)
Protocol Overview
Go-Back-N GBN
工作机制:
-
发送端:连续发几个Packets,让N个Packets保持 in-flight(No Acks) 的状态,上一层来了的包也要等待发送。对每一个 unacked 的包都有 Timer。有可能会收到重复的ACK,如果收到重复的ACK,说明有Gap。
接收ACK发现与期待接收到的不同后,会从ACK的下一个重新发
-
接收端:只发回序列数最大的包的ACK,如果有 gap, 则发送Gap前面一个的ACK并抛弃掉Gap后面的包
![D3D3564B3EFEAEFBA3FA4902D0B67C57](https://i-blog.csdnimg.cn/blog_migrate/1a79bb0d46f2b120b41c68d8c525bb22.png)
Selective Repeat
![image-20211031142354781](https://i-blog.csdnimg.cn/blog_migrate/80959755e9d50f7a88dd801f320ae332.png)
工作原理:
- 发送端:发送端发N个,如果接收到了上一层来的包,会立即发送。对每一个包都有Timer,timeout后只会重新发送还没有接收到ACK的包。
- 接收端:对接收到的每一个包都发送ACK,需要buffer,以应对out of order的情况,不按顺序到的包也会回ACK并存在Buffer中,等到order对了再发到上一层。当接收到这个窗口中Sequence #最小的一个包后,接收端的window往后移动一位,到下一个窗口。
![1B1C16B68419C03B8433AD2597B070B9](https://i-blog.csdnimg.cn/blog_migrate/fd39db8b235bf7df83952c7238d7f2e9.png)
3.5 connection-oriented transport TCP
Transmission Control Protocol
Segment Structure
TCP Header
20 bytes
TCP报⽂段由⾸部字段和⼀个数据字段(包含⼀块应⽤数据)组成。
-
当TCP发送⼀个大文件时,TCP通常将该文件划分为长度为MSS的若⼲块(最后⼀块除外,它通常小于MSS)。
-
然而,交互式应⽤通常传送⻓度⼩于MSS的数据块。例如,对于像Telnet这样的远程登录应用,其TCP报⽂段的数据字段经常只有⼀个字节。由于TCP的⾸部⼀般是20字节(比UDP⾸部 多12字节),所以Telnet发送的报⽂段也许只有21字节⻓。
-
TCP报文段结构如上图,其中首部包括:
①源端口号和目的端口号:被用于多路复用/分解来自或送到上层应⽤的数据。
②检验和字段(checksum field)
③32bits的序号字段(sequence number field)和32bits的确认号字段(acknowledgement number field):这些字段被TCP发送⽅和接收⽅⽤来实现可靠数据传输服务。
④16bits的接收窗口字段(receive window field):该字段⽤于流量控制(该字段⽤于指示接收⽅愿意接受的字节数量)。
⑤4bits的首部长度字段(header length field):字段指示了以32bits的字段为单位的TCP⾸部的⻓度。由于TCP选项字段的原因,TCP⾸部的⻓度是可变的(通常,选项字段为空,所以TCP⾸部的典型⻓度就是20字节。)
⑥可选与变⻓的选项字段(options field):该字段⽤于发送⽅与接收⽅协商最大报文段长度(MSS)时,或在⾼速⽹络环境下⽤作窗⼝调节因⼦时使⽤。
⑦6bits的标志字段(flag field):ACK⽐特:⽤于指示确认字段中的值是有效的,即该报⽂段包含⼀个对已被成功接收报⽂段的确认。
RST、SYN和FIN⽐特:⽤于连接建⽴和拆除。
PSH⽐特:该⽐特被设置时,就指接收⽅应⽴即将数据交给上层。
URG⽐特:⽤于指示报⽂段⾥存在着被发送端的上层实体置为“紧急”的数据。
⑧紧急数据指针字段(urgent data pointer):紧急数据的最后⼀个字节由16⽐特的紧急数据指针字段指出。当紧急数据存在并给出指向紧急数据尾的指针的时候,TCP必须通知接收端的上层实体。(在实践中,PSH、URG和紧急数据指针并没有使⽤。为了完整性,才提到这些字段。)
TCP seq.number, ACKS
sequence number: 为byte stream中,segments data的第一个byte的位置
acknowledgements (ACK): 期待从另一端收到的下一个byte的序号,而不是当前收到的包的序号
序号和确认好是TCP报文段首部中两个最重要的字段。这两个字段是TCP可靠传输服务的关键部分。
TCP round trip time, timeout
如何设置timeout的值:略大于RTT
- 太小,导致过早结束计数和不必要的重传
- 太大,反应过慢
如何确定RTT?
- 样本RTT,通过报文段传输单位ACK,忽略传输,样本RTT会变化,需要让RTT更平滑
计算RTT,记公式: E s t i m a t e d R T T n e w = ( 1 − α ) ∗ E s t i m a t e d R T T + α ∗ S a m p l e R T T EstimatedRTT_{new} = (1-α)*EstimatedRTT + α * SampleRTT EstimatedRTTnew=(1−α)∗EstimatedRTT+α∗SampleRTT
计算TimeoutInterval,记公式: E s t i m a t e d R T T + 4 ∗ D e v R T T EstimatedRTT + 4* DevRTT EstimatedRTT+4∗DevRTT
Test
![image-20211031151733485](https://i-blog.csdnimg.cn/blog_migrate/e54b6ab17bac4013d8a2f6f6e7f973ab.png)
补充
源端口号/目的端口号: 表示数据从哪个进程来, 到哪个进程去.
32位序号:
4位首部长度: 表示该tcp报头有多少个4字节(32个bit)
6位保留: 顾名思义, 先保留着, 以防万⼀
6位标志位
URG: 标识紧急指针是否有效
ACK: 标识确认序号是否有效
PSH: ⽤来提示接收端应⽤程序⽴刻将数据从tcp缓冲区读⾛
RST: 要求重新建⽴连接. 我们把含有RST标识的报⽂称为复位报⽂段
SYN: 请求建⽴连接. 我们把含有SYN标识的报⽂称为同步报⽂段
FIN: 通知对端, 本端即将关闭. 我们把含有FIN标识的报⽂称为结束报⽂段
16位窗口⼤⼩:
16位检验和: 由发送端填充, 检验形式有CRC校验等. 如果接收端校验不通过, 则认为数据有问
题. 此处的校验和不光包含TCP⾸部, 也包含TCP数据部分.
16位紧急指针: ⽤来标识哪部分数据是紧急数据.
选项和数据暂时忽略
往返时间的估计与超时
TCP如同rdt协议⼀样,它采⽤超时/重传机制来处理报文段的丢失问题。
1)超时间隔长度的设置?显然,超时时间间隔必须大于该连接的往返时间(RTT),即从⼀个报⽂
段发出到它被确认的时间。
2)如何估计往返时间?
3)是否应该为所有未确认的报⽂段各设⼀个定时器?
估计往返时间
报⽂段的样本RTT(表示为SampleRTT)就是从某报⽂段被发出(即交给IP)到对该报⽂段的确认被收到之间的时间量。⼤多数TCP的实现仅在某个时刻做⼀次SampleRTT测量,⽽不是为每个发送的报⽂段测量⼀个SampleRTT.
指数加权移动平均(Exponential Weighted Moving Average,EWMA)。
//推荐的α=0.25 E s t i m a t e d R T T = ( 1 – α ) ∗ E s t i m a t e d R T T + α ∗ S a m p l e R T T EstimatedRTT = (1 – α) * EstimatedRTT + α * SampleRTT EstimatedRTT=(1–α)∗EstimatedRTT+α∗SampleRTT
DevRTT:RTT偏差,测量RTT的变化。
//推荐的β=0.25 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 – β) * DevRTT + β * | SampleRTT – EstimatedRTT | DevRTT=(1–β)∗DevRTT+β∗∣SampleRTT–EstimatedRTT∣
设置和管理重传超时间隔,TimeoutInterval
超时间隔应该⼤于等于EstimatedRTT,否则将造成不必要的重传。但超时时间间隔也不能⽐EstimatedRTT⼤太多,否则当报⽂段丢失时,TCP不能很快地重传该报⽂段,导致数据传输时延⼤。
//⼀旦报⽂段收到并更新EstimatedRTT后,TimeoutInterval计算为:
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
1)TCP通过使⽤肯定确认与定时器来提供可靠数据传输。TCP确认正确接收到的数据,⽽当认 为报⽂段或其确认报⽂丢失或受损后,TCP会重传这些报⽂段。
2)TCP使⽤流⽔线,使得发送⽅在任意时刻都可以有多个已发出但还未确认的报⽂段存在。 ⼀个发送⽅具有的未被确认报⽂段的确切个数是由TCP的流量控制和拥塞控制机制决定的。
Reliable Data Transfer
TCP sender 工作内容
对于Sender来说,关注三个时间节点:
① data received from application
② timeout
③ ack recieved
① data received from application
- 以序列号创建segement,序列号(Seq #)是在字节流中Segment第一个data byte的位置
- 开启计时器
② timeout
- 重发引起Timeout的Seg
- 重启Timer
③ ack recieved
- 更新 acked 的 pkt
- 如果还有 unacked 的pkt,开启Timer
对于IP服务,数据报能够溢出路由器缓存而永远不能到达目的地,数据报也可能乱序到达,⽽且数据报中的bit可能损坏。TCP在IP不可靠的尽力而为服务之上创建⼀种可靠数据传输服务。TCP的可靠数据传输服务确保了⼀个进程从其接收缓存中读取数据流是无损坏、无间隔、非冗余和按序的数据流。
1)TCP从应用程序接收数据,将数据封装在⼀个报文段中,并把该报文段交给IP。(①注意到每⼀个报⽂段都包含⼀个序号,这个序号就是该报文段第⼀个数据字节的字节流编号。②如果定时器还没有为某些其他报文段而运行,则当报⽂段被传给IP时,TCP就启动该定时器。)
2)超时:TCP通过重传引起超时的报文段来响应超时事件。
3)来自接收方的确认报文段(ACK)的到达:TCP将ACK的值y与它的变量SendBase(是最早未被确认的字节序号)进行比较。TCP采用累积确认,所以y确认了字节编号在y之前的所有字节都已经收到。如果y > SendBase,则该ACK是在确认⼀个或多个先前未被确认的报文段。因此,发送方更新它的SendBase变量,如果接收到了ACK 3 那么说明pkt3前面的包都已经发送成功了
补充: 超时间隔 加倍
大多数TCP实现中所做的⼀些修改:TCP重传具有最小序号的还未被确认的报文段。只是每次TCP重传时都会将下⼀次的超时间隔设为先前值的两倍,而不是从EstimatedRTT和DevRTT推算出的值。然而,每当定时器在另两个事件(即收到上层应用数据或收到ACK)中的任意⼀个启动,TimeoutInterval由最近的EstimatedRTT和DevRTT推算得到。
优点:这种修改提供了⼀个形式受限的拥塞控制。定时器过期很有可能是由网络拥塞引起的,即太多的分组到达源与目的地之间路径上⼀台(或多台)路由器的队列中,造成分组丢失或长时间的排队时延。在拥塞的时候,如果源持续重传分组,会使拥塞更加严重。因此,TCP使⽤更好的方法,每个发送⽅的重传都是经过越来越长的时间间隔后进行的。
![image-20211031154354851](https://i-blog.csdnimg.cn/blog_migrate/83ca3f3d45a4f9c98b7b25fa081c52d5.png)
TCP 快速重传
工作原理:如果发送端对一个一样的data接收到了 3 个ACKs,那么重传全部unacked segment中序列号最小的segment
![150EC9EB3A49B301F15EC4192C7A852E](https://i-blog.csdnimg.cn/blog_migrate/07712ae3438b124006596f3ec1a14f44.png)
快速重传
问题:超时触发重传存在的问题是超时周期可能相对较长,当⼀个报文段丢失时,这种长超时 周期迫使发送方延迟重传丢失的分组,因而增加了端到端时延。
解决办法:冗余ACK(duplicate ACK):就是再次确认某个报文段的ACK,而发送方先前已经收到对该报文段的确认。(通过下面理解:发送方通常在超时事件发⽣之前通过注意所谓冗余ACK来较好地检测到丢包情况。)
TCP接收方的ACK生成策略:
因为发送方经常⼀个接⼀个地发送⼤量的报文段,如果⼀个报文段丢失,就很可能引起许多⼀个接⼀个的冗余ACK。如果TCP发送方接收到对相同数据的3个冗余ACK,它把这当做⼀种暗示,说明跟在这个已被确认3次的报文段之后的报文段已经丢失(为何是3个冗余ACK?)。⼀旦受到3个冗余ACK,TCP就执⾏快速重传(fast retransmit),即在该报文段的定时器过期之前重传丢失的报⽂段。
补充:超时重传
即怎样决定超时间隔和如何确定重传的频率。对每个连接, TCP管理4个不同的定时器:
1、重传定时器使用于当希望收到另⼀端的确认。在本章我们将详细讨论这个定时器以及⼀些相关的问题,如拥塞避免。
2、坚持(persist)定时器使窗口大小信息保持不断流动,即使另⼀端关闭了其接收窗⼝。
3、保活(keepalive)定时器可检测到⼀个空闲连接的另⼀端何时崩溃或重启。
4、2MSL定时器测量⼀个连接处于TIME_WAIT状态的时间。
Test
![image-20211031161639552](https://i-blog.csdnimg.cn/blog_migrate/a037f8d755d6580b146b58c6596decca.png)
Flow Control
这个部分讲的是Receiver部分的
- 并不能减少网络拥堵,因为只是在Receiver
Flow Control: receiver控制sender,确保sender不会发的太多太快让receiver的buffer overflow
工作机理:
- 接收端: 通过在接收端发给发送端的segment中的TCP header中包含rwnd部分 advertise 自由buffer 空间
- RcvBuffer 的大小通过 socket option来设置,通常默认值为4096字节
- 操作系统会自动调整RcvBuffer的大小
- 发送端:以接收端的rwnd来限制自己unacked(in-flight)包的数量以确保接收端的Buffer不会overflow
MSS and MTU
MSS (Maximum Segment Size): 最大报文长度,指报文段里应用层数据的最大长度,而不是指包括TCP首部的TCP报文段的最大长度
MTU (Maximum Transmission Unit): 最大传输单元,本地发送主机发送的最大链路层帧长达。TCP可以从缓存中取出并放入报文段中的数据数量受限于MSS,MSS通常由MTU来设置,该MSS要保证一个TCP报文段(当封装在一个IP数据报中)加上TCP/IP首部长度(通常是40字节)将适合单个链路层帧。以太网和PPP链路层协议都具有1500字节的MTU,因此,MSS的典型值是1460字节。
Nagle’s Algorithm
问题所在:
-
应用数据产生非常缓慢的时候会出问题,试想,远程只在用户键入的时候才会产生数据。TCP会在数据到达发送端缓存的时候去发送数据,这也就是说,对于远程连接,每次用户键⼊才会发送⼀个包。这个过程的头部非常巨大(TCP头部➕ IP头部➕ 发送⼀个字节需要的frame header)
-
小包问题:在使用一些协议通讯的时候,比如Telnet,会有一个字节字节的发送的情景,每次发送一个字节的有用数据,就会产生41个字节长的分组,20个字节的IP header和20个字节的TCP Header,这就导致了一个字节的有用信息要浪费掉40个字节的头部信息,这样会造成网络上的拥堵
解决问题:
- Nagle算法是通过减少需要通过网络发送包的数量来提高TCP/IP传输的效率
Nagle’s Algorithm
- 主要避免发送小的数据包,要求TCP连接上最多只有一个未被确认的小分组,在该分组的到达之前不能发送其他的小分组。相反,TCP收集这些少量的小分组,并在确认到来时以一个分组的方式发送出去。
算法步骤:
- TCP发送端发送他收到的第一个数据片,无论多小都发送
- TCP发送端会在发送端缓存里积攒数据直到下列条件之一实现了:
- TCP接收端发送了确认消息
- 积攒的数据达到了最大Segment的尺寸(MSS)
- 重复第二步
注意:有时不能用这种算法,比如说需要快速的交互反应,需要发送小的分组等等
在默认的情况下,Nagle算法是默认开启的,Nagle算法比较适用于发送方发送大批量的小数据,并且接收方作出及时回应的场合,这样可以降低包的传输个数。同时协议也要求提供一个方法来给上层来禁止掉Nagle算法。
当应用不是连续请求+应答模型的时候,而是需要实时的单项的发送数据并及时获取响应,这种case就明显不太适合Nagle算法,明显由Delay的
英文原版PPT如下👇
Silly Window Syndrome
糊涂窗口综合征发生在TCP系统被迫发送非常小的数据时
可能有两种触发的条件:
- Sender产生数据十分的慢
- 与Nagle’s Algorithm面临的问题一样
- Recierver处理数据十分的慢
- 单个的字节或者小的数字会被从满的缓存中移除;重复处理等等
解决方法:Receiver dose not advertise windows that would cause sender to send small amounts of data
展开讲原因:由于发送端和接收端上的处理不⼀致,导致网络上产生很多的⼩包,之前也介绍过避免网络上产生过多小包的措施,比如Nagle算法。在滑动窗口机制下,如果发送端和接收端速率很不⼀致,也会产⽣这种比较犯傻的状态:发送⽅发送的数据,只要⼀个大大的头部,携带数据很少。
对于接收端来讲,如果接收很慢,⼀次接收1个字节或者几个字节,这个时候接收端缓冲区很快就会被填满,然后窗口通告为0字节,这个时候发送端停止发送,应⽤程序收上去1个字节后,发出窗口通告为1字节,发送方收到通告之后,发出1个字节的数据,这样周而复始,传输效率会非常低。
同时如果发送端程序⼀次发送⼀个字节,虽然窗口足够⼤,但是发送仍是⼀个字节⼀个字节的传输,效率很低
Test
![image-20211031214826940](https://i-blog.csdnimg.cn/blog_migrate/dc3fe2ddad46723565471182b3089284.png)
Connection Management
在交换数据之间,Sender/Receiver要进行握手
- 同意建立连接
- 同意连接参数
三次握手 建立连接
第⼀次: SYN
客户端 - - > 服务器 此时服务器知道了客户端要建立连接了
第⼆次: SYN-ACK
客户端 < - - 服务器 此时客户端知道服务器收到连接请求了
第三次: ACK
客户端 - - > 服务器 此时服务器知道客户端收到了自己的回应
到这里,就可以认为客户端与服务器已经建立了连接。
为什么不是两次握手?
主要是为了防止已经失效的连接请求报文突然又传送到了服务器,从而产生错误。如果使用的是两次握手建立连接,假设有这样一种场景,客户端发送的第一个请求连接并且没有丢失,只是因为在网络中滞留的时间太长,由于TCP的客户端迟迟没有收到确认报文,认为服务器没有收到,此时重新向服务器发送这条报文,此后客户端和服务器经过两次握手完成连接,传输数据,然后关闭连接。此时之前滞留的那一次请求连接,因为网络通畅了,到达了服务器,这个报文本该是失效的,但是,两次握手的机制会让客户端和服务器再次建立连接,这将导致不必要的错误和浪费资源。
三次握手的情况下,就算是那一次失效的报文传过来了,服务器接收到了那条失效的报文给客户端回复确认的不保温,客户端也不会再次发出确认。由于服务器接收不到确认,就知道客户端并没有请求连接。
为什么不是四次?
因为三次已经足够了
四次握手 断开连接
第⼀次: FIN
客户端 - - > 服务器 此时服务器知道了客户端要断开连接了
第⼆次: ACK
客户端 < - - 服务器 此时客户端知道服务器确认关闭请求,等待服务器发送FIN,服务器仍然可以发送数据
第三次: FIN
客户端 < - - 服务器 此时服务器发送完待发送的数据了,可以关闭了。发送FIN后服务器便不可再发送数据。
第四次: ACK
客户端 - - > 服务器 此时客户端接收到了服务器的结束请求,接收后会等待一段时间,为两倍的最大Segment lifetime。
![image-20211031221300830](https://i-blog.csdnimg.cn/blog_migrate/369cac37cef12e6337e626416b98ef74.png)
三次握手与四次分手更多知识
三次握手:
TCP连接的建立会显著地增加人们感受到的时延。客户中的TCP会用以下方式与服务器中的TCP建立⼀条TCP连接:
刚开始, 客户端和服务器都处于 CLOSE 状态. 此时, 客户端向服务器主动发出连接请求, 服务器被动接受连接请求.
TCP服务器进程先创建传输控制块TCB, 时刻准备接受客户端进程的连接请求, 此时服务器就进入了 LISTEN(监听)状态。TCP客户端进程也是先创建传输控制块TCB, 然后向服务器发出连接请求报文
SYN报文段
第⼀步:客户端TCP首先向服务器端的TCP发送⼀个特殊的TCP报文段(TCP SYN报文段:该报文段不包含应用层数据,但在报文段的首部中的⼀个标志位SYN被置为1
。另外,客户会随机选择⼀个初始序号(client_isn),并将次编号放置于该起始的SYN报文段的序号字段中。该报文段会被封装在⼀个IP数据报中,并发送给服务器。此时,TCP客户端进程进入了SYN-SENT(同步已发送状态)状态。
SYN-ACK报文段
第二步:⼀旦包含SYN报文段的IP数据报到达服务器主机(假定它的确达到了),服务器会从该数据报中提取出TCP SYN报文段,为TCP连接分配TCP缓存和变量,并向该客户TCP发送允许连接的报文段(分配的这些缓存和变量,使得TCP易于受到SYN洪泛的拒绝服务攻击),这个允许连接的报文段(SYNACK报文段:该首部有3个重要信息①SYN置为1;②确认号字段被置为client_isn+1;③服务器选择自己的初始序号server_isn,并将其放在TCP报文段首部的序号字段中。)不包含应用层数据。此时, TCP服务器进程进⼊了SYN-RCVD(同步收到)状态。
ACK报文段
第三步:在收到SYNACK报文段后,客户也要给该连接分配缓存和变量。客户主机则向服务器发送另外⼀个报文段(ACK);这最后⼀个报文段对服务器的允许连接的报文段进⾏了确认(首部中:①确认字段为server_isn+1;②序号字段为client_isn+1;③SYN-bit置为0)。该三次握手的第三个阶段可以在报文段负载中携带客户到服务器的数据。
在以后的每⼀个报文段中,SYN比特都被置为0;这种连接创建过程被称为3次握手(three-wayhandshake)。此时,TCP连接建立,客户端进入ESTABLISHED(已建立连接)状态。当服务器收到客户端的确认后也进入ESTABLISHED状态,此后双方就可以开始通信了。
四次分手:
参与⼀条TCP连接的两个进程中的任意⼀个都能终止该连接。当连接结束后,主机中的“资源(缓存和变量)”将被释放。
假设某客户打算关闭连接:未关闭之前,初始状态都是 ESTAB
- 客户应用进程发送⼀个关闭连接命令:客户TCP向服务器进程发送⼀个特许TCP报⽂段(首部的标志位FIN置为1,并选择序号x)。发送后状态变为FIN_WAIT状态,不能再发送数据(但可以接收数据)
- 当服务器接收到该报文段后,就向发送方发送⼀个确认报文段。确认位序号为x+1,确认位ACK置
1
,仍然可以发送数据,进⼊ CLOSE_WAIT状态。客户端收到后,等待服务器关闭。 - 服务器发送它自己的终止报文段,其FIN bit置为1,附带序号y.并进入LAST_ACK状态,不可以再发送数据。客户端收到以后进入TIMED_WAIT状态。
- 客户端对这个服务器的终止报文段进行确认,确认位序号为y+1。(此时,两个主机用于连接的所有资源都被释放了。)
等待 2*MSL 时间
为什么要等待?
MSL (Maximum Segment Lifetime),TCP允许不同的实现可以设置不同的MSL的值。
- 保证客户端发送的最后一个ACK报文能够到达服务器,因为这个ACK报文可能丢失,再再服务器的角度看,我已经发送了FIN报文请求断开了,客户端还没有给我回应,应该是我发送的请求断开报文它没有收到,于是服务器又会重新发送一个,而客户端就能再这个2MSL时间段内收到这个重传的报文,接着给出回应报文,并且会重启2MSL计时器。
- 防止类似于 “三次握手” 中提及的 “已经失效的连接请求报文段” 出现在本连接中。客户端发送完最后一个确认报文后,在这个2MSL时间中,就可以使本连接持续的时间内产生所有报文段都从网络中消失。这样新的连接中就不会出现旧连接的请求报文。
3次握手 有限状态机图
建立连接:
-
客户TCP开始处于CLOSED状态
客户应用程序发起了一个新的连接,则客户TCP向服务器中的TCP发送一个SYN报文段。
-
发送过SYN报文段后,客户TCP进入SYN_SENT状态。接着,等待来自服务器TCP的对客户所发报文段进行确认且SYN bit被设置为1的一个报文段(SYN-ACK报文段)。
-
收到SYN-ACK报文段之后,客户机会进入ESTABLISHED状态当处在ESTABLISHED状态时,TCP客户就能发送和接收包含有效载荷数据(即应用层产生的数据)的TCP报文段了
断开连接:
- 假设客户要决定关闭该连接,这引起客户TCP发送一个带有FIN bit被设置成1的TCP的报文段,进入FIN_WAIT_1状态。客户等待来自服务器的带有确认的TCP报文段
- 在收到服务器的确认报文段后,客户端进入FIN_WAIT_2状态,等待来自服务器的FIN bit设置为1的另一个报文段
- 收到服务器的FIN报文段后,客户TCP对服务器发送ACK进行确认,并进入TIME_WAIT状态
假设ACK丢失,TIME_WAIT状态使TCP客户重传最后的确认报文。在TIME_WAIT状态追踪小号的时间与具体实现有关,典型值使30s,1min,2min。经过等待后,连接就正式关闭了,客户端所有的资源包括端口将被释放
Test
![image-20211031223145367](https://i-blog.csdnimg.cn/blog_migrate/885abc7683a151dc0b2f620146be9bc5.png)
More
为什么建立连接是三次握⼿,关闭连接确是四次挥手呢?
建立连接的时候, 服务器在LISTEN状态下,收到建⽴连接请求的SYN报文后,把ACK和SYN放在⼀个报⽂里发送给客户端。
而关闭连接时,服务器收到对方的FIN报文时,仅仅表示对方不再发送数据了但是还能接收数据,而自己也未必全部数据都发送给对方了,所以己方可以立即关闭,也可以发送⼀些数据给对方后,再发送FIN报⽂给对方来表示同意现在关闭连接,因此,己方ACK和FIN⼀般都会分开发送,从而导致多了⼀次。
如果已经建立了连接, 但是客户端突发故障了怎么办?
TCP设有⼀个保活计时器,显然,客户端如果出现故障,服务器不能⼀直等下去,白白浪费资源。服务器每收到⼀次客户端的请求后都会重新复位这个计时器,时间通常是设置为2小时,若两⼩时还没有收到客户端的任何数据,服务器就会发送⼀个探测报文段,以后每隔75分钟发送⼀次。若⼀连发送10个探测报⽂仍然没反应,服务器就认为客户端出了故障,接着就关闭连接。
3.6 Principles of congestion control
什么是Congestion
一下发太多,发太快到network上
跟flow control不同:flow control是在Receiver段的,Congest Control是防止对于network来说发得太快
Congest 后果
lost packets (buffer overflow at routers)
long delays (queueing in router buffers)
造成Congestion的原因
太多Traffic 进入到 Router中间,会造成delay,已经减少Throughput
有效吞吐量 goodput:
- 到达应用层的数据量/传输数据总量
- 与吞吐量的区别 – 丢失、重传和损坏
在某段时间,若对网络中某⼀资源的需求超过了该资源所能提供的可用部分,网络性能就要变坏,这种情况就叫做网络拥塞。
在计算机网络中数位链路容量(即带宽)、交换结点中的缓存和处理机等,都是网络的资源。若出现拥塞而不进行控制,整个网络的吞吐量将随输入负荷的增大而下降。
3.7 TCP Congestion Control
Additive Increase, Multiplicative Decrease (AIMD)
发送端提高传输速率,尽可能的用到全部的可用带宽,直到有loss出现
- 设置cwnd - congestion window to initial value
- additive increase: 每个RTT内提高 cwnd 1个 MSS,直到loss出现
- multiplicative decrease: 出现loss后,直接将 cwnd 减半
cwnd及TCP发送速率
TCP 四种Congestion控制算法
- 慢开始
- 拥塞控制
- 快重传
- 快恢复
TCP Slow Start
当连接开始时,以指数方式增加速率,直到第一次Loss 发生
- 初始: c w n d = 1 ∗ M S S cwnd = 1*MSS cwnd=1∗MSS
- c w n d cwnd cwnd 变为原来的两倍
- 在每一次收到ACK后执行
当连接刚建立或超时时,进入慢启动阶段
当新建TCP连接时,拥塞窗口(cwnd)被初始化为⼀个数据包大小。源端按cwnd大小发送数据,每收到⼀个ACK确认,就增加⼀个数据包发送量,这样慢启动阶段cwnd随RTT呈指数级增长。
慢启动采用逐渐增大cwnd的方法,可以防止TCP在启动⼀个连接时向网络发送过多的数据包而造成不必要的数据丢失和网络拥塞,并且它还能够避免采用单纯的AIMD算法造成的吞吐量增加过慢的问题。
为了防止cwnd的无限制增长引起网络拥塞,引入⼀个状态变量:慢启动阈值ssthresh。
当cwnd<ssthresh时,使用上述的慢启动算法,cwnd随RTT呈指数增长。
当cwnd>ssthresh时,使用拥塞避免算法,减缓cwnd的增长速度。
TCP 特点
Test
区分 rwnd
和 cwnd
![image-20211031230242319](https://i-blog.csdnimg.cn/blog_migrate/bf8ec3da21269689f04a923857979a0e.png)
检测丢包的不同方法及回应
检测方法:
- 超时timeout:
- cwnd 设置为 1 MSS (Tahoe)
- 随后进入指数增长,超过阈值后线性增长
- 收到三个相同的ACK
- 表明网络连接还在工作(TCP Reno)会将cwnd缩至原先的一半而后线性增加
TCP Tahow总将 cwnd 设置成 1,无论是timeout还是收到3个重复的acks
超时肯定是Tahoe,收到三个重复得acks有可能Reno也有可能Tahoe
![F8E749248C907721FE71EA34C4864BBE](https://i-blog.csdnimg.cn/blog_migrate/17a18c58f3d845ac32642ed4c0a839f9.png)
可以看到TCP cwnd 在增长过它上一次超时的一般(ssthresh)后,就会从指数增长转化为线性增长 -> 进入 AIMD
TCP throughput
吞吐量
拥塞控制使得window size时间图像为锯齿图,使得在线性增长过程中,TCP吞吐量(TCP throughout)的平均值可求
- 假设忽略slow start,以及data永远能送达
W: window size (in bytes) 在有loss的时候的
- 平均窗大小 是 3 4 W \frac{3}{4}W 43W
- 平均吞吐量: T C P t h r u p u t = 3 W 4 R T T TCPthruput = \frac{3W}{4RTT} TCPthruput=4RTT3W
TCP Fairness
如果 K 个 TCP 连接共享了相同的带宽为R 的瓶颈链路
=> 每⼀个的平均速度应该为 R / K R/K R/K
与UDP比较公平性
多媒体应用通常不适用TCP,因为不希望拥塞控制抑制其传输速率
UDP不会被拥塞控制所阻碍,也就是说音频/视频这些需要有即时速率发送的可以忍受包丢失的就是用UDP
平行的TCP连接
TCP就用于可以在两个主机间打开多个平行连接的连接(网络浏览器)