Transport Layer
连接复用
UDP: User Datagram Protocol
UDP只用一个二元组来区分链接,一个UDP的头只包括 dest ip
和 dest port
两个信息而在对上面的应用层提供服务的时候,拥有同样的 ip
和 port
的数据块会被送到同一个 Socket
里面
TCP
TCP使用一个四元组来区分链接,即(source ip,source port, dest ip,dest port)
这个四元组来区分,只有当这四元组完全相同的时候才会送到同一个 Socket
里面去。
UDP
优点和缺点
优点
- 不需要握手建立连接
- 简单,发送端和接收端没有状态切换
- 报文头小
缺点
- 只是尽最大努力传输,所以报文可能会丢失、乱序
- 没有拥塞控制,可能会严重超时
UDP报文的样式
如何做checksum
可靠的传输
这里面东西比较多,只记录怎么评估一个可信传输的效率
定义
如果使用pipeline,这里的计算就会变成下图:
特殊传输协议
GBN : Go-Back-N
Sender
在sender这一边,会使用一个大小不超过 累计的ACK
含义是,在收到 ACK(n)
的时候,序列号为 n 之前的所有报文都被成功按序接受了
Sender的行为如下:
- 收到
ACK(n)
的时候,把窗口向后移动到开始 - 对最早的一个发送了但没有
ACK
的包开计时器 - 在计时器超时的时候,重发在这个窗口内所有的包
Receiver
在这一边是ACK-only的,换言之只会发送当前收到的有序的最高序号的 ACK
Receiver的行为如下:
- 收到一个有序的包的时候,移动自己的
rcv_base
这个变量,回复当前最高的有序序列号ACK(n)
- 收到一个非有序的包的时候,可以丢弃这个包也可以储存下来,但是一定会回复一个当前最高有序序列号
ACK(n)
一个例子如下图:
SR : Selective repeat
这个协议的特色是对每一个包分开进行ACK,分开进行计时
Sender
- 当上面应用层往下发数据的时候,如果这个数据的
seq
现在在 Window 里面,就发送这个包 - 当第n个包的计时器超时的时候,即
timeout(n)
的时候,就重发这个包并重启这个计时器 - 收到
ack(n)
的时候,如果那么 - 标记 n 号包为已接收
- 如果这个 n 就是当前最小的没有被ack的n那么把窗口往前移动一格
Receiver
- 如果收到的包
那么 - 发送
- 如果是非有序的,那么就储存在buffer里面
- 如果是有序的,就把到当前为止所有有序的数据全部发给应用层,并且移动Window
- 发送
- 如果收到的
换言之在上一个Window里面,回复 - 否则忽略
Hint:我认为这里之所以需要给上一个窗口里面的也发ack是有可能上一个窗口内的某个ack没有成功发送给sender,那么sender就不知道上一个已经完全发送完了,就不会移动自己的Window
一个例子:
TCP协议
TCP协议报文样式
TCP协议的报文如下图所示
如何设计TCP的timeout时间
首先定义 SampleRTT
表示一个报文发送到接收到 ACK
的时间
下面给出这个的更新公式:
这个更新方式被称为 exponential weighted moving average (EWMA)
而衡量超时时间 TimeourInterval
的公式被定义如下:
而这里的 DevRTT
由下面的公式计算得出:
Sender和Receiver的行为
Sender
- 收到一个来自应用层的数据
- 产生对应的报文,其中的
seq #
就是它在bytestream中的位置 - 如果当前没有timer在运行就开启一个timer,并且设置过期时间为
TimeoutInterval
计算方法见上
- 产生对应的报文,其中的
- 如果timer超时了
- 重新发送没有被ack的第一个包
- 重启timer
- 收到了一个ACK
- 如果这个ACK的序号是在未被ACK的序列里面的
- 更新未被ACK的最大编号
- 如果此时还有没被ACK的包,那么就重启一下timer
- 否则计数,如果这种duplicate ack发送了三次,那么进入快速重传机制,重发第一个没有ack的包
- 如果这个ACK的序号是在未被ACK的序列里面的
Receiver
- 如果收到的是按照顺序的下一个包,那么进入
delay ack
即等待500ms如果没有下一个包到达再发ack - 如果收到的时候按顺序的下一个包并且当前有一个ack在等待发送,那么立即发送两个ack,表示这两个包都收到了
- 如果收到的包序号比当前预期的序号大,那么立即发送duplicate ack表示当前有乱序/丢包
- 否则不必理会
快速重传机制
如果Sender收到三个过期的ack(duplicate ack) 那么不必等待超时直接重发第一个没有ack的包
流量控制
Receiver会在回传的包里面填写 rwnd
字段,表示receiver期望获得的数据窗口的大小
链接控制
三次握手建立连接
TCP在建立连接的时候,会进行三次握手,其具体过程如下:
Hint:如果没有第三次client回传一个 ACK=1 ACKNum = y + 1 的包,那么server不知道此时client是否成功收到了上一个server表示同意的包
四次挥手断开连接
client和server都会分别发送自己的 FIN = 1
的包,并且收到之后都会回复 ACK
这里在一方收到
FIN
的时候,可以在进行ack
应答的同时发自己的FIN
拥塞控制
基本定义
TCP的拥塞控制采用 AIMD
策略,即 Additive Increase Multiplicative Decrease
- Additive Increase:每次都会把发送速率提高1
- Multiplicative Decrease:每次出现loss的时候,会吧发送速率直接对半砍
这里的Multiplicative Decrease有两种策略: - 如果遇到的是三个过期的ack,这个时候对半砍,称为
TCP Reno
- 如果事件是超时,这个时候直接把发送速率设计成 1 MSS(最大的报文长度) 称为
TCP Tahoe
这里定义cwnd
表示发送了但没有ack的包和可用但未发送的包的总和,定义一个TCP Rate
为:
slow start
在最开始的时候,cwnd会被设置为1,然后后面每一次都会倍增,即乘以2,直到出现loss事件(timeout或者3个过期的ack)
ssthresh
这个变量在每次出现loss事件的时候,都会被更新为loss事件之前的cwnd的一半
每次当cwnd大于了ssthresh的时候,此时的增长会从2倍的倍增改为线性增长
TCP CUBIC
基于延迟的拥塞控制
这里先计算一个叫measured throughput的东西,计算方法是:
而注意到没有拥塞发生的throughput应该是:
如果这两个值很接近那么就线性增加 cwnd
否则应该线性减少cwnd
TCP Fairness
Fairness的定义
这里期望的Fairness是如果有
UDP和TCP的Fairness
这里给出结论,在理想状态下,TCP
是公平的,但是 UDP
没有公平性保证