轉自:http://www.cnblogs.com/kzloser/articles/2582957.html
首部格式
圖釋:

各個段位說明:
- 源端口和目的端口: 各占 2 字節.端口是傳輸層與應用層的服務接口.傳輸層的復用和分用功能都要通過端口才能實現
- 序號: 占 4 字節.TCP 連接中傳送的數據流中的每一個字節都編上一個序號.序號字段的值則指的是本報文段所發送的數據的第一個字節的序號
- 確認號: 占 4 字節,是期望收到對方的下一個報文段的數據的第一個字節的序號
- 數據偏移/首部長度: 占 4 位,它指出 TCP 報文段的數據起始處距離 TCP 報文段的起始處有多遠.“數據偏移”的單位是 32 位字(以 4 字節為計算單位)
- 保留: 占 6 位,保留為今后使用,但目前應置為 0
- 緊急URG: 當 URG=1 時,表明緊急指針字段有效.它告訴系統此報文段中有緊急數據,應盡快傳送(相當於高優先級的數據)
- 確認ACK: 只有當 ACK=1 時確認號字段才有效.當 ACK=0 時,確認號無效
- PSH(PuSH): 接收 TCP 收到 PSH = 1 的報文段,就盡快地交付接收應用進程,而不再等到整個緩存都填滿了后再向上交付
- RST (ReSeT): 當 RST=1 時,表明 TCP 連接中出現嚴重差錯(如由於主機崩潰或其他原因),必須釋放連接,然后再重新建立運輸連接
- 同步 SYN: 同步 SYN = 1 表示這是一個連接請求或連接接受報文
- 終止 FIN: 用來釋放一個連接.FIN=1 表明此報文段的發送端的數據已發送完畢,並要求釋放運輸連接
- 檢驗和: 占 2 字節.檢驗和字段檢驗的范圍包括首部和數據這兩部分.在計算檢驗和時,要在 TCP 報文段的前面加上 12 字節的偽首部
- 緊急指針: 占 16 位,指出在本報文段中緊急數據共有多少個字節(緊急數據放在本報文段數據的最前面)
- 選項: 長度可變.TCP 最初只規定了一種選項,即最大報文段長度 MSS.MSS 告訴對方 TCP:“我的緩存所能接收的報文段的數據字段的最大長度是 MSS 個字節.” [MSS(Maximum Segment Size)是 TCP 報文段中的數據字段的最大長度.數據字段加上 TCP 首部才等於整個的 TCP 報文段]
- 填充: 這是為了使整個首部長度是 4 字節的整數倍
- 其他選項:
- 窗口擴大: 占 3 字節,其中有一個字節表示移位值 S.新的窗口值等於TCP 首部中的窗口位數增大到(16 + S),相當於把窗口值向左移動 S 位后獲得實際的窗口大小
- 時間戳: 占10 字節,其中最主要的字段時間戳值字段(4字節)和時間戳回送回答字段(4字節)
- 選擇確認: 接收方收到了和前面的字節流不連續的兩2字節.如果這些字節的序號都在接收窗口之內,那么接收方就先收下這些數據,但要把這些信息准確地告訴發送方,使發送方不要再重復發送這些已收到的數據
數據單位
TCP 傳送的數據單位協議是 TCP 報文段(segment)
特點
TCP 是面向連接的傳輸層協議 每一條 TCP 連接只能有兩個端點(endpoint),每一條 TCP 連接只能是點對點的(一對一) TCP 提供可靠交付的服務 TCP 提供全雙工通信 面向字節流
注意
TCP 對應用進程一次把多長的報文發送到TCP 的緩存中是不關心的 TCP 根據對方給出的窗口值和當前網絡擁塞的程度來決定一個報文段應包含多少個字節(UDP 發送的報文長度是應用進程給出的) TCP 可把太長的數據塊划分短一些再傳送.TCP 也可等待積累有足夠多的字節后再構成報文段發送出去 每一條 TCP 連接有兩個端點 TCP 連接的端點不是主機,不是主機的IP 地址,不是應用進程,也不是傳輸層的協議端口.TCP 連接的端點叫做套接字(socket)或插口
自動重傳請求ARQ
定義:
可靠傳輸協議常稱為自動重傳請求ARQ (Automatic Repeat reQuest)
累積確認:
- 定義: 接收方一般采用累積確認的方式.即不必對收到的分組逐個發送確認,而是對按序到達的最后一個分組發送確認,這樣就表示:到這個分組為止的所有分組都已正確收到了
- 優點: 容易實現,即使確認丟失也不必重傳
- 缺點: 不能向發送方反映出接收方已經正確收到的所有分組的信息
Go-back-N(回退N):
如果發送方發送了前 5 個分組,而中間的第 3 個分組丟失了.這時接收方只能對前兩個分組發出確認.發送方無法知道后面三個分組的下落,而只好把后面的三個分組都再重傳一次
具體實現
說明:
- TCP 連接的每一端都必須設有兩個窗口 一個發送窗口和一個接收窗口
- TCP 可靠傳輸機制用字節的序號進行控制.TCP 所有的確認都是基於序號而不是基於報文段
- TCP 兩端的四個窗口經常處於動態變化之中
- TCP連接的往返時間 RTT 也不是固定不變的.需要使用特定的算法估算較為合理的重傳時間
圖釋:

