Bittorrent uTorrent?傳輸協(xié)議

uTorrent 傳輸協(xié)議(uTP)由 Ludvig Strigeus沉帮,Greg Hazel,Stanislav Shalunov娇澎,Arvid Norberg 和 Bram Cohen 設(shè)計(jì)逐工。

設(shè)計(jì)原因

uTP 協(xié)議的動(dòng)機(jī)是讓 BitTorrent 客戶端不會(huì)中斷互聯(lián)網(wǎng)連接,同時(shí)仍然充分利用未使用的帶寬铝噩。

BitTorrent 流量通常是后臺(tái)傳輸衡蚂,其優(yōu)先級(jí)應(yīng)該低于檢查電子郵件,辦公和瀏覽網(wǎng)頁(yè)骏庸,但是當(dāng)使用常規(guī) TCP 連接時(shí)毛甲,BitTorrent 會(huì)快速填滿發(fā)送緩沖區(qū),為所有交互式流量增加數(shù)秒的延遲具被。 BitTorrent 使用多個(gè) TCP 連接的事實(shí)使其在與其他服務(wù)競(jìng)爭(zhēng)帶寬時(shí)具有不公平的優(yōu)勢(shì)玻募,這夸大了 BitTorrent 占用上傳帶寬的效果。這樣做的原因是 TCP 在連接之間均勻分配可用帶寬一姿,并且一個(gè)應(yīng)用程序使用的連接越多七咧,它獲得的帶寬份額就越大跃惫。

這個(gè)問(wèn)題的傳統(tǒng)解決方案是將 BitTorrent 客戶端的上傳速率限制在上行帶寬容量的 80% 。為其余上下行流量留下了一些空間艾栋。此解決方案的主要缺點(diǎn)是:

  1. 用戶需要配置他/她的 BitTorrent 客戶端爆存,它不會(huì)即開即用。
  2. 用戶需要知道他/她的互聯(lián)網(wǎng)連接的上限容量蝗砾。此容量可能會(huì)發(fā)生變化先较,尤其是在可能連接到大量不同網(wǎng)絡(luò)的筆記本電腦或手機(jī)上。
  3. 20% 的余量是比較隨意的悼粮,會(huì)浪費(fèi)帶寬闲勺。每當(dāng)沒(méi)有交互式流量與 BitTorrent 競(jìng)爭(zhēng)時(shí),額外的 20% 就會(huì)被浪費(fèi)掉矮锈。每當(dāng)存在競(jìng)爭(zhēng)的交互式流量時(shí)霉翔,它不能只需要使用 20% 的容量。

uTP 通過(guò)使用調(diào)制解調(diào)器隊(duì)列大小作為其發(fā)送速率的控制器來(lái)解決此問(wèn)題苞笨。當(dāng)隊(duì)列變得太大時(shí)债朵,它會(huì)控制流量。這允許它在沒(méi)有競(jìng)爭(zhēng)時(shí)利用全部上傳容量瀑凝,并且在有大量交互式流量時(shí)允許它減少到幾乎為零序芦。

概述

本文檔假定讀者對(duì) TCP 和基于窗口的堵塞控制的工作原理有一定的了解。 uTP 是一種分層在 UDP 之上的傳輸協(xié)議粤咪。因此谚中,它必須(并且有能力)實(shí)現(xiàn)自己的網(wǎng)絡(luò)堵塞控制。與 TCP 相比寥枝,主要區(qū)別在于基于延遲的堵塞控制宪塔。

