BT协议学习笔记4--uTP

这是一个对于uTorrent建立在UDP之上的传输层协议。可以和目的就是为了改善TCP的一些特性,可以和TCP作一些对比学习。

所以我想专门对这个拓展,记录一章。

BEP:uTorrent transport protocol

作用:在DSL 和 cable modems中,会有一个send buffer由于TCP connection采用的是平均分配带宽的方式。

在所有的服务中,BT会建立很多的TCP connections,而其他本来应该具有高优先级的服务比如:电子邮件,电话,网页浏览。

它们因为具有的TCP connection少,所以就会争抢到少量带宽,从而经历大量延迟。

而采用架设在UDP层之上的uTP协议,能够根据网络的延迟来很好滴调控自身,使没有其他服务的时候充分利用带宽,而有其他服务的时候让出带宽。

其实迅雷的网页模式和下载模式大概就是这个意思,只是迅雷给user一个使用的选择吧,当然实际效果怎么样,主要还是看自己的网啦。

格式:既然是建立在UDP之上一层,帧结构就应该是这样。<uTP帧>=<帧头><payload>,其中<payload>=<UDP帧>。或者还有个校验什么的。

标准中主要给出了帧头信息,如下


version 1 header:

0       4       8               16              24              32
+-------+-------+---------------+---------------+---------------+
| type  | ver   | extension     | connection_id                 |
+-------+-------+---------------+---------------+---------------+
| timestamp_microseconds                                        |
+---------------+---------------+---------------+---------------+
| timestamp_difference_microseconds                             |
+---------------+---------------+---------------+---------------+
| wnd_size                                                      |
+---------------+---------------+---------------+---------------+
| seq_nr                        | ack_nr                        |
+---------------+---------------+---------------+---------------+


type:帧类型。一共有ST_DATA = 0,ST_FIN = 1,ST_STATE = 2,ST_RESET = 3,ST_SYN = 4 五种。
分别表示数据帧,断开连接帧(TCP 的FIN),确认帧(TCP 的ACK),重建连接帧,建立连接帧(TCP 的SYN)

()表示,对应TCP里面的类型。

ver:版本号。不重要。

extension:扩展字段,比如selective ack就需要这个字段非零,没有扩展置零即可。

connection id:用来唯一表示一个连接的,一个connection会使用两个id,一个用来发,一个用来收,注意本端的收=对端的发,所以一个connection有两个id,而变量一共有四个:一端的收发两个,另一端的收发两个。而一端的收发id只相差1(连接发起一端随机产生一个数,作为接收id,此端发送id=接收id+1),所以可以用这个id来唯一标识一个connection。

timestamp_microseconds:表示此帧的发送时间。

timestamp_difference_microseconds:单向传播时延,用帧的收到时间-timestamp_microseconds的到。由于两端的时间并没有同步,或者说并没有到达微秒级别的同步,这个字段的绝对值并没有实际意义,但是对比两次timestamp_difference_microseconds的差别具有意义。

wnd_size:窗口大小,这个和TCP里面的意义一样,是对端给的一个限制发送的标志,用于流量控制。

seq_nr:包序号。这个和TCP一样,双方各自维护一个序列来表示自己的发送。

ack_nr:确认号。注意这里和TCP不同,TCP是应答下一个期望得到的对方的seq。而这里是收到了哪个seq就ack那个seq。

比如,TCP中,我收到了对方的seq1000我的ack就是1001.而在这里我收到了seq1000我还是ack1000。

帧头信息总结,在简单的交互之中,最重要的就是这四个参数:type,connection id,seq_nr,ack_nr。在接下来的connection setup流程中可以看到。

而timestamp那两个字段要具体的网络环境才能确定。

最后还有个本端需要知道的参数是max_window,用于拥塞控制,相关计算后面会有。


connection setup
Here is a diagram illustrating the exchanges and states to initiate a connection. The c.* refers to a state in the socket itself, pkt.* refers to a field in the packet header.

initiating endpoint                           accepting endpoint

          | c.state = CS_SYN_SENT                         |
          | c.seq_nr = 1                                  |
          | c.conn_id_recv = rand()                       |
          | c.conn_id_send = c.conn_id_recv + 1           |
          |                                               |
          |                                               |
          | ST_SYN                                        |
          |   seq_nr=c.seq_nr++                           |
          |   ack_nr=*                                    |
          |   conn_id=c.rcv_conn_id                       |
          | >-------------------------------------------> |
          |             c.receive_conn_id = pkt.conn_id+1 |
          |             c.send_conn_id = pkt.conn_id      |
          |             c.seq_nr = rand()                 |
          |             c.ack_nr = pkt.seq_nr             |
          |             c.state = CS_CONNECTED            |
          |                                               |
          |                                               |
          |                                               |
          |                                               |
          |                     ST_STATE                  |
          |                       seq_nr=c.seq_nr++       |
          |                       ack_nr=c.ack_nr         |
          |                       conn_id=c.send_conn_id  |
          | <------------------------------------------<  |
          | c.state = CS_CONNECTED                        |
          | c.ack_nr = pkt.seq_nr                         |
          |                                               |
          |                                               | connection established
     .. ..|.. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..|.. ..
          |                                               |
          |                                               |
          | ST_DATA                                       |
          |   seq_nr=c.seq_nr++                           |
          |   ack_nr=c.ack_nr                             |
          |   conn_id=c.conn_id_send                      |
          | >-------------------------------------------> |
          |                         c.ack_nr = pkt.seq_nr |
          |                                               |
          |                                               |
          |                                               |
          |                     ST_DATA                   |
          |                       seq_nr=c.seq_nr++       |
          |                       ack_nr=c.ack_nr         |
          |                       conn_id=c.send_conn_id  |
          | <------------------------------------------<  |
          | c.ack_nr = pkt.seq_nr                         |
          |                                               |
          |                                               |
          V                                               V

Congestion Control

前面已经提到了,流量控制使用参数:wnd_size 而拥塞控制使用参数:max_window。

其实拥塞控制的所有内容都是按照max_window这个参数展开的。

注意:max_window和wnd_size的单位都是bytes,current_window的单位也是bytes。

那么下面分两种情况讨论max_window的变化:(1)正常情况基于delay变化。(2)有丢包重传发生。

(1)正常情况下基于delay变化

先要介绍几个delay。

timestamp:发送时的时间。

timestamp_variance:收到时间-发送时间、即单边延迟。

base_delay:2min 内最小的timestamp_variance。

our_delay:本次timestamp_variance-base_delay。

off_target:CCONTROL_TARGET-our_delay,其中CCONTROL_TARGET=100ms。

delay_factor = off_target / CCONTROL_TARGET;

window_factor = outstanding_packet / max_window;

scaled_gain = MAX_CWND_INCREASE_PACKETS_PER_RTT * delay_factor * window_factor

max_window += scaled_gain

即可计算max_window

(2)有丢包发生。

①数据驱动的重传。

即越界应答超过3个以上,或者3个以上的duplicate ACKs。

max_window=max_window/2

②时间驱动,即timeout。

它会有各种计算RTT的公式,然后


rtt and rtt_var are calculated by the following formula, every time a packet is ACKed:

delta = rtt - packet_rtt
rtt_var += (abs(delta) - rtt_var) / 4;
rtt += (packet_rtt - rtt) / 8;
The default timeout for packets associated with the socket is also updated every time rtt and rtt_var is updated. It is set to:

timeout = max(rtt + rtt_var * 4, 500);

一旦超时以后,就会

max_window=max_window/2

包大小也会设置为最小的150bytes。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值