發送緩存
發送緩存用來暫時存放:
- 發送應用程序傳送給發送方 TCP 准備發送的數據
- TCP 已發送出但尚未收到確認的數據
圖釋:

接收緩存
接收緩存用來暫時存放:
- 按序到達的、但尚未被接收應用程序讀取的數據;
- 不按序到達的數據
圖釋:

滑動窗口
圖釋:

特點:
- 以字節為單位的滑動窗口
- A 的發送窗口並不總是和 B 的接收窗口一樣大(因為有一定的時間滯后)
要求:
- TCP 標准沒有規定對不按序到達的數據應如何處理.通常是先臨時存放在接收窗口中,等到字節流中所缺少的字節收到后,再按序交付上層的應用進程
- TCP 要求接收方必須有累積確認的功能,這樣可以減小傳輸開銷
具體實現:




確認丟失和確認遲到

超時重傳時間選擇
具體實現:
TCP 每發送一個報文段,就對這個報文段設置一次計時器.只要計時器設置的重傳時間到但還沒有收到確認,就要重傳這一報文段
加權平均往返時間:
做法:
TCP 保留了 RTT 的一個加權平均往返時間 RTTS(這又稱為平滑的往返時間),第一次測量到 RTT 樣本時,RTTS 值就取為所測量到的 RTT 樣本值.以后每測量到一個新的 RTT 樣本,就按下式重新計算一次 RTTS:
公式:
新的 RTTS = ( 1 - α)×(舊的 RTTS)+α(新的 RTT 樣本)
說明:
式中,0 ≤ α< 1.若α很接近於零,表示 RTT 值更新較慢若選擇 α 接近於1,則表示 RTT 值更新較快 RFC 2988 推薦的 α 值為 1/8,即 0.125
超時重傳時間RTO:
RTO 應略大於上面得出的加權平均往返時間 RTTS. RFC 2988 建議使用下式計算 RTO:
RTO=RTTS + 4×RTTD
RTTD 是 RTT 的偏差的加權平均值 RFC 2988 建議這樣計算 RTTD.第一次測量時,RTTD 值取為測量到的 RTT 樣本值的一半.在以后的測量中,則使用下式計算加權平均的 RTTD:
新的 RTTD = (1-β)×(舊的RTTD)+β×|RTTS﹣新的 RTT 樣本|
β是個小於 1 的系數,其推薦值是 1/4,即 0.25 在計算平均往返時間 RTT 時,只要報文段重傳了,就不采用其往返時間樣本
修正的Karn算法:
報文段每重傳一次,就把 RTO 增大一些:
新的 RTO= γ×(舊的 RTO)
系數γ 的典型值是 2 當不再發生報文段的重傳時,才根據報文段的往返時延更新平均往返時延 RTT 和超時重傳時間 RTO 的數值
持續計時器
- TCP 為每一個連接設有一個持續計時器
- 只要 TCP 連接的一方收到對方的零窗口通知,就啟動持續計時器
- 若持續計時器設置的時間到期,就發送一個零窗口探測報文段(僅攜帶 1 字節的數據),而對方就在確認這個探測報文段時給出了現在的窗口值
- 若窗口仍然是零,則收到這個報文段的一方就重新設置持續計時器
- 若窗口不是零,則死鎖的僵局就可以打破了
報文段的發送時機
TCP 維持一個變量,它等於最大報文段長度 MSS.只要緩存中存放的數據達到 MSS 字節時,就組裝成一個 TCP 報文段發送出去 由發送方的應用進程指明要求發送報文段,即 TCP 支持的推送(push)操作 發送方的一個計時器期限到了,這時就把當前已有的緩存數據裝入報文段(但長度不能超過 MSS)發送出去
運輸連接
三個階段:
- 連接建立:
- 圖釋:

-
- 步驟:
- A 的 TCP 向 B 發出連接請求報文段,其首部中的同步位 SYN = 1,並選擇序號 seq = x,表明傳送數據時的第一個數據字節的序號是 x
- B 的 TCP 收到連接請求報文段后,如同意,則發回確認(B 在確認報文段中應使 SYN = 1,使 ACK = 1,其確認號ack = x﹢1,自己選擇的序號 seq = y)
- A 收到此報文段后向 B 給出確認,其 ACK = 1,確認號 ack = y﹢1(A 的 TCP 通知上層應用進程,連接已經建立,B 的 TCP 收到主機 A 的確認后,也通知其上層應用進程:TCP 連接已經建立)
- 步驟:
- 數據傳送
- 連接釋放:
- 圖釋:

-
- 步驟:
- 數據傳輸結束后,通信的雙方都可釋放連接.現在 A 的應用進程先向其 TCP 發出連接釋放報文段,並停止再發送數據,主動關閉 TCP 連接(A 把連接釋放報文段首部的 FIN = 1,其序號seq = u,等待 B 的確認)
- B 發出確認,確認號 ack = u+1,而這個報文段自己的序號 seq = v(TCP 服務器進程通知高層應用進程.從 A 到 B 這個方向的連接就釋放了,TCP 連接處於半關閉狀態.B 若發送數據,A 仍要接收)
- 若 B 已經沒有要向 A 發送的數據,其應用進程就通知 TCP 釋放連接
- A 收到連接釋放報文段后,必須發出確認,在確認報文段中 ACK = 1,確認號 ack=w﹢1,自己的序號 seq = u + 1
- 注意:
- 步驟:
TCP 連接必須經過時間 2MSL 后才真正釋放掉(2MSL 的時間的用意 --- 為了保證 A 發送的最后一個 ACK 報文段能夠到達 B.防止 “已失效的連接請求報文段”出現在本連接中.A 在發送完最后一個 ACK 報文段后,再經過時間 2MSL,就可以使本連接持續的時間內所產生的所有報文段,都從網絡中消失.這樣就可以使下一個新的連接中不會出現這種舊的連接請求報文段)
-
- 發現丟失確認時候的處理:

三個問題:
- 要使每一方能夠確知對方的存在
- 要允許雙方協商一些參數(如最大報文段長度,最大窗口大小,服務質量等)
- 能夠對運輸實體資源(如緩存大小,連接表中的項目等)進行分配
發送TCP請求客戶端

擁塞處理相關概念
擁塞窗口:
含義:
擁塞窗口的大小取決於網絡的擁塞程度,並且動態地在變化.發送方讓自己的發送窗口等於擁塞窗口.如再考慮到接收方的接收能力,則發送窗口還可能小於擁塞窗口
發送方控制擁塞窗口的原則:
只要網絡沒有出現擁塞,擁塞窗口就再增大一些,以便把更多的分組發送出去.但只要網絡出現擁塞,擁塞窗口就減小一些,以減少注入到網絡中的分組數
乘法減小:
是指不論在慢開始階段還是擁塞避免階段,只要出現一次超時(即出現一次網絡擁塞),就把慢開始門限值 ssthresh 設置為當前的擁塞窗口值乘以 0.5
加法增大:
是指執行擁塞避免算法后,在收到對所有報文段的確認后(即經過一個往返時間),就把擁塞窗口 cwnd增加一個 MSS 大小,使擁塞窗口緩慢增大,以防止網絡過早出現擁塞
快重傳:
快重傳算法首先要求接收方每收到一個失序的報文段后就立即發出重復確認.這樣做可以讓發送方及早知道有報文段沒有到達接收方,發送方只要一連收到三個重復確認就應當立即重傳對方尚未收到的報文段

快恢復:
當發送端收到連續三個重復的確認時,就執行“乘法減小”算法,把慢開始門限 ssthresh 減半.但接下去不執行慢開始算法
發送窗口的上限值:
發送方的發送窗口的上限值應當取為接收方窗口 rwnd 和擁塞窗口 cwnd 這兩個變量中較小的一個,即應按以下公式確定: 發送窗口的上限值 Min [rwnd, cwnd]
-
- 當 rwnd < cwnd 時,是接收方的接收能力限制發送窗口的最大值
- 當 cwnd < rwnd 時,則是網絡的擁塞限制發送窗口的最大值
避免擁塞具體實現
慢開始算法:
- 在主機剛剛開始發送報文段時可先設置擁塞窗口 cwnd = 1,即設置為一個最大報文段 MSS 的數值
- 在每收到一個對新的報文段的確認后,將擁塞窗口加 1,即增加一個 MSS 的數值
- 使用慢開始算法后,每經過一個傳輸輪次(往返時間 RTT),擁塞窗口 cwnd 就加倍
擁塞避免算法:
擁塞窗口 cwnd 緩慢地增大,即每經過一個往返時間 RTT 就把發送方的擁塞窗口 cwnd 加 1,使擁塞窗口 cwnd 按線性規律緩慢增長
慢開始門限 ssthresh 的用法:
- 當 cwnd < ssthresh 時,使用慢開始算法
- 當 cwnd > ssthresh 時,停止使用慢開始算法而改用擁塞避免算法
- 當 cwnd = ssthresh 時,既可使用慢開始算法,也可使用擁塞避免算法
網絡出現擁塞時(其根據就是沒有按時收到確認):
- 就要把慢開始門限 ssthresh 設置為出現擁塞時的發送方窗口值的一半(但不能小於2)
- 然后把擁塞窗口 cwnd 重新設置為 1.執行慢開始算法
TCP 的有限狀態機
說明:
- TCP 有限狀態機的圖中每一個方框都是 TCP 可能具有的狀態
- 每個方框中的大寫英文字符串是 TCP 標准所使用的 TCP 連接狀態名.狀態之間的箭頭表示可能發生的狀態變遷
- 箭頭旁邊的字,表明引起這種變遷的原因,或表明發生狀態變遷后又出現什么動作
- 圖中有三種不同的箭頭
- 粗實線箭頭表示對客戶進程的正常變遷
- 粗虛線箭頭表示對服務器進程的正常變遷
- 另一種細線箭頭表示異常變遷