uTP 是建立在 UDP 之上的傳輸協(xié)議,因此它需要自己實(shí)現(xiàn)擁塞控制機(jī)制囊拜。與 TCP 相比某筐,uTP 的主要區(qū)別在于基于延遲的擁塞控制。具體細(xì)節(jié)可參考擁塞控制部分的描述冠跷。類似于 TCP南誊,uTP 采用基于窗口的擁塞控制。每個(gè)套接字都有一個(gè) max_window蜜托,用于確定套接字在任何給定時(shí)間內(nèi)可同時(shí)傳輸?shù)淖畲笞止?jié)數(shù)抄囚。已發(fā)送但尚未確認(rèn)的任何數(shù)據(jù)包都被認(rèn)為是在傳輸過(guò)程中。

  1. cur_window 表示當(dāng)前傳輸過(guò)程中的字節(jié)數(shù)橄务。只有當(dāng) cur_window + packet_size 小于等于 min(max_window, wnd_size)時(shí)幔托,套接字才能發(fā)送數(shù)據(jù)包。 packet_size 表示數(shù)據(jù)包的大小蜂挪,可能會(huì)有不同的取值柑司。
  2. wnd_size 是對(duì)方端口所廣告的窗口大小迫肖。它設(shè)置了傳輸中的數(shù)據(jù)包數(shù)量的上限锅劝。
  3. 如果 max_window 小于數(shù)據(jù)包大小攒驰,并且通過(guò)調(diào)整數(shù)據(jù)包傳輸速率使得平均 cur_window 小于等于 max_window,實(shí)現(xiàn)可能違反上述規(guī)則故爵。
  4. 每個(gè)套接字保存了與其他端點(diǎn)的最后一次延遲測(cè)量狀態(tài)(reply_micro)玻粪。每當(dāng)接收到一個(gè)數(shù)據(jù)包時(shí),通過(guò)將時(shí)間戳(以微秒為單位)減去主機(jī)當(dāng)前時(shí)間來(lái)更新該狀態(tài)诬垂。
  5. 每次發(fā)送數(shù)據(jù)包時(shí)劲室,套接字的 reply_micro 值將放置在數(shù)據(jù)包頭部的 timestamp_difference_microseconds 字段中。
  6. 與 TCP 不同结窘,uTP 中的序列號(hào)和 ACK 是基于數(shù)據(jù)包而不是字節(jié)的很洋。這意味著在重新發(fā)送數(shù)據(jù)時(shí),uTP 無(wú)法對(duì)其進(jìn)行重新封裝隧枫。
  7. 每個(gè)套接字都保持著下一個(gè)用于發(fā)送數(shù)據(jù)包的序列號(hào)(seq_nr)和上次接收到的數(shù)據(jù)包的序列號(hào)(ack_nr)的狀態(tài)喉磁。最老的未確認(rèn)數(shù)據(jù)包序列號(hào)為 seq_nr – cur_window 。

header 格式

版本 1 標(biāo)頭:

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

所有字段均按網(wǎng)絡(luò)字節(jié)順序(大端序)排列官脓。

版本

這是協(xié)議版本协怒。當(dāng)前版本為 1 。

connection_id

這是一個(gè)隨機(jī)的唯一數(shù)字卑笨,用于標(biāo)識(shí)屬于同一連接的所有數(shù)據(jù)包孕暇。每個(gè)套接字都有一個(gè)用于發(fā)送數(shù)據(jù)包的連接 ID 和一個(gè)用于接收數(shù)據(jù)包的不同連接 ID 。啟動(dòng)連接的終結(jié)點(diǎn)決定使用哪個(gè) ID赤兴,返回路徑具有相同的 ID + 1 妖滔。

timestamp_microseconds

這是發(fā)送此數(shù)據(jù)包的時(shí)間戳的 “微秒” 部分。這是在 posix 上使用 gettimeofday()和在 windows 上使用 QueryPerformanceTimer()設(shè)置的桶良。此時(shí)間戳的分辨率越高越好座舍。設(shè)置的越接近實(shí)際傳輸時(shí)間越好。

timestamp_difference_microseconds

這是本地時(shí)間與上次接收數(shù)據(jù)包(在收到最后一個(gè)數(shù)據(jù)包時(shí))中的時(shí)間戳之間的差異艺普。這是從遠(yuǎn)程對(duì)等體到本地計(jì)算機(jī)的鏈路的最新單向延遲測(cè)量簸州。當(dāng)套接字是新打開的并且還沒(méi)有任何延遲樣本時(shí),必須將其設(shè)置為 0 歧譬。

