TCP、UDP以及TCP滑窗,它們的區別

我們已經講解了物理層、連接層和網絡層。最開始的連接層協議種類繁多(Ethernet、Wifi、ARP等等)。到了網絡層,我們只剩下一個IP協議(IPv4和IPv6是替代關係)。進入到傳輸層(transport layer),協議的種類又開始繁多起來(比如TCP、UDP、SCTP等)。這就好像下面的大樹,根部(連接層)分叉很多,然後統一到一個樹幹(網絡層),到了樹冠(傳輸層)部分又開始開始分叉,而每個樹枝上長出更多的樹葉(應用層)。我們在網絡層已經看到,通過樹幹的統一,我們實現了一個覆蓋全球的互聯網絡(Internet)。然而,我們可能出於不同的目的利用這張“網”,隨之使用的方式也有所區分。不同的傳輸層協議(以及更多的應用層協議)正是我們使用“網”的不同方式的體現。

傳輸層最重要的協議爲TCP協議和UDP協議。這兩者使用“網”的方式走了兩個極端。兩個協議的對比非常有趣。TCP協議複雜,但傳輸可靠。UDP協議簡單,但傳輸不可靠。其他的各個傳輸層協議在某種程度上都是這兩個協議的折中。我們先來看傳輸層協議中比較簡單的UDP協議。我們將參考許多之前文章的內容(協議森林01, 03, 05)。

UDP協議簡介

UDP(User Datagram Protocol)傳輸與IP傳輸非常類似。你可以將UDP協議看作IP協議暴露在傳輸層的一個接口。UDP協議同樣以數據包(datagram)的方式傳輸,它的傳輸方式也是"Best Effort"的,所以UDP協議也是不可靠的(unreliable)。那麼,我們爲什麼不直接使用IP協議而要額外增加一個UDP協議呢? 一個重要的原因是IP協議中並沒有端口(port)的概念。IP協議進行的是IP地址到IP地址的傳輸,這意味者兩臺計算機之間的對話。但每臺計算機中需要有多個通信通道,並將多個通信通道分配給不同的進程使用(關於進程,可以參考Linux進程基礎)。一個端口就代表了這樣的一個通信通道。正如我們在郵局和郵差中提到的收信人的概念一樣。UDP協議實現了端口,從而讓數據包可以在送到IP地址的基礎上,進一步可以送到某個端口。

儘管UDP協議非常簡單,但它的產生晚於更加複雜的TCP協議。早期的網絡開發者開發出IP協議和TCP協議分別位於網絡層和傳輸層,所有的通信都要先經過TCP封裝,再經過IP封裝(應用層->TCP->IP)。開發者將TCP/IP視爲相互合作的套裝。但很快,網絡開發者發現,IP協議的功能和TCP協議的功能是相互獨立的。對於一些簡單的通信,我們只需要“Best Effort”式的IP傳輸就可以了,而不需要TCP協議複雜的建立連接的方式(特別是在早期網絡環境中,如果過多的建立TCP連接,會造成很大的網絡負擔,而UDP協議可以相對快速的處理這些簡單通信)。UDP協議隨之被開發出來,作爲IP協議在傳輸層的"傀儡"。這樣,網絡通信可以通過應用層->UDP->IP的封裝方式,繞過TCP協議。由於UDP協議本身異常簡單,實際上只爲IP傳輸起到了橋樑的作用。我們將在TCP協議的講解中看到更多TCP協議和UDP協議的對比。

UDP的數據包同樣分爲頭部(header)和數據(payload)兩部分。UDP是傳輸層(transport layer)協議,這意味着UDP的數據包需要經過IP協議的封裝(encapsulation),然後通過IP協議傳輸到目的電腦。隨後UDP包在目的電腦拆封,並將信息送到相應端口的緩存中。

UDP協議的頭部

來自wikipedia

上面的source port和destination port分別爲UDP包的出發端口和目的地端口。Length爲整個UDP包的長度。

checksum的算法與IP協議的header checksum算法相類似。然而,UDP的checksum所校驗的序列包括了整個UDP數據包,以及封裝的IP頭部的一些信息(主要爲出發地IP和目的地IP)。這樣,checksum就可以校驗IP:端口的正確性了。在IPv4中,checksum可以爲0,意味着不使用checksum。IPv6要求必須進行checksum校驗。

端口與socket

