跳至內容

TCP

出自轻之舟百科

傳輸控制協議

傳輸控制協議
中文名 傳輸控制協議
英文名 Transmission Control Protocol
縮寫 TCP
標準編號 STD 7(RFC 9293)
首次發布 RFC 793(1981年9月)
當前版本 RFC 9293(2022年8月)
端口類型 傳輸層協議,協議號6
主要功能 面向連接的可靠字節流傳輸
關鍵機制 序列號、確認應答、滑動窗口、擁塞控制
設計者 Vint Cerf、Bob Kahn
標準化機構 IETF

傳輸控制協議(Transmission Control Protocol,縮寫TCP) 是TCP/IP協議套件中的核心傳輸層協議,設計用於在不可靠的IP網絡上提供面向連接的、可靠的、有序的字節流傳輸服務[1]。TCP通過序列號機制和累積確認應答實現對丟失或亂序數據段的檢測與重傳,利用滑動窗口協議實施流量控制以防止接收方緩衝區溢出,並內置擁塞控制算法以防止發送方速率過快導致網絡過載[1]。TCP與上層應用之間通過端口號建立復用/解復用通道,使單台主機上的多個應用程序能夠同時維持獨立的TCP連接[1]。TCP具有全雙工特性——每一個TCP連接支持兩條獨立的字節流,分別向兩個方向傳輸數據[1]。自1981年首次標準化以來,TCP歷經數十年的持續演進,在原始規範基礎上增加了多項擴展和改進,是當今互聯網中承載Web瀏覽、電子郵件、文件傳輸、遠程登錄等絕大多數應用流量的基礎協議[1]。2022年8月發布的RFC 9293收集並整合了自RFC 793以來的所有重要修訂,正式取代後者成為TCP的現行標準[1]

歷史

傳輸控制協議的歷史可以追溯到1970年代初期。1973年,Robert Kahn和Vint Cerf開始研究一種能夠在不同分組交換網絡之間互聯的通信協議,起初將其稱為「傳輸控制程序(Transmission Control Program)」[2][3]。該方案需要同時解決分組在網絡中的路由和數據可靠傳輸問題。1974年5月,Cerf和Kahn在IEEE Transactions on Communications上發表了題為「A Protocol for Packet Network Intercommunication」的論文,正式提出了現代TCP/IP的核心設計理念[4]。同年12月,Cerf與Carl Sunshine、Yogen Dalal共同發表了RFC 675,記錄了早期傳輸控制程序的完整規範[3]

隨着互聯網規模的不斷擴大,將通信子網的尋址與路由功能從傳輸功能中分離出來的需求日益迫切。1976年起,研究團隊着手將早期的單一體傳輸控制程序拆分為兩個相互獨立的協議層:IP負責跨網絡的數據包尋址與轉發,TCP負責端到端的可靠數據傳輸[2]。1981年9月,TCP的正式規範RFC 793和IP的正式規範RFC 791同時發布,標誌着現代TCP/IP協議套件的標準化完成[3][4]。1983年1月1日,ARPANET從NCP全面切換到TCP/IP,這一天通常被視為現代互聯網的正式誕生日期。

RFC 793作為TCP的基礎規範沿用了超過四十年。在此期間,IETF陸續發布了數十份RFC文檔對RFC 793進行補充和修訂,包括TCP擁塞控制的引入(RFC 2581,2000年)、選擇性確認機制的提出(RFC 2018,1996年)、顯式擁塞通告的引入(RFC 3168,2001年)等重要改進。2022年8月,IETF發布了RFC 9293,將上述所有零散修訂整合到一份統一的規範文檔中,同時廢止了RFC 793以及更新過RFC 793的RFC 879、2873、6093、6429、6528和6691[1]。RFC 9293被歸類為互聯網標準STD 7,保持了對RFC 793的向後兼容性,並反映了過去數十年間TCP在實際部署中積累的經驗與持續改進[1]

核心服務特徵