wnd_size

播發(fā)的接收窗口岸浑。這是 32 位寬,以字節(jié)為單位指定瑰步。窗口大小是當(dāng)前正在進(jìn)行的字節(jié)數(shù)矢洲,即已發(fā)送但未確認(rèn)的字節(jié)數(shù)。通告的接收窗口允許另一端限制窗口大小缩焦,如果它不能更快地接收读虏,如果它的接收緩沖區(qū)正在填滿责静。發(fā)送數(shù)據(jù)包時(shí),應(yīng)將其設(shè)置為套接字接收緩沖區(qū)中剩余的字節(jié)數(shù)盖桥。

extension

擴(kuò)展標(biāo)頭鏈接列表中第一個(gè)擴(kuò)展的類型灾螃。 0 表示無(wú)擴(kuò)展名。

目前有一個(gè)擴(kuò)展:

  1. 選擇性確認(rèn)

擴(kuò)展是鏈接的揩徊,就像 TCP 選項(xiàng)一樣腰鬼。如果擴(kuò)展字段不為零,則緊跟在 uTP 標(biāo)頭后面的兩個(gè)字節(jié):

0               8               16
+---------------+---------------+
| extension     | len           |
+---------------+---------------+

其中 extension 指定鏈表中下一個(gè)擴(kuò)展名的類型塑荒,0 終止列表熄赡。并 len 指定此擴(kuò)展的字節(jié)數(shù)。未知擴(kuò)展可以通過(guò)簡(jiǎn)單地前進(jìn) len bytes 來(lái)跳過(guò)齿税。

SELECTIVE ACK

選擇性 ACK 是一種擴(kuò)展彼硫,可以非順序地選擇性地 ACK 數(shù)據(jù)包。其有效負(fù)載是至少 32 位的位掩碼凌箕,以 32 位的倍數(shù)表示拧篮。每個(gè)位表示發(fā)送窗口中的一個(gè)數(shù)據(jù)包。發(fā)送窗口之外的位將被忽略陌知。設(shè)置位指定數(shù)據(jù)包已接收他托,清除位指定數(shù)據(jù)包尚未接收。標(biāo)題如下所示:

0               8               16
+---------------+---------------+---------------+---------------+
| extension     | len           | bitmask
+---------------+---------------+---------------+---------------+
                                |
+---------------+---------------+

請(qǐng)注意仆葡,擴(kuò)展的 len 字段引用字節(jié)赏参,在此擴(kuò)展中,字節(jié)必須至少為 4沿盅,并且是 4 的倍數(shù)把篓。

僅當(dāng)接收的流中至少跳過(guò)一個(gè)序列號(hào)時(shí),才會(huì)發(fā)送選擇性 ACK 腰涧。因此韧掩,掩碼中的第一個(gè)位表示 ack_nr + 2 。 ack_nr + 1 假定在發(fā)送此數(shù)據(jù)包時(shí)已被丟棄或丟失窖铡。設(shè)置位表示已接收的數(shù)據(jù)包疗锐,清除位表示尚未接收的數(shù)據(jù)包。

位掩碼的字節(jié)順序相反费彼。第一個(gè)字節(jié)以相反的順序表示數(shù)據(jù)包 [ack_nr + 2滑臊, ack_nr + 2 + 7] 。字節(jié)中最低有效位表示 ack_nr + 2箍铲,字節(jié)中最高有效位表示 ack_nr + 2 + 7 雇卷。掩碼中的下一個(gè)字節(jié)以相反的順序表示 [ack_nr + 2 + 8,ack_nr + 2 + 15],依此類推关划。位掩碼不限于 32 位小染,但可以是任何大小。

下面是位掩碼的布局贮折,表示選擇性 ACK 位域中表示的前 32 個(gè)數(shù)據(jù)包確認(rèn):

0               8               16
+---------------+---------------+---------------+---------------+
| 9 8 ...   3 2 | 17   ...   10 | 25   ...   18 | 33   ...   26 |
+---------------+---------------+---------------+---------------+