端口(port)是伴隨着傳輸層誕生的概念。它可以將網絡層的IP通信分送到各個通信通道。UDP協議和TCP協議儘管在工作方式上有很大的不同,但它們都建立了從一個端口到另一個端口的通信。

隨着我們進入傳輸層,我們也可以調用操作系統中的API,來構建socket。Socket是操作系統提供的一個編程接口,它用來代表某個網絡通信。應用程序通過socket來調用系統內核中處理網絡協議的模塊,而這些內核模塊會負責具體的網絡協議的實施。這樣,我們可以讓內核來接收網絡協議的細節,而我們只需要提供所要傳輸的內容就可以了,內核會幫我們控制格式,並進一步向底層封裝。因此,在實際應用中,我們並不需要知道具體怎麼構成一個UDP包,而只需要提供相關信息(比如IP地址,比如端口號,比如所要傳輸的信息),操作系統內核會在傳輸之前會根據我們提供的相關信息構成一個合格的UDP包(以及下層的包和幀)。

總結

端口是傳輸層帶來的最重要的概念。我們進一步瞭解了UDP協議。如果已經掌握了IP協議,那麼UDP協議就沒有任何困難可言,它只是IP協議暴露在傳輸層上的接口。

TCP協議簡介

在TCP協議中,我們使用連接記錄TCP兩端的狀態,使用編號和分段實現了TCP傳輸的有序,使用advertised window來實現了發送方和接收方處理能力的匹配,並使用重複發送來實現TCP傳輸的可靠性。我們只需要將TCP片段包裝成IP包,扔到網絡中就可以了。TCP協議的相關模塊會幫我們處理各種可能出現的問題(比如排序,比如TCP片段丟失等等)。最初的TCP協議就是由上述的幾大塊構成的。

TCP(Transportation Control Protocol)協議與IP協議是一同產生的。事實上,兩者最初是一個協議,後來才被分拆成網絡層的IP和傳輸層的TCP。我們已經在UDP協議中介紹過,UDP協議是IP協議在傳輸層的“傀儡”,用來實現數據包形式的通信。而TCP協議則實現了“流”形式的通信。

“流”通信

TCP協議是傳輸層協議,實現的是端口到端口(port)的通信。

IP協議(參考協議森林03,05)和UDP協議採用的是數據包的方式傳送,後發出的數據包可能早到,我們並不能保證數據到達的次序。TCP協議確保了數據到達的順序與文本流順序相符。當計算機從TCP協議的接口讀取數據時,這些數據已經是排列好順序的“流”了。比如我們有一個大文件要從本地主機發送到遠程主機,如果是按照“流”接收到的話,我們可以一邊接收,一邊將文本流存入文件系統。這樣,等到“流”接收完了,硬盤寫入操作也已經完成。如果採取UDP的傳輸方式,我們需要等到所有的數據到達後,進行排序,才能組裝成大的文件。這種情況下,我們不得不使用大量的計算機資源來存儲已經到達的數據,直到所有數據都達到了,才能開始處理。

“流”的要點是次序(order),然而實現這一點並不簡單。TCP協議是基於IP協議的,所以最終數據傳送還是以IP數據包爲單位進行的。如果一個文本流很長的話,我們不可能將整個文本流放入到一個IP數據包中,那樣有可能會超過MTU。所以,TCP協議封裝到IP包的不是整個文本流,而是TCP協議所規定的片段(segment)。與之前的一個IP或者UDP數據包類似,一個TCP片段同樣分爲頭部(header)和數據(payload)兩部分 (“片段”這個名字更多是起提醒作用:嘿,這裏並不是完整的文本流)。整個文本流按照次序被分成小段,而每一段被放入TCP片段的數據部分。一個TCP片段封裝成的IP包不超過整個IP接力路徑上的最小MTU,從而避免令人痛苦的碎片化(fragmentation)。

(給文本流分段是在發送主機完成的,而碎片化是在網絡中的路由器完成的。路由器要處理許多路的通信,所以相當繁忙。文本流提前在發送主機分好段,可以避免在路由器上執行碎片化,可大大減小網絡負擔)

TCP片段的頭部(header)會存有該片段的序號(sequence number)。這樣,接收的計算機就可以知道接收到的片段在原文本流中的順序了,也可以知道自己下一步需要接收哪個片段以形成流。比如已經接收到了片段1,片段2,片段3,那麼接收主機就開始期待片段4。如果接收到不符合順序的數據包(比如片段8),接收方的TCP模塊可以拒絕接收,從而保證呈現給接收主機的信息是符合次序的“流”。