TCP為應用層提供了一系列有別於底層IP的服務特徵。

  • 面向連接(Connection-Oriented):在任何數據交換發生之前,通信雙方必須通過三報文握手建立一條邏輯連接,並在數據交換完成後通過連接釋放過程關閉連接[1]
  • 可靠傳輸(Reliable Delivery):TCP使用基於累計確認和超時重傳的自動重傳請求機制,檢測並恢復傳輸中丟失或損壞的數據段,同時利用序列號處理亂序到達的數據包,確保應用層收到的字節流與發送方發出的字節流完全一致且順序正確[1]
  • 字節流服務(Byte-Stream Service):TCP不維護消息邊界的概念,發送端寫入的數據被TCP視為一個連續的字節流,由協議自行決定如何將字節流分割成數據段進行傳輸,接收端的TCP負責將這些數據段重新組裝成原始的連續字節流後交付給應用層[5]
  • 流量控制(Flow Control):TCP使用滑動窗口機制使接收方能向發送方通告自己當前可用的接收緩衝區容量,從而防止發送方以超出接收方處理能力的速率發送數據[5]
  • 擁塞控制(Congestion Control):TCP實施多種擁塞控制算法,主動探測網絡路徑上的可用帶寬並據此調整發送速率,防止過多數據注入網絡導致中間節點出現嚴重擁塞和丟包[5]
  • 全雙工通信(Full-Duplex Communication):每個TCP連接一經建立,即支持雙向數據的同時傳輸,每條方向上的字節流彼此獨立維護各自的序列號和確認號[1]
  • 復用/解復用(Multiplexing/Demultiplexing):TCP利用16位的源端口號和目的端口號,使多台主機上的多個應用程序可以同時維持獨立的TCP連接,而互不干擾[1]

工作機制

協議號

在IP協議棧中,TCP被IANA分配了協議號6,該編號出現在IP數據報頭部的「協議」字段中,用於標識IP載荷中承載的是TCP報文段而非UDP或其他傳輸層協議[6]。該協議號在nmap等工具的協議掃描輸出中列為tcp 6 TCP[7]

端口號與連接標識

TCP使用16位的端口號對上層應用進行標識。IANA將端口號空間劃分為三類:0至1023為系統端口或熟知端口,由IANA統一分配給標準的網絡服務(如HTTP使用80端口,HTTPS使用443端口);1024至49151為用戶端口或註冊端口,可供IANA註冊或自由使用;49152至65535為動態端口或私有端口,通常由操作系統在客戶端建立連接時臨時分配[8]

一個TCP連接由四元組唯一標識:(源IP地址,源端口,目的IP地址,目的端口)。TCP通過該四元組在收發兩端正確地將數據段分發到對應的應用進程[1]

序列號與確認應答

TCP為傳輸字節流中的每一個字節分配一個32位的序列號。發送方的TCP在發送數據段時,會在TCP頭部中攜帶該數據段第一個字節的序列號(Sequence Number)[9]。接收方在收到數據後,回復的ACK報文中攜帶的確認號(Acknowledgment Number)指示接收方期望收到的下一個字節的序列號,從而隱含確認之前所有字節均已正確接收。這種累積確認機制使TCP能夠在不逐個確認每個數據包的情況下高效運行。連接建立階段,雙方各自獨立選擇一個隨機的初始序列號(ISN)作為起始序號[10]

連接建立與釋放

TCP連接通過「三報文握手」(Three-Way Handshake)過程建立。具體步驟如下:首先,主動連接發起方(客戶端)發送SYN報文段(SYN標誌位為1),攜帶客戶端選擇的初始序列號ISN_c[10]。服務器收到後,回復SYN+ACK報文段,在確認客戶端的序列號(ACK號置為ISN_c+1)的同時,攜帶有服務器初始序列號ISN_s。客戶端收到SYN+ACK報文後,回復ACK報文,確認服務器的序列號(ACK號置為ISN_s+1)[10]。至此連接進入ESTABLISHED狀態,雙方可以進行數據通信[11]