圖中的數(shù)字將位掩碼中的位映射到要添加到 ack_nr 的偏移量裤翩,以便計(jì)算位正在確認(rèn)的序列號(hào)。

type

類型字段描述數(shù)據(jù)包的類型脱货。它可以是以下之一:

ST_DATA = 0

常規(guī)數(shù)據(jù)包岛都。套接字處于連接狀態(tài),并且有要發(fā)送的數(shù)據(jù)振峻。 ST_DATA 數(shù)據(jù)包始終具有數(shù)據(jù)有效負(fù)載。

ST_FIN = 1

完成連接择份。這是最后一個(gè)數(shù)據(jù)包扣孟。它關(guān)閉連接,類似于 TCP FIN 標(biāo)志荣赶。此連接的序列號(hào)永遠(yuǎn)不會(huì)大于此數(shù)據(jù)包中的序列號(hào)凤价。套接字將此序列號(hào)記錄為 eof_pkt 。這允許套接字等待可能仍然丟失的數(shù)據(jù)包拔创,即使在收到 ST_FIN 數(shù)據(jù)包后也會(huì)無(wú)序到達(dá)利诺。

ST_STATE = 2

狀態(tài)數(shù)據(jù)包。用于傳輸沒(méi)有數(shù)據(jù)的 ACK 剩燥。不包含任何有效負(fù)載的數(shù)據(jù)包不會(huì)增加 seq_nr 慢逾。

ST_RESET = 3

強(qiáng)制終止連接。類似于 TCP RST 標(biāo)志灭红。遠(yuǎn)程主機(jī)沒(méi)有任何此連接的狀態(tài)侣滩。它是過(guò)時(shí)的,應(yīng)該終止变擒。

ST_SYN = 4

與 TCP SYN 標(biāo)志類似君珠,此數(shù)據(jù)包啟動(dòng)連接。序列號(hào)初始化為 1 娇斑。連接 ID 初始化為隨機(jī)數(shù)策添。 syn 數(shù)據(jù)包是特殊的,在此連接上發(fā)送的所有后續(xù)數(shù)據(jù)包(ST_SYN 的重新發(fā)送除外)都以連接 ID + 1 發(fā)送毫缆。連接 ID 是另一端應(yīng)在其響應(yīng)中使用的 ID 唯竹。

收到 ST_SYN 時(shí),應(yīng)使用數(shù)據(jù)包標(biāo)頭中的 ID 初始化新套接字悔醋。套接字的發(fā)送 ID 應(yīng)初始化為 ID + 1 摩窃。返回通道的序列號(hào)初始化為隨機(jī)數(shù)。另一端需要 ST_STATE 數(shù)據(jù)包(僅 ACK)作為響應(yīng)。

seq_nr

這是此數(shù)據(jù)包的序列號(hào)猾愿。與 TCP 相反鹦聪,uTP 序列號(hào)不是指字節(jié),而是數(shù)據(jù)包蒂秘。序列號(hào)告訴另一端數(shù)據(jù)包應(yīng)以何種順序返回應(yīng)用層泽本。

ack_nr

這是數(shù)據(jù)包的發(fā)送方上次在另一個(gè)方向上收到的序列號(hào)。

連接設(shè)置

下圖說(shuō)明了啟動(dòng)連接的交換和狀態(tài)姻僧。 c.* 表示套接字本身中的狀態(tài)规丽,pkt.* 表示數(shù)據(jù)包標(biāo)頭中的字段。

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_SYN_RECV             |
          |                                               |
          |                                               |
          |                                               |
          |                                               |
          |                     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                         |
          |                                               |
          |                                               |
          |                                               |
          | ST_DATA                                       |
          |   seq_nr=c.seq_nr++                           |
          |   ack_nr=c.ack_nr                             |
          |   conn_id=c.conn_id_send                      |
          | >-------------------------------------------> |
          |                        c.ack_nr = pkt.seq_nr  |
          |                        c.state = CS_CONNECTED |
          |                                               |
          |                                               | connection established
     .. ..|.. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..|.. ..
          |                                               |
          |                     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

