-
TCP協議最主要的特點
- TCP是面向連接的運輸層協議。這就是說,應用程序在使用TCP協議之前,必須要建立TCP連接,且在傳輸完畢后,還要斷開連接。
- 每一條TCP連接只能有兩個端點,每一條TCP連接只能是點對點(一對一),並且按序到達。
- TCP提供全雙工通信。TCP允許通信雙方的應用進程可以在任何時候都能發送時數據。TCP連接的兩端都設有發送緩存和接收緩存,用來臨時存放雙向通信的數據。在發送的時候,應用進程把數據傳送給TCP緩存后,就可以做自己的事情,而TCP會在合適的時候把數據發送出去。在接受時,TCP把接受到的數據放入緩存,上層的應用進程會在合適的時候讀取緩存中的數據。
- 面向字節流,TCP中的”流“指的是流入到進程或者從進程流出的字節序列。”面向字節流“的含義是:雖然應用進程和TCP交互是一次一個數據塊(大小不等),但TCP把應用程序交下來的數據僅僅看成一連串的”無結構的字節流“。TCP並不知道所傳送的字節流的含義。
- 如圖TCP連接是一條虛連接:並不是真正的物理連接。TCP報文段先要傳送到IP層,加上IP首部,再傳送到數據鏈路層。再加上數據鏈路層的首部和尾部,才離開主機發送到物聯鏈路。

-
TCP的連接
TCP把連接作為最基本的抽象,TCP許多的特性都與TCP面向連接相關。每一條TCP連接有兩個端點,TCP連接的端點,不是主機,不是主機IP,不是應用進程,也不是運輸層的協議端口,而是叫做套接字(socket)或者插口,根據RFC793規定:端口號拼接到IP地址即構成了套接字==》套接字socket=(IP地址:port端口號)。
每一條TCP連接唯一地址通信的兩端(及兩個套接字所規定):
TCP連接::={socket1,socket2}={(IP1:Port1),(IP2:Port2)}
-
可靠傳輸的工作原理
我們知道,TCP發送報文的時候是交給IP層,但是IP層只能提供盡最大努力服務,也就是說,TCP下面的網絡層提供的是不可靠傳輸,因此TCP就必須采取適當的措施要使得兩個運輸層之間通信變得可靠。
理想的傳輸條件有以下兩個特點:
1. 傳輸信道不產生差錯。 2. 不管發送方以多塊的數據發送數據,接受方總能及時的來處理這些數據。然而實際的網絡並不具備以上兩個理想條件,但我們可以采用一些可靠傳輸協議,當出現差錯的時候讓發送方重傳發送錯誤的數據,同時在接收方來不及處理的時候及時報告發送方適當降低發送數據的速度。這樣一i來,本來不可靠的傳輸信道就能夠實現可靠傳輸了。下面從最簡單的停止等待協議說起。
-
停止等待下協議
全雙工通信的雙方既是發送方也是接收方,下面是我們僅考慮A發送數據而B接收數據並發送確認。因此A叫做發送方,B叫做接收方。
- 無差錯情況

- A發送分組M1,發送完就暫停發送,等待B的確認。B接收到M1就向就向A發送確認。A在接收到對M1確認的后,就再發送下一個分組M2。一次類推。
- 出現差錯
- B接收到M1時檢測到了差錯,就丟棄M1,其他什么也不做(並不會通知A收到有差錯的分組)。也可能是M1在傳輸的過程中丟失了,這時候B當然什么也不知道。在這兩種情況下,B都不會發送任何信息。可靠傳輸協議是這樣設計的:A只要超過了一段時間仍然沒有接收到確認,就認為剛才發送的分組丟失了,因而重傳錢前面發送過的分。這就叫做‘重傳’。要實現如何重傳,就要在每發完一份分組,就設置一個超時計時器,如果在規定的時間內收到對方的確認,就撤銷已設置的超時計時器