TCP連接的釋放採用「四報文揮手」過程。主動關閉方發送FIN報文段,表示己方已無數據需要發送;對端回復ACK確認該FIN,並繼續發送可能尚未發送完畢的數據;當對端也完成數據發送後,發送FIN報文段;最後主動關閉方回復ACK確認該FIN,經過一段時間的等待後完全關閉連接。TCP協議狀態機包含十一種狀態(LISTEN、SYN-SENT、SYN-RECEIVED、ESTABLISHED、FIN-WAIT-1、FIN-WAIT-2、CLOSE-WAIT、LAST-ACK、CLOSING、TIME-WAIT、CLOSED),系統性地描述了一個TCP端點在整個連接生命周期中的行為,並定義了各狀態間的合法遷移路徑[1]

數據可靠傳輸:滑動窗口與流量控制

TCP使用滑動窗口算法提供可靠的、帶流量控制的字節流傳輸服務。滑動窗口協議規定發送方無需等待ACK即可連續發送多個數據段,發送能力上限由兩個因子共同決定:一是接收方通過TCP頭部中的窗口字段(Window)通告的接收窗口(rwnd),反映了接收方的可用緩衝區容量;二是發送方基於擁塞控制算法自行維護的擁塞窗口(cwnd)[5]。發送方實際能發送的未確認數據量不能超過min(rwnd, cwnd)。當發送方持續收到ACK時,窗口向右滑動,允許後續新數據的發送;當檢測到丟包時,窗口收縮並觸發重傳[5]

差控制與校驗和

TCP頭部包含一個16位的校驗和字段,用於檢測TCP報文段(包括TCP頭部和有效載荷數據)在傳輸過程中是否發生損壞。該校驗和的計算涉及一個12字節的偽頭部,偽頭部包含源IP地址、目的IP地址、保留字段(8位0)、協議字段(值為6)以及TCP段長度[12]。偽頭部本身並不隨數據包在網絡上傳輸,只在發送端和接收端本地臨時構造以參與校驗和計算。校驗和為整個報文段提供差錯檢測能力,一旦發現損壞,接收方直接丟棄該報文段,發送方的超時重傳機制將負責重新發送丟失或損壞的數據[1]

緊急數據機制

TCP頭部包含URG標誌位和16位的緊急指針字段,用於支持緊急數據機制。當URG位為1時,緊急指針指示從當前序列號開始的偏移量,標明緊急數據結束的位置。該機制允許發送方在正常字節流中插入標記為緊急的數據,使接收方應用程序能夠在數據流中優先處理該部分內容。由於此機制在實際應用中導致多種交互與實現層面的複雜性,其使用場景已大幅減少,後續標準化工作中已有文檔對該機制的適用性進行了進一步澄清和限制[1]

報文段頭部格式

TCP報文段由TCP頭部和緊隨其後的有效載荷數據組成。TCP頭部最小長度為20字節(不含選項),最大長度可根據選項字段的存在而增至60字節[13]。頭部長度的具體值由數據偏移字段指示,該字段以32位字為單位計量頭部的長度。