連接由其 conn_id 標(biāo)頭標(biāo)識(shí)撇贺。如果新連接的連接 ID 與現(xiàn)有連接沖突赌莺,則連接嘗試將失敗,因?yàn)?ST_SYN 數(shù)據(jù)包在現(xiàn)有流中將是意外的松嘶,并被忽略艘狭。

丟包

如果序列號(hào)為( seq_nr – cur_window )的數(shù)據(jù)包尚未確認(rèn)(這是發(fā)送緩沖區(qū)中最早的數(shù)據(jù)包,下一個(gè)數(shù)據(jù)包預(yù)計(jì)被確認(rèn))翠订,但已通過(guò)該數(shù)據(jù)包 3 個(gè)或更多數(shù)據(jù)包(通過(guò)選擇性 ACK)巢音,則假定該數(shù)據(jù)包已丟失。同樣尽超,當(dāng)收到 3 個(gè)重復(fù)的確認(rèn)時(shí)官撼, ack_nr 假定 + 1 已丟失(如果已發(fā)送具有該序列號(hào)的數(shù)據(jù)包)。

這也適用于選擇性確認(rèn)似谁。在選擇性確認(rèn)消息中確認(rèn)的每個(gè)數(shù)據(jù)包都計(jì)為一個(gè)重復(fù)的確認(rèn)傲绣,如果為 3 個(gè)或更多,則應(yīng)觸發(fā)重新發(fā)送至少包含 3 個(gè)數(shù)據(jù)包的數(shù)據(jù)包棘脐。

當(dāng)數(shù)據(jù)包丟失時(shí)斜筐, max_window 乘以 0.5 以模擬 TCP 。

超時(shí)

每個(gè)被確認(rèn)的數(shù)據(jù)包蛀缝,無(wú)論是落在范圍(last_ack_nr 顷链、 ack_nr] 還是被選擇性 ACK 消息顯式確認(rèn),都應(yīng)用于更新(往返時(shí)間)和 rtt rtt_var (rtt 方差)測(cè)量值屈梁。 last_ack_nr 這里是當(dāng)前數(shù)據(jù)包之前在套接字上收到的最后一個(gè) ack_nr嗤练,ack_nr 是當(dāng)前接收的數(shù)據(jù)包中的字段。

僅針對(duì) rtt 僅發(fā)送一次的數(shù)據(jù)包更新 和 rtt_var 在讶。這避免了確定哪個(gè)數(shù)據(jù)包被確認(rèn)的問(wèn)題煞抬,第一個(gè)還是第二個(gè)。

rtt 并通過(guò) rtt_var 以下公式計(jì)算构哺,每次確認(rèn)數(shù)據(jù)包時(shí):

delta = rtt - packet_rtt
rtt_var += (abs(delta) - rtt_var) / 4;
rtt += (packet_rtt - rtt) / 8;

與套接字關(guān)聯(lián)的數(shù)據(jù)包的默認(rèn)超時(shí)也會(huì)每次更新 rtt 并 rtt_var 更新革答。它設(shè)置為:

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

其中以毫秒為單位指定超時(shí)战坤。即數(shù)據(jù)包的最小超時(shí)為 1/2 秒。

每次套接字發(fā)送或接收數(shù)據(jù)包時(shí)残拐,它都會(huì)更新其超時(shí)計(jì)數(shù)器途茫。如果在上次超時(shí)計(jì)數(shù)器重置后的毫秒 timeout 內(nèi)沒(méi)有數(shù)據(jù)包到達(dá),套接字將觸發(fā)超時(shí)溪食。它會(huì)將其 packet_size and max_window 設(shè)置為最小的數(shù)據(jù)包大心也贰(150 字節(jié))仔掸。這允許它再發(fā)送一個(gè)數(shù)據(jù)包籍嘹,如果窗口大小降至零,這就是套接字再次啟動(dòng)的方式梅掠。

