日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

uTorrent transport protocol

發布時間:2024/3/26 编程问答 55 豆豆
生活随笔 收集整理的這篇文章主要介紹了 uTorrent transport protocol 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

uTorrent Transport Protocol

  • 設計人員
  • 產生背景
  • 總體介紹
  • 頭部格式
      • type
      • version
      • connection_id
      • timestamp_microseconds
      • timestamp_difference_microseconds
      • wnd_size
      • seq_nr
      • ack_nr
      • extension
        • SELECTIVE ACK
  • 建立連接
  • 包丟失
  • 超時
  • 包大小
  • 擁塞控制

設計人員

uTorrent傳輸協議由Ludvig Strigeus,Greg Hazel,Stanislav Shalunov,Arvid Norberg和Bram Cohen設計。

產生背景

uTP的起源動機是讓BitTorrent客戶端不會中斷互聯網連接,同時仍然充分利用未使用的帶寬。

問題是DSL和電纜調制解調器通常具有與其最大發送速率不成比例的發送緩沖器,其可以容納幾秒鐘的數據包。BitTorrent流量通常是后臺傳輸,應該比檢查電子郵件,電話和瀏覽網頁的優先級低,但是當使用常規TCP連接時,BitTorrent會快速填滿發送緩沖區(多并發連接),為所有交互式流量增加多秒延遲。

BitTorrent使用多個TCP連接這一事實使其在與其他服務競爭帶寬時具有不公平的優勢,這夸大了BitTorrent填充上傳管道的影響。這是因為TCP在連接中均勻分配可用帶寬,并且一個應用程序使用的連接越多,它所獲得的帶寬份額就越大。

這個問題的傳統解決方案是將BitTorrent客戶端的上傳速率限制在上行鏈路容量的80%。80%為交互式交通留下了一些空間。

