连接复用

UDP: User Datagram Protocol

UDP只用一个二元组来区分链接,一个UDP的头只包括 dest ipdest port 两个信息而在对上面的应用层提供服务的时候,拥有同样的 ipport 的数据块会被送到同一个 Socket 里面

TCP

TCP使用一个四元组来区分链接,即(source ip,source port, dest ip,dest port) 这个四元组来区分,只有当这四元组完全相同的时候才会送到同一个 Socket 里面去。

UDP

优点和缺点

优点

  • 不需要握手建立连接
  • 简单,发送端和接收端没有状态切换
  • 报文头小

缺点

  • 只是尽最大努力传输,所以报文可能会丢失、乱序
  • 没有拥塞控制,可能会严重超时

UDP报文的样式

如何做checksum

可靠的传输

这里面东西比较多,只记录怎么评估一个可信传输的效率

定义 表示sender工作的时长站总传输时长的占比,定义传输时间 这里的 表示每一个待发包的大小,而 表示这个Link的传输速率,那么在发送一个包并等待 的这个过程中有

如果使用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的包

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是如果有 个TCP链接共享同一个宽度为 的物理链接的时候,它们每一个的传输速率都接近

UDP和TCP的Fairness

这里给出结论,在理想状态下,TCP 是公平的,但是 UDP 没有公平性保证