初始超時(shí)設(shè)置為 1000 毫秒枢析,稍后根據(jù)上述公式進(jìn)行更新玉掸。對(duì)于超時(shí)的每個(gè)連續(xù)數(shù)據(jù)包,超時(shí)將加倍登疗。

數(shù)據(jù)包大小

為了盡可能減少對(duì)慢速擁塞鏈路的影響排截,uTP 將其數(shù)據(jù)包大小調(diào)整為每個(gè)數(shù)據(jù)包 150 字節(jié)。使用這么小的數(shù)據(jù)包的好處是不會(huì)阻塞慢速上行鏈路辐益,并且序列化延遲較長(zhǎng)。使用這么小的數(shù)據(jù)包的代價(jià)是數(shù)據(jù)包標(biāo)頭的開銷變得很大脱吱。在高速率下智政,使用大數(shù)據(jù)包大小,在慢速率下箱蝠,使用小數(shù)據(jù)包大小续捂。

擁塞控制

uTP 擁塞控制的總體目標(biāo)是使用單向緩沖區(qū)延遲作為主要擁塞測(cè)量,以及數(shù)據(jù)包丟失(如 TCP)宦搬。關(guān)鍵是要避免在發(fā)送數(shù)據(jù)時(shí)使用完整的發(fā)送緩沖區(qū)運(yùn)行牙瓢。對(duì)于 DSL/電纜調(diào)制解調(diào)器來(lái)說(shuō),這是一個(gè)特別的問(wèn)題间校,其中調(diào)制解調(diào)器中的發(fā)送緩沖區(qū)通常具有容納數(shù)秒數(shù)據(jù)的空間矾克。 uTP(或任何后臺(tái)流量協(xié)議)的理想緩沖區(qū)利用率是以 0 字節(jié)緩沖區(qū)利用率運(yùn)行。即任何其他流量可以隨時(shí)發(fā)送憔足,而不會(huì)受到后臺(tái)流量阻塞發(fā)送緩沖區(qū)的阻礙胁附。實(shí)際上,uTP 目標(biāo)延遲設(shè)置為 100 毫秒滓彰。每個(gè)套接字的目標(biāo)是永遠(yuǎn)不會(huì)在發(fā)送鏈接上看到超過(guò) 100 毫秒的延遲控妻。如果是這樣,它將節(jié)流回去揭绑。

這有效地使 uTP 屈服于任何 TCP 流量弓候。

這是通過(guò)在通過(guò) uTP 發(fā)送的每個(gè)數(shù)據(jù)包中包含高分辨率時(shí)間戳來(lái)實(shí)現(xiàn)的,接收端計(jì)算其自己的高分辨率計(jì)時(shí)器與其接收的數(shù)據(jù)包中的時(shí)間戳之間的差異。然后將此差異反饋給數(shù)據(jù)包的原始發(fā)送方(timestamp_difference_microseconds)菇存。此值作為絕對(duì)值沒(méi)有意義夸研。機(jī)器中的時(shí)鐘很可能不同步,尤其是沒(méi)有達(dá)到微秒級(jí)的分辨率撰筷,并且數(shù)據(jù)包的傳輸時(shí)間也包含在這些時(shí)間戳的差異中陈惰。但是,與以前的值相比毕籽,該值很有用抬闯。

每個(gè)套接字在最后兩分鐘內(nèi)保持最低值的滑動(dòng)最小值。此值稱為 base_delay关筒,用作基準(zhǔn)溶握,即主機(jī)之間的最小延遲。從每個(gè)數(shù)據(jù)包的時(shí)間戳差異中減去 base_delay 時(shí)蒸播,您可以測(cè)量套接字上的當(dāng)前緩沖延遲睡榆。這種測(cè)量稱為 our_delay 。它有很多噪音袍榆,但用作驅(qū)動(dòng)程序來(lái)確定是增加還是減少發(fā)送窗口(控制發(fā)送速率)胀屿。

CCONTROL_TARGET 是 uTP 在上行鏈路上接受的緩沖延遲。目前包雀,延遲目標(biāo)設(shè)置為 100 毫秒宿崭,off_target 實(shí)際測(cè)量的延遲與目標(biāo)延遲的距離(根據(jù) CCONTROL_TARGET – our_delay 計(jì)算)。