該解決方案的主要缺點是:

  • 用戶需要配置他/她的BitTorrent客戶端,它不會開箱即用。
  • 用戶需要知道他/她的互聯網連接的上傳容量。此容量可能會發生變化,尤其是在可能連接到大量不同網絡的筆記本電腦上。
  • 20%的凈空是任意的,浪費帶寬。每當沒有交互式流量與BitTorrent競爭時,額外的20%就會被浪費掉。每當存在競爭性交互流量時,它就不能使用超過20%的容量。
  • uTP通過使用調制解調器隊列大小作為其發送速率的控制器來解決此問題。當隊列變得太大時,它會限制回來。

    這使得它可以在沒有競爭的情況下利用完整的上傳容量,并且當有大量交互流量時,它可以讓它減少到幾乎沒有。

    總體介紹

    本文檔假設您了解TCP和基于窗口的擁塞控制的工作原理。

    uTP是一種在UDP之上分層的傳輸協議。因此,它必須(并且有能力)實現自己的擁塞控制。

    與TCP相比的主要區別是基于延遲的擁塞控制。請參閱擁塞控制部分。

    與TCP一樣,uTP使用基于窗口的擁塞控制。每個socket具有一個max_window,其決定在任何給定的時間,socket可以具有處于 in-flight 狀態的最大字節數。已發送但尚未確認的任何數據包都被視為處于 in-flight 狀態,處于 in-flight 狀態的字節數被定義為 cur_window。

    只有在 cur_window + packet_size <= min(max_window,wnd_size),socket 允許發送數據包。數據包大小可能會有所不同,請參閱數據包大小部分。wnd_size是對端的建議窗口。它設定了對端處于 in-flight 狀態的數據包數量上限。

    如果 max_window 小于數據包大小,則實現可能違反上述規則,并且它會調度數據包以使平均 cur_window <= max_window。

    每個socket記錄來自對端的最后一次延遲測量的狀態(reply_micro)。無論何時收到數據包,都會通過從主機當前時間減去timestamp_microseconds字段值(參閱頭部格式部分)來更新此狀態(以微秒為單位)。每次發送數據包時,socket 的reply_micro值都會放入數據包標頭的timestamp_difference_microseconds字段中。

    與TCP不同,uTP中的序列號和ACK指的是數據包,而不是字節。這意味著uTP 在重新發送時無法重新打包數據。

    每個socket會記錄發送數據包時要使用的下一個序列號seq_nr。它還記錄上次接收的序列號ack_nr。最舊的未確認的數據包是seq_nr - cur_window。

    頭部格式

    version 1 頭部:

    所有字段都按網絡字節順序(大端)。

    type

    type字段描述了數據包的類型。它可以是以下之一:

    • ST_DATA = 0
      常規數據包。套接字處于連接狀態并具有要發送的數據。ST_DATA數據包始終具有數據有效負載。

    • ST_FIN = 1
      終止連接。這是最后一個數據包。類似于TCP FIN標志,關閉連接。屬于該連接的數據包,序列號永遠不會有大于此數據包中的序列號。socket將此序列號記錄為eof_pkt。即使在收到ST_FIN數據包后,socket仍會等待一段時間,接收那些可能是丟失的或亂序到達的數據包。

    • ST_STATE = 2
      狀態包。用于傳輸沒有數據的ACK。不包含任何有效負載的數據包不會增加seq_nr。

    • ST_RESET = 3
      強行終止連接。與TCP RST標志類似。遠程主機沒有此連接的任何狀態,標識它是陳舊的,應該被終止。

    • ST_SYN = 4
      連接SYN。與TCP SYN標志類似,此數據包啟動連接。序列號初始化為1。connection ID 初始化為隨機數。syn數據包是特殊的,在此連接上發送的所有后續數據包(除了重新發送的ST_SYN)都使用(connection ID + 1)發送。connection ID 是另一端在其響應中使用的。

      當接收到ST_SYN時,應使用包頭中的ID初始化新socket。應將socket的發送ID初始化為ID + 1。返回通道的序列號初始化為隨機數。另一端期望收到響應ST_STATE包(僅ACK)。

    version

    協議版本。目前的版本是1。

    connection_id

    這是一個隨機的唯一編號,用于標識屬于同一連接的所有數據包。每個socket都有一個用于發送數據包的連接ID和用于接收數據包的不同連接ID。啟動連接的端點決定使用哪個ID,返回路徑具有相同的ID + 1。

    timestamp_microseconds

    這是發送此數據包的時間戳的“微秒”部分。這是在posix上使用gettimeofday()和在windows上使用QueryPerformanceTimer()設置的。時間戳精度越高越好,時間戳設定越接近實際傳輸時間越好。

    timestamp_difference_microseconds

    這是收到最新的一個數據包時,數據包的時間戳和本地時間之間的差值。這是從遠端到本地的鏈路最新單向延遲測量。

    當新打開socekt并且還沒有任何延遲樣本時,必須將其設置為0。

    wnd_size

    通知接收窗口。這是32位寬,以字節為單位指定。

    window size是指當前正在傳輸的字節數,即已發送但未被確認ACK。當接收緩沖區即將被填滿時,如果它不能更快??地接收,則通知接收窗口可以讓另一端修改窗口大小。

    發送數據包時,應將其設置為socket接收緩沖區中剩余的字節數。

    seq_nr

    這是該數據包的序列號。與TCP相反,uTP序列號不是指字節,而是指數據包。序列號告訴另一端應該將數據包送回應用層的順序。

    ack_nr

    這是數據包的發送者最后在對端接收的序列號。

    extension

    擴展鏈表中第一個擴展的類型。0表示沒有擴展名。

    目前有一個擴展:

  • Selective acks
  • 擴展是鏈接形式的,就像TCP options一樣。如果擴展字段非零,則緊跟在uTP頭之后是兩個字節:

    其中extension指定鏈表中下一個擴展的類型,0終止列表。len指定這個擴展的字節數。只需向前len個字節就可以跳過未知的擴展名。

    SELECTIVE ACK

    Selective ACK是一種非順序的、可選擇性的ACK包擴展。其有效載荷是至少32位的位掩碼,長度是32位的倍數。每個位代表發送窗口中的一個數據包。發送窗口之外的位將被忽略。設置位(1)指定已接收數據包,清除位(0)指定尚未接收數據包。頭部格式如下:

    請注意,擴展名的len字段指的是字節,在此擴展名中必須至少為4,并且為4的倍數。

    僅當在接收的流中跳過至少一個序列號時才發送選擇性ACK。因此,掩碼中的第一個比特表示ack_nr + 2。當發送該包時,則ack_nr + 1被假設為已被丟棄或丟失。設置位表示已接收的數據包,清除位表示尚未接收的數據包。

    位掩碼具有反向字節順序。第一個字節以相反的順序表示包[ack_nr + 2,ack_nr + 2 + 7]。字節中的最低有效位表示ack_nr + 2,字節中的最高有效位表示ack_nr + 2 + 7。掩碼中的下一個字節以相反的順序表示[ack_nr + 2 + 8,ack_nr + 2 + 15],等等。位掩碼不限于32位,而是可以是任何大小。

    以下是位掩碼的布局,表示在Selective ACK位域中表示的前32個包的acks:

    圖中的數字將位掩碼中的位映射到偏移量,然后加上 ack_nr來計算該位要確認的序列號。

    建立連接

    下圖說明了啟動連接的通信和狀態。c.*指的是socket本身的狀態,pkt.*指的是包頭中的字段。

    連接由conn_id標頭標識。如果新連接的連接ID與現有連接沖突,則連接嘗試將失敗,因為ST_SYN數據包在現有流中將是異常的,并被忽略。

    包丟失

    如果序列號(seq_nr - cur_window)的數據包尚未被確認(這是發送緩沖區中最早的數據包,也是需要被確認的下一個數據包),但跳過該數據包之后的3個或更多數據包已被確認(通過Selective ACK),則假設該數據包丟失了。類似地,當接收到3個重復的ack時,假設ack_nr + 1已經丟失(如果已經發送了具有該序列號的數據包)。

    這也適用于Selective ACK。在選擇性確認消息中被確認的每個包被計為一個重復的ack,如果它>=3,則在其之后的具有>=3個被確認的數據包都應該被重新發送。

    當數據包丟失時,max_window乘以0.5以模擬TCP。

    超時

    通過落入范圍(last_ack_nr,ack_nr] 或明確地被Selective ACK消息被確認的每個數據包都應該用于更新rtt(往返時間)和rtt_var(rtt方差)測量。這里的 last_ack_nr 是 socket 在當前數據包之前收到的最后一個ack_nr,ack_nr是當前數據包中的字段。

    該 rrt 和 rtt_var 只更新已發送且只發送了一次的數據包。這避免了需要知道是哪個數據包被確認的問題,第一個或第二個數據包。

    每次確認數據包時,rtt 和 rtt_var 都由以下公式計算:

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

    每次更新 rtt 和 rtt_var 時,也會更新與socket關聯的數據包的默認超時 。它被設置為:

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

    其中timeout以毫秒為單位指定。即數據包的最小超時為1/2秒。

    每次socket發送或接收數據包時,它都會更新其timeout計數器。如果從上一次timeout計數器重置開始,在timeout毫秒內沒有數據包到達,則socket觸發超時。它將 packet_size 和 max_window 設置為最小的數據包大小(150字節)。這允許它再發送一個數據包,這就是如果窗口大小降到零,套接字再次啟動的方式。

    初始超時設置為1000毫秒,稍后根據上面的公式進行更新。對于超時的數據包以及后續的每個數據包,超時加倍。

    包大小

    為了盡可能減少對慢速擁塞鏈路的影響,uTP將其數據包大小調整為每個數據包150個字節。使用較小的數據包具有不會阻塞慢速上行鏈路的優點,具有較長的序列化延遲。使用小數據包的成本使得數據包報頭的開銷變得很大。在高速率下,使用大的包大小,慢速率下使用小的包大小。

    擁塞控制

    uTP擁塞控制的總體目標是使用單向緩沖延遲作為主要擁塞測量,丟包也是如此,和TCP類似。關鍵是要避免在發送數據時使用全部的發送緩沖區運行。這對于DSL / Cable調制解調器來說尤其是一個問題,其中調制解調器中的發送緩沖器通常具有多秒數據的空間。uTP(或任何后臺流量協議)的理想緩沖區利用率是以0字節緩沖區利用率運行。即任何其他流量可以在任何時間發送而不受阻礙。實際上,uTP目標延遲設置為100 ms。每個socket的目的是永遠不會在發送鏈路上看到超過100毫秒的延遲,如果有,它會減速。這有效地使uTP流量屈服于任何TCP流量。

    這是通過在uTP發送的每個數據包中包含高精度時間戳來實現的,并且接收端計算其自己的高精度計時器與其接收的數據包中的時間戳之間的差異。然后將該差異反饋給包的原始發送方(timestamp_difference_microseconds)。該值作為絕對值沒有意義。機器中的時鐘很可能不同步,尤其是不低于微秒分辨率,并且數據包在傳輸的時間也包含在這些時間戳的差異中。但是,與以前的timestamp_difference_microseconds值相比,該值很有用。

    每個socket記錄在最后兩分鐘內的滑動最小值。此值稱為base_delay,用作基線,即主機之間的最小延遲。當從每個數據包中的時間戳差異中減去base_delay時,您將獲得socket上當前緩沖延遲的度量。此測量稱為our_delay。它有很多噪音,但用作驅動程序來確定是增加還是減少發送窗口(控制發送速率)。

    CCONTROL_TARGET是UTP接受上行鏈路上的緩沖延遲。目前,延遲目標設置為100毫秒。off_target是實際測量延遲距目標延遲的距離(從CCONTROL_TARGET - our_delay計算得出)。

    socket結構中的窗口大小指定了連接上我們可能在in_flight中(未確認)的字節數。發送速率與此窗口大小直接相關。飛行中的字節越多,發送速率越快。在代碼中,窗口大小稱為 max_window。它的大小大致由以下表達式控制:

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

    第一個因子將off_target縮放到目標延遲的單位。

    然后將scaled_gain添加到max_window:

    max_window += scaled_gain;

    如果off_target大于0,這將使窗口變小,如果off target小于0,則增大窗口。

    如果max_window小于0,則將其設置為0。窗口大小為零意味著socket可能不發送任何數據包。在此狀態下,socekt將觸發超時并將窗口大小強制為一個數據包大小,并發送一個數據包。有關更多信息,請參閱有關超時的部分。

    總結

    以上是生活随笔為你收集整理的uTorrent transport protocol的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。