上章計算機網絡的學習整理中整理了Http協議的內容,今天的文章中整理一下tcp協議。html
文章中部分圖片來自於網絡,侵刪算法
首先介紹一下tcp協議, tcp一種可靠的,面向鏈接的服務,它爲端與端之間的進程通訊提供了可靠的數據傳輸功能,經過流量控制,序號,確認和定時器等功能,tcp可以講數據按序正確的從原進程傳遞到目標進程中。緩存
多路複用以及多路分解是由網絡層提供的主機到主機交付服務延伸到爲運行在主機上的應用程序提供進程到進程的交付服務。一個進程(做爲網絡應用的一部分)有一個或多個套接字(socket),它至關於從網絡向進程傳遞數據和從進程向網絡傳遞數據的門戶。將運輸層報文段中的數據交付到正確的套接字的工做稱爲多路分解(demultiplexing)。而在源主機中從不一樣套接字中收集數據塊,併爲每一個數據塊封裝上首部信息從而生成報文段,而後將報文段傳遞到網絡層,全部這些工做稱爲多路複用(multiplexing)。服務器
從上面概念來看,多路複用以及多路分解就是一個對稱關係的概念。接下來看下多路複用以及多路分解在傳輸層封裝的報文段中的表現:網絡
咱們在開發時候都知道TCP是一個可靠的傳輸協議,那麼爲何是可靠的呢?這個可能不少人並不瞭解。首先咱們來試想一想看可能會發生的問題:併發
這些問題在數據傳輸中確定時會遇到的,那麼該怎麼解決這些問題呢?socket
首先看看第一個問題,發生情境多是底層物理部件時候發生問題,致使了分組數據中有概率使一個比特數據從0變成了1。如何處理呢?在《計算機網絡-自頂向下》中舉了一個情景,我以爲挺好:在打電話中,咱們在正常狀況就正常對話就能夠了,若是對方忽然說話聲音聽不清了,那麼咱們就會讓他重複一下上次說的話。那麼在第一種問題情境中,咱們也可使用這種方式來處理,這種基於重傳的可靠數據傳輸協議叫自動重傳請求協議(ARQ)。tcp
在ARQ中包含三種方式處理比特差錯的狀況:性能
這三種方式是按序發生的,當發送方發出數據的時候,接收方在接收到的同事進行差錯檢測,若是出現問題,那麼接收方在答覆的時候,在數據中帶上NAK,反之帶上ACK。發送方在拿到響應數據的時候,若是收到NAK時候,則進行重傳。這裏還得考慮一個問題,萬一接收方的反饋也被物理部件影響返回徹底錯誤的結果了怎麼辦呢?既然發生了,那麼咱們重發一次分組不就行了麼,不是ACK的答覆,都按照NAK來處理,其實不就處理好了麼?經過這種方式是能解決問題,可是可能會形成一個問題:因爲發送方不清楚接收方是否收到了數據,因此發兩次給接收方可能形成冗餘分組的問題。學習
如何卻解決冗餘分組的問題呢,TCP中會對每個分組帶上序號,這樣接收方能夠去判斷是重複數據仍是初始數據,若是接收方最近收到了相同序號的分組,那麼就是重複數據了。而且,經過序號的方式,接收方在收到數據的時候可不只能夠處理重複數據的問題,也能處理數據順序的問題,接收方能夠按照序號對失序的分組集進行重組傳遞給接收方應用程序,那麼問題二情境也就天然而然解決了。
最後看下問題三,分組數據丟失了怎麼辦?可能發送方的分組數據丟了沒到達接收方手裏,也可能接收方返回的響應數據丟了,那麼這個時候該怎麼處理呢?這個問題其實很簡單,咱們針對每一個分組數據設置一個定時器不就完了麼。在定時器規定時間內沒有獲得響應數據,發送方就進行重傳的操做就行了。
經過ARQ協議就可以保證數據的可靠傳輸,可是效率也是須要去重視的,如何在保證數據可靠傳輸的狀況下進行高效的做業呢?
首先考慮最簡單的狀況,就是串行進行上面的一系列操做,一個分組操做完後才進行下一個分組的傳輸。這樣的方式稱之爲停等協議。這種協議對於網絡利用率實在太差了,咱們能夠類比一下若是咱們在一個線程中進行一系列串行I/O的操做,這個咱們是不能接受的。
那麼改爲類比並發的方式處理確定是更爲穩當的,咱們容許發送多個分組無需等待確認,這種技術稱之爲流水線,經過該技術對可靠傳輸協議會帶來影響以下:
上面的影響TCP的開發人員提出了兩種方式去解決:回退N步以及選擇重傳。
回退N步協議(GBN)也稱之爲滑動窗口協議,其做用是容許發送方發送多個分組並且無需等待確認,可是受限於流水線中未確認的分組的最大數不能超過N。下面的圖中顯示了發送方的序號範圍:
能夠看到在窗口長度範圍內有已發送但未確認的數據,以及可用可是未發送的數據,在後面的數據(紫紅色)只能等待窗口中的數據發送被確認後纔有機會進入窗口中,至關於窗口主動進行了滑動,這也就是GBN稱爲滑動窗口協議的緣由。
GBN的運行過程以下描述:
GBN好處在於容許發送方發送多個分組並且無需等待確認,可是也存在着很是明顯的性能問題,單個分組一旦出了錯就會自動重傳全部已發送未確認的數據,所以又提出了選擇重傳協議。
選擇重傳協議經過讓發送發僅僅重傳接收方出錯的分組,避免沒必要要的重傳操做。這種個別的,按需的重傳要求接收方逐個確認正確接收的分組,再次用窗口長度N來限制流水線中未完成,違背確認的分組數。接收方會接收失序的分組,直到全部丟失的分組被接收到爲止,而後按序的交付於上層程序。
選擇確認機制能夠認爲是選擇重傳以及回退N步協議的綜合體,即接收方有選擇性的確認失序的報文段,而不是累計確認最後一個正確接收的有序報文段,只重傳未被接收方確認過的報文段。更加詳細的內容能夠看這篇文章,寫的很是淺顯易懂。
這裏總結一下可靠數據傳輸原理思路圖:
首先整理一下該節中會遇到的縮寫:
TCP協議是基於可靠數據傳輸原理,這也是爲何上面整理了:靠數據傳輸原理的相關內容。首先看下TCP報文段結構吧:
TCP的首部爲20字節,主要的字段說明以下:
首先介紹一下序號字段,序號的概念創建在傳送的字節流之上,一個報文段的序號爲報文段首字節流的編號,假設一段字節流爲1000字節,每一個報文段大小爲200字節,那麼第一個報文段序號爲0,第二個爲200,第三個爲400,以此類推。
確認號的概念則是發送方但願從接送方收到的下一節數據的序號,好比發送方已經從接收方收到了0-200字節的數據,此時發送方再發送一個報文段給接收方,而且帶上確認號201,代表但願收到201以及以後的全部字節。
接下來畫個流程圖來加深理解一下序號和確認號的概念吧,假設客戶端和服務端的字節流的起始序號分別爲20和40,而且報文段的字節大小都是1字節:
TCP協議經過三次握手和四次揮手來保證鏈接的創建與拆除操做。首先看下三次握手:
經過三次握手,雙方創建了鏈接,就能夠相互發送/接收數據了。那麼爲何要三次握手呢?網絡得來的答案以下:
爲何A還要發送一次確認呢?能夠二次握手嗎?
主要爲了防止已失效的鏈接請求報文段忽然又傳送到了B,於是產生錯誤。如A發出鏈接請求,但因鏈接請求報文丟失而未收到確認,因而A再重傳一次鏈接請求。後來收到了確認,創建了鏈接。數據傳輸完畢後,就釋放了鏈接,A工發出了兩個鏈接請求報文段,其中第一個丟失,第二個到達了B,可是第一個丟失的報文段只是在某些網絡結點長時間滯留了,延誤到鏈接釋放之後的某個時間纔到達B,此時B誤認爲A又發出一次新的鏈接請求,因而就向A發出確認報文段,贊成創建鏈接,不採用三次握手,只要B發出確認,就創建新的鏈接了,此時A不理睬B的確認且不發送數據,則B一致等待A發送數據,浪費資源。
四次揮手用於斷開雙方的鏈接,主要流程以下圖所示:
該內容來自這位大牛的文章,我只是作搬運工,底下內容的ACK以及ack兩個不是特別明白,看計算機網絡自頂向下中沒有解釋,不過不影響理解
爲何鏈接的時候是三次握手,關閉的時候倒是四次握手?
由於當Server端收到Client端的SYN鏈接請求報文後,能夠直接發送SYN+ACK報文。其中ACK報文是用來應答的,SYN報文是用來同步的。可是關閉鏈接時,當Server端收到FIN報文時,極可能並不會當即關閉SOCKET,因此只能先回復一個ACK報文,告訴Client端,"你發的FIN報文我收到了"。只有等到我Server端全部的報文都發送完了,我才能發送FIN報文,所以不能一塊兒發送。故須要四步握手。
一條TCP鏈接每一側的主機都會爲該鏈接創建一個接受緩存來保存數據,當TCP接收到正確的數據的時候就會放入到緩存當中,相關應用程序則會在合適的時間去緩存中讀取數據。那麼若是發送方發送數據過快致使了接受方的緩存溢出了就會形成問題。
解決該問題的方案就是流量控制,流量控制是一個速度匹配的服務,即便得發送方的發送速率和接收方應用程序的讀取速率相匹配。TCP使發送方維護一個窗口的變量來提供流量控制,就是咱們在TCP報文段結構中的接收窗口字段,代表接收方還有多少可用的緩存空間。因爲TCP爲全雙工通訊,因此接收方和發送方各有一個接收窗口。
下面簡單看個例子:
擁塞控制主要用於解決網絡擁塞的問題,網絡擁塞緣由主要在於太多的源想要以太高的速率發送數據。TCP中實現的擁塞控制主要有以下方式:
發送方會維護一個擁塞窗口(cwnd)來控制發送速率
慢啓動的原理以下:
當一條TCP鏈接開始的時候,cwnd的值通常設置爲一個MSS,首先傳遞一個報文段,當接收到該報文段的確認時候,cwnd值就變成2個MSS,而後發送兩個報文段,當這兩個報文段被確認後,cwnd值就變成4個MSS而後發送4個報文段,以此類推
慢啓動呈指數冪的形式增長擁塞窗口,可是也不能無限制的去增長對應的擁塞窗口,慢啓動會伴隨着一個變量共同使用:ssthresh(慢啓動閾值)。當cwnd的值等於ssthresh的時候,就會進入擁塞避免的策略當中去。
當進入擁塞避免的時候,cwnd按線性規律增加。
一條TCP鏈接有時會因等待重傳計時器的超時而空閒較長的時間,慢開始和擁塞避免沒法很好的解決這類問題,所以提出了快速重傳和快速恢復的擁塞控制方法。
快重算法機制是,丟包了,接收端重複發送丟包前的ACK,發送端每發送一個包過來,接收端就發相同的ACK回去,這個ACK是對丟包以前的確認。當接收端連續收到3個相同的ACK,它就知道發生丟包了,根據ACK序號就能重發丟的包。其並不是取消了重傳機制,只是在某些狀況下更早的重傳丟失的報文段(若是當發送端接收到三個的確認ACK時,則判定分組丟失,當即重傳丟失的報文段,而沒必要等待重傳計時器超時)。
快恢算法主要是跟着快重算法一塊兒使用的,因爲發送方如今認爲網絡極可能沒有發生擁塞,所以如今不執行慢開始算法,而是把cwnd值設置爲慢啓動閾值減半後的值,而後開始執行擁塞避免算法,是擁塞窗口的線性增大。
因此擁塞控制的基本流程是以下:
TCP的可靠性應該是相對於UDP不可靠傳輸來講的,由於UDP提供的是不可靠的數據報服務,不保證數據報能到達接收端,可能會有丟失;另外處於傳輸層之下的IP層也是不可靠的,僅提供盡力而爲的端到端數據傳輸服務,不做任何保證。因此TCP的可靠性是指基於不可靠的IP層在傳輸層提供可靠的數據傳輸服務,主要是指傳輸數據不會損壞或丟失,並且全部數據都是按照發送順序進行傳送。實現TCP的可靠傳輸有如下機制:
https://blog.csdn.net/u014738387/article/details/52046502
https://blog.csdn.net/mxway/article/details/42784495
《計算機網絡-自頂向下》
http://www.javashuo.com/article/p-ooymcqhd-mo.html