TCP頭部的字段結構如下:

  • 源端口(Source Port):16位。標識發送端應用進程使用的端口號。
  • 目的端口(Destination Port):16位。標識接收端應用進程使用的端口號。
  • 序列號(Sequence Number):32位。若SYN標誌位未置位,該字段為當前報文段數據部分第一個字節的序列號;若SYN標誌位置位,該字段為初始序列號(ISN),且實際傳輸的第一個字節的序列號為ISN+1。
  • 確認號(Acknowledgment Number):32位。若ACK標誌位置位,該字段為發送方期望接收的下一個字節的序列號,確認號之前的所有字節均已被正確接收。
  • 數據偏移(Data Offset):4位。以32位字為單位指示TCP頭部的總長度,即頭部包含多少個4字節字。最小值為5(對應20字節),最大值為15(對應60字節)。
  • 保留字段(Reserved):4位。保留供將來使用,在當前的協議規範中必須填充為0。
  • 標誌位(Control Bits):8位(RFC 3168擴展後)。包括如下標誌位(自低位至高位):CWR(擁塞窗口已減少)、ECE(ECN-Echo,顯式擁塞通告回顯)、URG(緊急指針字段有效)、ACK(確認字段有效)、PSH(推送功能)、RST(連接復位)、SYN(同步序列號,用於建立連接)、FIN(發送方不再有數據)。其中PSH標誌位在交互式應用場景中提示協議棧立即交付數據,而非等待緩衝區填滿;RST標誌位用於異常中斷一個連接,如接收到非法報文或服務不可達時觸發。
  • 窗口(Window):16位。表示從確認號開始算起,接收方願意接收的數據字節數。該值用於流量控制。
  • 校驗和(Checksum):16位。用於計算偽頭部、TCP頭部和TCP數據三個部分的16位校驗和。
  • 緊急指針(Urgent Pointer):16位。若URG標誌位置位,該字段指示緊急數據的結束位置與當前序列號之間的偏移量(以字節為單位)。
  • 選項(Options):長度可變,最多40字節。支持多種擴展功能,包括MSS選項、窗口縮放因子選項、時間戳選項、選擇性確認(SACK)選項等。擴展選項使用類型-長度-數值格式(TLV)編碼。
  • 填充(Padding):在必要時填充附加的0值,確保TCP頭部以32位邊界結束,並使數據偏移字段與頭部實際長度一致。

擁塞控制

TCP擁塞控制機制是協議可擴展性的核心,旨在防止多個TCP連接同時發送數據時因注入網絡的數據量超過網絡容量而造成嚴重的丟包和延遲[5]。擁塞控制算法通常在發送端維護擁塞窗口(cwnd),並結合ACK的到達模式來推斷網絡的擁塞狀態。

TCP Tahoe與TCP Reno

TCP Tahoe(以1988年Jacobson在Lawrence Berkeley Laboratory開發的算法為原型)首次引入了現代TCP擁塞控制的核心要素:慢啟動和擁塞避免。Tahoe在檢測到丟包時(通過超時或收到三次重複ACK)將擁塞窗口重置為1個MSS,重新進入慢啟動階段,並將慢啟動閾值(ssthresh)設置為發生丟包時擁塞窗口的一半。TCP Reno在Tahoe的基礎上增加了快速恢復機制:當收到三次重複ACK後,TCP Reno不立即將窗口重置為1,而是將擁塞窗口減半(進入擁塞避免階段),同時將慢啟動閾值設置為擁塞窗口的一半,並利用重複ACK維持傳輸。快速恢復避免了因丟包檢測而將擁塞窗口完全重置的低效率問題[14]

TCP CUBIC

CUBIC是Linux、Windows和macOS等主流操作系統中TCP擁塞控制的默認實現。與Reno的線性窗口增長不同,CUBIC使用三次函數來描述窗口隨時間的增長曲線,在擁塞窗口接近上一次丟包時的窗口值後進入穩定區域,窗口增長較為平緩,在此穩定區域之外則採用更積極的窗口增長策略。CUBIC的窗口增長函數與RTT無關,使其在高帶寬長距離網絡以及存在不同RTT的競爭流時具有更好的擴展性和帶寬利用率[15]

其他擁塞控制算法變體

在CUBIC之外,業界也發展出了多種旨在優化特定網絡場景的TCP擁塞控制變體,包括但不限於:BBR(Google開發的基於瓶頸帶寬和RTT的擁塞控制算法)、NewReno(對Reno算法在恢復機制上的改進和細化)、Westwood+(適用於無線網絡的擁塞控制算法)以及Compound TCP(由微軟開發,在長RTT高帶寬環境中引入延遲敏感組件來改進擁塞窗口增長)。

顯式擁塞通告

顯式擁塞通告是一種支持主動擁塞通知的機制,通過IP頭部中的ECN位與TCP頭部中的ECE和CWR標誌位協同工作。ECN允許路由設備在沒有丟包的情況下提前標記擁塞信號,從而使發送端能夠在不依賴丟包觸發的情況下主動減速。該機制於2001年在RFC 3168中標準化,目前已在主流操作系統的TCP實現中得到廣泛支持。