其實在圖5-10(a)中,A為每一個已發送的分組都設置了一個超時計時器,但A在超時計時器之前都收到了相應的確認,就撤銷該超時計時器。這里應該注意三點:
- A在發送完一個分組后,還必須要保留一個已經發送分組的副本(在發送重傳的時候使用),只有在接收到相應的確認后才能清楚暫時保留分分組副本。
- 分組和確認分組就必須要進行編號,這樣才能明確是哪一個發送出去的分組收到了確認,而哪一個分組還沒有收到確認。
- 超時計時器設置的重傳時間應該比數據在分組傳輸的平均往返時間要長一些,如圖5-9(b)中的一條虛線標識如果如果M1正到達B處同時A也正確的收到確認報文的過程,可見重傳時間也應該比平均往返時間更長一些,顯然,如果重傳時間設定特別的長,那么通信的效率就會很低,但如果重傳的設置的太短,以致產生不必要的重傳,就浪費了網絡資源。關於重傳時間如何處理和選擇,我們會在后面討論。
- 確認丟失和確認遲到:圖5-10(a)說明的是另一種情況,B發送的對M1分組確認丟失了,A在設定的超時重傳時間內沒有收到確認,並無法知道是自己發出的分組錯誤,丟失,還是B發送的確認丟失了。因此A在超時計時器到后期就要重傳M1分組。現在應該注意到B的動作。假如B接收到了重傳的分組M1,這時候應該采取兩個行動:
- 丟棄這個重復的分組M1,不向上層交付。
- 向A發送確認,就算是重傳報文M1,也要發送確認報文。
通常情況下A最終總是能可以收到所有發出分組確認,如果A不斷重傳分組但總是收不到確認,說明這條通信線路太差了,不能進行通信。
使用上述的確認和重傳機制,我們就可以在不可靠的傳輸網絡上實現可靠的通信。
像上述的這種可靠傳輸協議稱之為自動重傳請求ARQ(Automatic Respeat ReQuest),意思是重傳的請求是自動進行的,接收方不需要請求發送方重傳某個出錯的分組。
-
信道利用率
停止等待的協議優點是簡單,但缺點是信道利用率太低了,我么可以用圖5-11來說明這個問題

假定A發送分組需要的時間是TD。顯然,TD等於分組長度除以數據率。再假定分組確認到達B后,B處理分組的時間可以忽略不計,同時立即發送一個確認。假定B發送一個確認分組需要時間為TA,如果A確認處理分組的時間也忽略不計,那么A在經過時間(TD+RTT+TA)后就可以在發送下一個分組,RTT是往返時間,因此信道的利用率U=TD/(TD+RTT+TA).
舉個例子,假定1200km 的信道往返時間為RTT=20ms。分組長度為1200bit,發送速率為1M/S,則可以計算出信道利用率U=5.66%,若把發送速率提高到10B/S,則U=5.96X10^-4,信道在大多數時間都是空閑的。
因此,為了提高傳輸效率,發送方可以不使用低效率的停止等待協議,而是采用流水線傳輸,(如圖5-12)

流水線傳輸就是發送方可以連續發送多個分組,不必沒發完一個分組就停止等待對迪阿敏確認,這樣可以使信道上的一直有數據不間斷的發送,顯然這種傳輸效率可以得到很大的提高。
當使用流水線傳輸時候,就要介紹下面要使用的連接ARQ協議,滑動窗口協議
-
連續ARQ協議
滑動窗口協議比較復雜,是TCP協議的精髓所在,