套接字結(jié)構(gòu)中的窗口大小指定了我們?cè)谶B接上總共可能具有的運(yùn)行(未確認(rèn))字節(jié)數(shù)才写。發(fā)送速率與此窗口大小直接相關(guān)葡兑。傳輸中的字節(jié)越多,發(fā)送速率越快赞草。在代碼中讹堤,窗口大小稱為 max_window 。它的大小大致由以下表達(dá)式控制:

delay_factor = off_target / CCONTROL_TARGET;
window_factor = outstanding_packet / max_window;
scaled_gain = MAX_CWND_INCREASE_PACKETS_PER_RTT * delay_factor * window_factor;

其中厨疙,第一個(gè)因素將 off_target 縮放到目標(biāo)延遲單位洲守。

然后將 scaled_gain 添加到 max_window:

max_window += scaled_gain;

如果 off_target 大于 0,這將使窗口變小轰异,如果偏離目標(biāo)小于 0岖沛,則窗口增大。

如果 max_window 小于 0搭独,則設(shè)置為 0 婴削。窗口大小為零表示套接字可能不會(huì)發(fā)送任何數(shù)據(jù)包。在此狀態(tài)下牙肝,套接字將觸發(fā)超時(shí)并強(qiáng)制窗口大小為一個(gè)數(shù)據(jù)包大小唉俗,并發(fā)送一個(gè)數(shù)據(jù)包嗤朴。有關(guān)詳細(xì)信息,請(qǐng)參閱有關(guān)超時(shí)的部分虫溜。

參考鏈接

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末雹姊,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子衡楞,更是在濱河造成了極大的恐慌吱雏,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,386評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件瘾境,死亡現(xiàn)場(chǎng)離奇詭異歧杏,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)迷守,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,142評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門犬绒,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人兑凿,你說(shuō)我怎么就攤上這事凯力。” “怎么了礼华?”我有些...
    開封第一講書人閱讀 164,704評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵咐鹤,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我圣絮,道長(zhǎng)慷暂,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,702評(píng)論 1 294
  • 正文 為了忘掉前任晨雳,我火速辦了婚禮,結(jié)果婚禮上奸腺,老公的妹妹穿的比我還像新娘餐禁。我一直安慰自己,他們只是感情好突照,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,716評(píng)論 6 392
  • 文/花漫 我一把揭開白布帮非。 她就那樣靜靜地躺著,像睡著了一般讹蘑。 火紅的嫁衣襯著肌膚如雪末盔。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,573評(píng)論 1 305
  • 那天座慰,我揣著相機(jī)與錄音陨舱,去河邊找鬼。 笑死版仔,一個(gè)胖子當(dāng)著我的面吹牛游盲,可吹牛的內(nèi)容都是我干的误墓。 我是一名探鬼主播,決...
    沈念sama閱讀 40,314評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼益缎,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼谜慌!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起莺奔,我...
    開封第一講書人閱讀 39,230評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤欣范,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后令哟,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體恼琼,經(jīng)...
    沈念sama閱讀 45,680評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,873評(píng)論 3 336
  • 正文 我和宋清朗相戀三年励饵,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了驳癌。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,991評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡役听,死狀恐怖颓鲜,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情典予,我是刑警寧澤甜滨,帶...
    沈念sama閱讀 35,706評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站瘤袖,受9級(jí)特大地震影響衣摩,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜捂敌,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,329評(píng)論 3 330
  • 文/蒙蒙 一艾扮、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧占婉,春花似錦泡嘴、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,910評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至奖慌,卻和暖如春抛虫,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背简僧。 一陣腳步聲響...
    開封第一講書人閱讀 33,038評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工建椰, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人涎劈。 一個(gè)月前我還...
    沈念sama閱讀 48,158評(píng)論 3 370
  • 正文 我出身青樓广凸,卻偏偏與公主長(zhǎng)得像阅茶,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子谅海,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,941評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容