可靠性

片段編號這個初步的想法並不能解決我們所有的問題。IP協議是不可靠的,所以IP數據包可能在傳輸過程中發生錯誤或者丟失。而IP傳輸是"Best Effort" 式的,如果發生異常情況,我們的IP數據包就會被輕易的丟棄掉。另一方面,如果亂序(out-of-order)片段到達,根據我們上面說的,接收主機不會接收。這樣,錯誤片段、丟失片段和被拒片段的聯手破壞之下,接收主機只可能收到一個充滿“漏洞”的文本流。

TCP的補救方法是,在每收到一個正確的、符合次序的片段之後,就向發送方(也就是連接的另一段)發送一個特殊的TCP片段,用來知會(ACK,acknowledge)發送方:我已經收到那個片段了。這個特殊的TCP片段叫做ACK回覆。如果一個片段序號爲L,對應ACK回覆有回覆號L+1,也就是接收方期待接收的下一個發送片段的序號。如果發送方在一定時間等待之後,還是沒有收到ACK回覆,那麼它推斷之前發送的片段一定發生了異常。發送方會重複發送(retransmit)那個出現異常的片段,等待ACK回覆,如果還沒有收到,那麼再重複發送原片段… 直到收到該片段對應的ACK回覆(回覆號爲L+1的ACK)。

當發送方收到ACK回覆時,它看到裏面的回覆號爲L+1,也就是發送方下一個應該發送的TCP片段序號。發送方推斷出之前的片段已經被正確的接收,隨後發出L+1號片段。ACK回覆也有可能丟失。對於發送方來說,這和接收方拒絕發送ACK回覆是一樣的。發送方會重複發送,而接收方接收到已知會過的片段,推斷出ACK回覆丟失,會重新發送ACK回覆。

通過ACK回覆和重新發送機制,TCP協議將片段傳輸變得可靠。儘管底盤是不可靠的IP協議,但TCP協議以一種“不放棄的精神”,不斷嘗試,最終成功。(技術也可以很勵志)

滑窗

上面的工作方式中,發送方保持發送->等待ACK->發送->等待ACK…的單線工作方式,這樣的工作方式叫做stop-and-wait。stop-and-wait雖然實現了TCP通信的可靠性,但同時犧牲了網絡通信的效率。在等待ACK的時間段內,我們的網絡都處於閒置(idle)狀態。我們希望有一種方式,可以同時發送出多個片段。然而如果同時發出多個片段,那麼由於IP包傳送是無次序的,有可能會生成亂序片段(out-of-order),也就是後發出的片段先到達。在stop-and-wait的工作方式下,亂序片段完全被拒絕,這也很不效率。畢竟,亂序片段只是提前到達的片段。我們可以在緩存中先存放它,等到它之前的片段補充完畢,再將它綴在後面。然而,如果一個亂序片段實在是太過提前(太“亂”了),該片段將長時間佔用緩存。我們需要一種折中的方法來解決該問題:利用緩存保留一些“不那麼亂”的片段,期望能在段時間內補充上之前的片段(暫不處理,但發送相應的ACK);對於“亂”的比較厲害的片段,則將它們拒絕(不處理,也不發送對應的ACK)。

滑窗(sliding window)被同時應用於接收方和發送方,以解決以上問題。發送方和接收方各有一個滑窗。當片段位於滑窗中時,表示TCP正在處理該片段。滑窗中可以有多個片段,也就是可以同時處理多個片段。滑窗越大,越大的滑窗同時處理的片段數目越多(當然,計算機也必須分配出更多的緩存供滑窗使用)。

我們假設一個可以容納三個片段的滑窗,並假設片段從左向右排列。對於發送方來說,滑窗的左側爲已發送並已ACK過的片段序列,滑窗右側是尚未發送的片段序列。滑窗中的片段(比如片段5,6,7)被髮送出去,並等待相應的ACK。如果收到片段5的ACK,滑窗將向右移動。這樣,新的片段從右側進入滑窗內,被髮送出去,並進入等待狀態。在接收到片段5的ACK之前,滑窗不會移動,即使已經收到了片段6和7的ACK。這樣,就保證了滑窗左側的序列是已經發送的、接收到ACK的、符合順序的片段序列。

對於接收方來說,滑窗的左側是已經正確收到並ACK回覆過的片段(比如片段1,2,3,4),也就是正確接收到的文本流。滑窗中是期望接收的片段(比如片段5, 6, 7)。同樣,如果片段6,7先到達,那麼滑窗不會移動。如果片段5先到達,那麼滑窗會向右移動,以等待接收新的片段。如果出現滑窗之外的片段,比如片段9,那麼滑窗將拒絕接收。