應用與擴展

時間戳選項

時間戳選項在RFC 7323中定義,為TCP報文段提供兩個32位時間戳字段(發送時間戳和接收時間戳,分別對應於TSval和TSecr)。PAWS機制使TCP能夠區分屬於同一連接不同生命周期的新舊報文段,從而在高速長往返時間網絡環境中有效避免序列號迴繞造成的混亂。同時,時間戳還精確測量RTT,在多個擁塞控制變體中為更準確的RTT估算提供了基礎。

選擇性確認

SACK通過在TCP選項中攜帶一個或多個非連續的序列號範圍塊,使接收方能精確告知發送方哪些數據塊已成功到達、哪些數據塊出現丟失。在不支持SACK的傳統實現中,重傳超時後的發送方只能還原到GBN模型,或在新Reno的擴展中恢復有限數據塊;SACK使發送方無需盲目重傳即可確定丟失邊界,只重傳真正丟失的段而非整個窗口,顯著提升了丟包恢復效率和吞吐量[1]

窗口縮放選項

該選項將TCP窗口的最大大小從基礎RFC 793中的65535字節擴展至約1GB。在長時延長距離網絡中,標稱窗口在未縮放時因BDP較大而限制帶寬利用,窗口縮放通過將通告窗口字段與該選項中約定的移位因子結合,使接收方可以在不改動原始協議的前提下大幅提升通告窗口的容量上限。

常見應用

TCP在數據完整性要求嚴格而時延容忍度相對寬鬆的場景中占據主導地位,其服務模型掩蓋了丟包、亂序、重傳和擁塞等底層網絡的複雜性。絕大多數現代網絡應用依賴TCP作為其傳輸協議:HTTP/1.x、HTTP/2及HTTP/3儘管QUIC使用了UDP和類似可靠性層,但web傳統流量中的大部分仍運行於TCP之上;SMTP及IMAP/POP3郵件傳輸與收取;FTP數據與命令通道;SSH安全遠程登錄;Telnet早期遠程登錄;數據庫客戶端/服務器遠程交互等。

安全

TCP在設計之初優先考慮了數據可靠傳輸和流量/擁塞控制問題,安全並非首要設計目標。因此,TCP面臨多種已知的安全威脅,包括TCP序列號預測攻擊(1985年羅伯特·莫里斯最早描述)、會話劫持和連接復位攻擊等。由於TCP頭部校驗和覆蓋了IP偽頭部部分信息,該校驗和可以在一定程度上幫助接收端驗證IP地址合法性,但並不提供對加密性的保證。在實際部署中,傳輸層安全協議(TLS)通常工作在TCP之上,通過在TCP字節流中插入加密/認證握手和加密數據幀,為上層應用提供通信的機密性、數據完整性及端到端身份認證能力。RFC 9293中提及早期TCP校驗和依賴於偽頭部中的IP源和目標地址進行校驗,以維護TCP的端到端屬性,但該設計也帶來了一些對IP變化的不適應性。現代TCP安全主要依賴上層加密隧道和網絡基礎設施中的通用安全機制,而非協議本身的內建安全特徵。

實現

主流操作系統的內核協議棧中都包含TCP的完整實現。Linux內核的TCP/IP協議棧版本持續演進,長期支持Reno、CUBIC、BBR等多種擁塞控制算法並通過sysctl接口允許用戶動態切換;微軟Windows中的TCP/IP協議棧從Windows Vista和Windows Server 2008開始引入CTCP等多種改進,自Windows 10及Windows Server 2019起默認啟用了基於類似CUBIC的擁塞控制和現代流量/擁塞窗口參數等調優;Apple的macOS和iOS則基於BSD協議棧的XNU內核TCP/IP實現,並同樣將CUBIC作為默認擁塞控制算法;除上述完整內核實現外,學術界和嵌入式軟件生態中還存在多個簡約或形式驗證驅動的TCP實現,例如LwIP、μC/TCP-IP以及經過高階邏輯證明的TCP/HOL4實現等。

參考文獻