圖5-13(a)表示發送方維持的發送窗口,它的意義是:位於發送窗口內的5個分組都可以連續發出去,而不需要等待對方確認,這樣,信道的利用率就高了。
連續ARQ協議規定,發送方每收到一個確認,就把發送窗口向前滑動一個分組的位置。圖5-13(b)表示發送方接收到了對第一個分組的確認,於是把發送窗口向前移動一個分組的位置。
接收方一般采用的是累計確認的方式。這就是說,接收方不必對接收到的分組逐個發送確認。而是收到幾個分組后,對按照順序到達最后一個分組發送確認,這就表明:到這個分組為止的所有分組都正確的收到了。
TCP報文段的首部格式
TCP雖然是面向字節流的,但TCP傳送的數據單元卻是報文段。一個TCP報文段分為首部和數據兩部分,而TCP的全部功能都體現在它在首部中各字段的作用。
TCP報文首部前20字節是固定的,后面4n字節是根據需要而增加的選項。(TCP協議首部的最小長度為20字節)
- 源端口和目的端口 (各占2字節):分別寫入源端口號和目的端口號。
- 序號(4字節):序號的范圍是【0,(232)-1】,共232個序號,在一個TCP連接中傳送的字節流的每一個字節按照順序編號,這個字節也叫做報文段序號。
- 確認號(4字節):是期望收到對方的下一個報文段的第一個數據字節的序號,例如:B正確的接收到了A發送過來的一個報文段,其序列號字段為501,而數據長度是200字節(序號為501-700),這表明B正確的接收到了A發送的到序號700為止的數據,。因此,B希望收到A下一個數據序號為701的數據,於是A在A發送給A確認號設置為701。總之就是要記住:確認號=N:到序號N-1為止的所有數據都已正常的收到了。
- 數據偏移(4位):它指出的TCP報文段的數據部分的其實部分距離TCP報文段的起始位置,其實就是指出了TCP報文段首部的長度,(TCP報文首部最大的長度為60字節)。
- 保留位(6位):保留為今后使用,目前是0。
- 下面是6個控制位
- 緊急URG(URGent):當URG=1,表示緊急指針字段有效,它告訴系統此報文段中有緊急數據,應該盡快送達,不要按照原來的排隊順序來傳送,發送方TCP就要把這個緊急報文插入到本報文隊列中的首部。
- 確認ACK(ACKnowledment)僅當ACK=1時候確認號字段才有效,當ACK=0時候,確認號無效。TCP規定,在連接建立后,所有傳送的報文段都必須把ACK設置為1
- 推送PSH(PuSH)當兩個應用進程進行交互式的通信的時候,有時在一端的應用進程希望在鍵入一個命令后能夠立即接受到對方的響應。在這種情況下,TCP就可以使用推送操作。當發送方把PDSH設置為1,並立即創建一個報文段發送出去,接收方TCP收到PSH=1的報文的時候,會把這個報文盡快 的交給付給應用進程。而並不是放到緩存中。
- 復位RST(ReSet):當RST=1時候,表明TCP連接中出現了嚴重的差錯,必須要釋放連接,然后重新建立運輸連接,RST=1還用來拒絕一個非法的報文段或者拒絕打開一個鏈接。
- 同步SYN(SYNchronization)在建立一個用來同步序號,當SYN=1而ACK=0,表明這是一個連接請求報文段,對方若同意建立連接,則應該在相應的報文段中使得SYV=1和ACK=1
- 終止FIN(FINis)用來釋放一個連接,當FIN=1時,表示此報文段的發送方發送的數據已經發送完畢,並要求釋放運輸層連接。
- 窗口(2字節):窗口值為【0,(2^16)-1】,窗口指的是發送本報文的一方的接收窗口。窗口值告訴對方:從本報文段的確認號開始,接收方目前只能接受對方的數據報文發送量。設置這個窗口值的原因是接收方的數據接收緩存是有限的。
- 檢驗和(2字節):檢驗和字段檢驗的范圍包括首部和數據兩部分。和UDP一樣,在計算檢驗和時,要在TCP報文段的前面加上12字節的偽首部,偽首部的格式和UDP偽首部的格式一樣。但應該要把偽首部的第四個字段值改為6(TCP的協議號為6),第5字段中UDP長度改為TCP長度。
- 緊急指針(2字節):緊急指針僅僅在URG=1的時候才有意義,它指出本報文段的緊急數據的字節數(緊急數據結束后就是普通數據),窗口期為0也是可以發送緊急數據。
- 選項(可變,最長為40字節)
TCP可靠傳輸的實現
- 以字節為單位的滑動窗口
TCP的滑動窗口是以字節為單位的,現假定A收到了B發來的確認報文段,其中窗口是20字節,而確認號是31(這表明B期望接收到的下一個序列號為31,而序號30為止的數據已經接收到了),根據這兩個數據,A就構造出了自己的發送窗口。
我們首先討論發送發A的發送窗口,發送窗口表示:在沒有收到B確認的情況下,A可以連續的把窗口內的數據都發送出去。凡是已經發送出去的數據,在未收到確認之前都必須暫時保留,以便在重傳時使用。
發送窗口里面的序號表示允許發送的序號,顯然,窗口越大,發送方就可以在收到對方確認之前發送的數據就越多,因此就可以提高傳輸速率。
發送窗口后延部分表示已經已經發送且收到了確認。這些數據顯然不在需要保留了,發送窗口前沿的部分表示不允許發送,因為接收方還沒有為這部分數據提供緩存空間。
發送窗口的位置由窗口前沿和后延位置共同確認,
- TCP緩存和窗口的關系
發送方的應用進程把字節流寫入了TCP的發送緩存中,接收方的應用進程從TCP的接收緩存中讀取字節流數據。下面我們就討論窗口和緩存之間的關系:
這里首先明確兩點:
- 緩存空間和序號空間都是有限的,並且是循環使用的。
- 由於實際的緩存或窗口中的字節數是非常大的。圖中只是說明一下情況。
我們首先查看一下(a)發送方的情況:
- 發送緩存用來暫時存放:
- 發送應用程序傳給發送方TCP准備發送的數據。
- TCP已發出但尚未收到確認的數據。
- 發送窗口只是發送緩存的一部分,已被確認的數據應當從緩存中被刪除。因此發送緩存和發送窗口的后延是重合的。發送應用程序最后寫入發送緩存的字節減去最后被確認的字節,就是還保留在發送傳中的被寫入的字節數。發送應用進程必須控制寫入緩存中的速度。不能太快,否則發送緩存就沒有存放數據的空間。
再看一下圖(b)接收方的情況。
- 節后緩存暫時用來存放:
- 按序到達,但尚未被應用進程接讀取的數據。
- 為按序到達的數據。
- 如果收到的分組有差錯,則要丟棄 。如果接受應用進程來不及讀取收到的數據,接收緩存中就會被填滿,使得減少到0。反之,如果接受應用程序接收到數據能夠及時從接受緩存中讀取到數據,接收窗口就可以不斷增大,但最大就不能超過接收緩存的大小。圖(b)還指出了下一個期待收到的字節號,這個字節號也是接收方給發送方的報文段中的首部確認號。
根據以上總結出:
- 雖然A的發送窗口是根據B接受窗口的大小而動態設置的,但是在同一時刻,A發送窗口和B的接受窗口並不是一樣大的。這是因為通過網絡傳輸需要經歷一定的時間滯后(延遲),除此之外,發送方還要根據當時的網絡環境要適當的調整自己的發送窗口。
- 對於不按序到達的數據(字節流),TCP標准並無明確規定,如果接受方把不按序的數據一律丟掉,那么接收窗口的管理就會簡單很多,但是這回對網絡資源的利用不利(因為發送方會不斷的傳送較多的數據)。因此TCP通常會把不按序到達的數據先臨時放到存儲窗口中,等到字節流所缺少的字節接收到后,再按序交付上層的應用進程。
- TCP要求接收方必須有積累確認的功能,這樣可以減少傳輸開銷,接收方可以在合適的時候發送確認,也可以在自己有數據要發送時把確認信息捎上。但是這里注意:
- 一十接收方不應該過分推遲發送確認,否則這樣容易導致發送方不必要的重傳,這樣反而浪費了網絡資源。TCP規定,確認推遲的時間不能超過0.5秒,若收到了一連串具有最大長度的報文,則必須每隔一個報文段就發送一個確認【RFC 1122】.
- 二是捎帶確認實際上並不是經常發生,因為大多數應用很少同時在兩個方向上傳輸數據。
- 最后強調:TCP通信是全雙工通信。通信中的每一方都在發送和接受報文段,因此,每一方都有自己的發送窗口和接收窗口。在談到這些窗口的時候,一定要分清楚。