利用滑窗,我們一定程度上實現了對亂序數據的緩存。但是,過於亂序的數據依然會被拒絕。我們之前說的stop-and-wait的工作方式,相當於發送方和接收方的滑窗都只能容納一個片段。

累計ACK

在TCP連接中,我們通過將ACK回覆“附着”在其他數據片段的方式,減少了ACK回覆所消耗的流量。但這並不是全部的故事。TCP協議並不是對每個片段都發送ACK回覆。TCP協議實際採用的是累計ACK回覆(accumulative acknowledgement)。接收方往往利用一個ACK回覆來知會連續多個片段的成功接收。通過累計ACK,所需要的ACK回覆通常可以降到50%。

如下圖所示,橙色爲已經接收的片段。方框爲滑窗,滑窗可容納3個片段。

累計ACK

滑窗還沒接收到片段7時,已接收到片段8,9。這樣就在滑窗中製造了一個“空穴”(hole)。當滑窗最終接收到片段7時,滑窗送出一個回覆號爲10的ACK回覆。發送方收到該回復,會意識到,片段10之前的片段已經按照次序被成功接收。整個過程中節約了片段7和片段8所需的兩個ACK回覆。

此外,接收方在接收到片斷,並應該回復ACK的時候,會故意延遲一些時間。如果在延遲的時間裏,有後續的片段到達,就可以利用累計ACK來一起回覆了。

滑窗結構

在之前的討論中,我們以片段爲單位,來衡量滑窗的大小的。真實的滑窗是以byte爲單位表示大小,但這並不會對我們之前的討論造成太大的影響。

發送方滑窗可以分爲下面兩個部分。offered window爲整個滑窗的大小。

接收方滑窗可分爲三個部分:

可以看到,接收方的滑窗相對於發送方的滑窗多了一個"Received; ACKed; Not Sent to Proc"的部分。接收方接收到的文本流必須等待進程來讀取。如果進程正忙於做別的事情,那麼這些文本流即使已經正確接收,還是需要暫時佔用接收緩存。當出現上述佔用時,滑窗的可用部分(也就是圖中advertised window)就會縮水。這意味着接收方的處理能力下降。如果這個時候發送方依然按照之前的速率發送數據給接收方,接收方將無力接收這些數據。

流量控制

TCP協議會根據情況自動改變滑窗大小,以實現流量控制。流量控制(flow control)是指接收方將advertised window的大小通知給發送方,從而指導發送方修改offered window的大小。接收方將該信息放在TCP頭部的window size區域:

發送方在收到window size的通知時,會調整自己滑窗的大小,讓offered window和advertised window相符。這樣,發送窗口變小,文本流發送速率降低,從而減少了接收方的負擔。

零窗口

advertised window大小有可能變爲0,這意味着接收方的接收能力降爲0。發送方收到大小爲0的advertised window通知時,停止發送。

TCP協議是一個可靠的協議。它通過重新發送(retransmission)來實現TCP片段傳輸的可靠性。簡單的說,TCP會不斷重複發送TCP片段,直到片段被正確接收。

TCP片段丟失

接收方(receiver)可以通過校驗TCP片段頭部中checksum區域來檢驗TCP片段是否出錯。我們已經接觸過了IP協議詳解的checksum算法。TCP片段的checksum算法與之類似。IP協議的checksum只校驗頭部,TCP片段頭部的checksum會校驗包括IP頭部、TCP頭部和TCP數據在內的整個序列,確保IP地址、端口號和其他相關信息正確。如果TCP片段出錯,接收方可以簡單的丟棄改TCP片段,也就相當於TCP片段丟失。

TCP片段包裹在一個IP包中傳輸。IP包可能在網絡中丟失。導致IP包丟失的原因可能有很多,比如IP包經過太多的路由器接力,達到hop limit;比如路由器太過擁擠,導致一些IP包被丟棄;再比如路由表(routing table)沒有及時更新,導致IP包無法送達目的地。

下面我們要介紹兩種重新發送TCP片段的機制:超時重新發送和快速重新發送。

超時重新發送

我們之前已經簡單介紹過重新發送的機制:當發送方送出一個TCP片段後,將開始計時,等待該TCP片段的ACK回覆。如果接收方正確接收到符合次序的片段,接收方會利用ACK片段回覆發送方。發送方得到ACK回覆後,繼續移動窗口,發送接下來的TCP片段。如果直到計時完成,發送方還是沒有收到ACK回覆,那麼發送方推斷之前發送的TCP片段丟失,因此重新發送之前的TCP片段。這個計時等待的時間叫做重新發送超時時間(RTO, retransmission timeout)。

快速重新發送

我們剛纔介紹了超時重新發送的機制:發送方送出一個TCP片段,然後開始等待並計時,如果RTO時間之後還沒有收到ACK回覆,發送方則重新發送。TCP協議有可能在計時完成之前啓動重新發送,也就是利用快速重新發送(fast-retransmission)。快速發送機制如果被啓動,將打斷計時器的等待,直接重新發送TCP片段。

由於IP包的傳輸是無序的,所以接收方有可能先收到後發出的片段,也就是亂序(out-of-order)片段。亂序片段的序號並不等於最近發出的ACK回覆號。已接收的文本流和亂序片段之間將出現空洞(hole),也就是等待接收的空位。比如已經接收了正常片段5,6,7,此時又接收亂序片段9。這時片段8依然空缺,片段8的位置就是一個空洞。

TCP協議規定,當接收方收到亂序片段的時候,需要重複發送ACK。比如接收到亂序片段9的時候,接收方需要回復ACK。回覆號爲8 (7+1)。此後接收方如果繼續收到亂序片段(序號不是8的片段),將再次重複發送ACK=8。當發送方收到3個ACK=8的回覆時,發送方推斷片段8丟失。即使此時片段8的計時器還沒有超時,發送方會打斷計時,直接重新發送片段8,這就是快速重新發送機制(fast-retransmission)。

快速重新發送機制利用重複的ACK來提示空洞的存在。當重複次數達到閾值時,認爲空洞對應的片段在網絡中丟失。快速重新發送機制提高了檢測丟失片段的效率,往往可以在超時之前探測到丟失片段,並重復發送丟失的片段。

總結

TCP協議利用重新發送(retransmission)來實現TCP傳輸的可靠性。重新發送的基本形式是超時重新發送,根據統計的往返時間來設置超時標準;如果超時,則重新發送TCP片段。另一方面,快速重新發送則通過亂序片段的ACK來更早的推斷出片段的丟失。

總結

TCP協議和UDP協議走了兩個極端。TCP協議複雜但可靠,UDP協議輕便但不可靠。在處理異常的時候,TCP極端負責,而UDP一副無所謂的樣子。在TCP中,分段和編號實現了次序;ACK和重新發送實現了可靠性;sliding window則讓上面的機制更加有效率的運行。

面向報文(UDP)和麪向字節流(TCP)的區別

面向報文的傳輸方式是應用層交給UDP多長的報文,UDP就照樣發送,即一次發送一個報文。因此,應用程序必須選擇合適大小的報文。若報文太長,則IP層需要分片,降低效率。若太短,會是IP太小。UDP對應用層交下來的報文,既不合並,也不拆分,而是保留這些報文的邊界。這也就是說,應用層交給UDP多長的報文,UDP就照樣發送,即一次發送一個報文。

面向字節流的話,雖然應用程序和TCP的交互是一次一個數據塊(大小不等),但TCP把應用程序看成是一連串的無結構的字節流。TCP有一個緩衝,當應用程序傳送的數據塊太長,TCP就可以把它劃分短一些再傳送。如果應用程序一次只發送一個字節,TCP也可以等待積累有足夠多的字節後再構成報文段發送出去。

下圖是TCP和UDP協議的一些應用。

下圖是TCP和UDP協議的比較。

這裏再詳細說一下面向連接和麪向無連接的區別:

面向連接舉例:兩個人之間通過電話進行通信;

面向無連接舉例:郵政服務,用戶把信函放在郵件中期待郵政處理流程來傳遞郵政包裹。顯然,不可達代表不可靠。

從程序實現的角度來看,可以用下圖來進行描述。

從上圖也能清晰的看出,TCP通信需要服務器端偵聽listen、接收客戶端連接請求accept,等待客戶端connect建立連接後才能進行數據包的收發(recv/send)工作。而UDP則服務器和客戶端的概念不明顯,服務器端即接收端需要綁定端口,等待客戶端的數據的到來。後續便可以進行數據的收發(recvfrom/sendto)工作。

在前面講解UDP時,提到了UDP保留了報文的邊界,下面我們來談談TCP和UDP中報文的邊界問題。在默認的阻塞模式下,TCP無邊界,UDP有邊界。

對於TCP協議,客戶端連續發送數據,只要服務端的這個函數的緩衝區足夠大,會一次性接收過來,即客戶端是分好幾次發過來,是有邊界的,而服務端卻一次性接收過來,所以證明是無邊界的;

而對於UDP協議,客戶端連續發送數據,即使服務端的這個函數的緩衝區足夠大,也只會一次一次的接收,發送多少次接收多少次,即客戶端分幾次發送過來,服務端就必須按幾次接收,從而證明,這種UDP的通訊模式是有邊界的。

TCP無邊界,造成對採用TCP協議發送的數據進行接收比較麻煩,在接收的時候易出現粘包,即發送方發送的若干包數據到接收方接收時粘成一包。由於TCP是流協議,對於一個socket的包,如發送 10AAAAABBBBB兩次,由於網絡原因第一次又分成兩次發送, 10AAAAAB和BBBB,如果接包的時候先讀取10(包長度)再讀入後續數據,當接收得快,發送的慢時,就會出現先接收了 10AAAAAB,會解釋錯誤 ,再接到BBBB10AAAAABBBBB,也解釋錯誤的情況。這就是TCP的粘包。

在網絡傳輸應用中,通常需要在網絡協議之上再自定義一個協議封裝一下,簡單做法就是在要發送的數據前面再加一個自定義的包頭,包頭中可以包含數據長度和其它一些信息,接收的時候先收包頭,再根據包頭中描述的數據長度來接收後面的數據。詳細做法是:先接收包頭,在包頭裏指定包體長度來接收。設置包頭包尾的檢查位( 比如以0xAA開頭,0xCC結束來檢查一個包是否完整)。對於TCP來說:

1)不存在丟包,錯包,所以不會出現數據出錯 ;

2)如果包頭檢測錯誤,即爲非法或者請求,直接重置即可。

爲了避免粘包現象,可採取以下幾種措施。

一、對於發送方引起的粘包現象,用戶可通過編程設置來避免,TCP提供了強制數據立即傳送的操作指令push,TCP軟件收到該操作指令後,就立即將本段數據發送出去,而不必等待發送緩衝區滿;

二、對於接收方引起的粘包,則可通過優化程序設計、精簡接收進程工作量、提高接收進程優先級等措施,使其及時接收數據,從而儘量避免出現粘包現象;

三、由接收方控制,將一包數據按結構字段,人爲控制分多次接收,然後合併,通過這種手段來避免粘包。

1.無連接VS面向連接

UDP是無連接的,TCP面向連接的,這個連接指的就是在運用TCP協議之前,必須先建立TCP連接,在數據傳送完畢之後必須釋放連接,通俗地將通信的雙方知道彼此的存在這個連接是一個虛電路。

影響:

①因爲要建立連接所以TCP有建立連接的“三次握手”,所以UDP在發送數據之前時延更加小。

②因爲面向連接是端到端的通信,所以多播和廣播就只能運用UDP協議。

2.盡最大努力交付VS可靠交付

影響:

①UDP不保證可靠交付,當發生丟包的時候不重傳,並且不保證數據包按序到達。所以UDP數據報報頭小,並且不用維護很多的定時器、連接狀態表、算法。

②TCP提供可靠交付。保證數據包無差錯、不丟失、不重複、並且按序到達。

3.面向報文VS面向數據流

UDP面向報文,發送方的UDP應用程序交下來的報文,在添加首部後就向下交付給IP層。UDP對應用層交下來的報文,既不合並,也不拆分,而是保留這些報文的邊界。這就是說應用層交給UDP多大的報文,UDP就照樣發送,即一次發送一個報文。

TCP面向字節流,TCP中的“流”指的是流入到進程或從進程流出的字節序列。面向字節流的含義是:雖然應用程序和TCP的交互式一次一個數據塊(大小不等),但是TCP把應用程序交下來的數據看成僅僅是一連串的無結構字節流。所以TCP纔有滑動窗口機制、Nagle算法等等。因此TCP並不保證發送的數據塊和應用層交付的數據塊相等,比如應用層交付了10個數據塊,但是TCP將此10個數據塊合併爲4個數據塊發送,這是出於效率的考慮,但是字節流是一樣的。

4.TCP具有擁塞控制

   擁塞控制是面向全局網絡的,和應用程序沒有太多的關係。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章