TCP IP 網路基礎(三)傳輸層

2021-09-14 07:50:40 字數 3160 閱讀 7686

網路層為通訊搭建好了基礎架構,但對於應用程式來說,它仍是「不可用」的。類似地,即使各級鐵路公路能通到全國的任何地方,但如果沒有快遞公司,你怎麼寄東西?傳輸層就是給需要使用網路傳輸的應用程式直接使用的協議,也只有它提供了程式設計介面,即套接字。

tcp/ip在傳輸層的主要協議就是tcp和udp。在這一層,它們引入了兩個新的概念。

埠網路層只有位址。但實際上,同乙個位址(主機)上還有不同的程序。為了區分這些程序就引入了埠。協議+ip+埠才能唯一定位到乙個目標應用。

http、ftp等上層協議使用的埠號都是固定的,這些叫做知名埠號,由0到1023佔據。應用程式應該避免使用這些埠號。

客戶端/伺服器

雖然通訊的兩個實體應該是對等的,但必然有乙個要先發出第乙個請求,它就是客戶端。另乙個就是伺服器。而作為伺服器,應該在第乙個請求到來之前就啟動並準備好,因此通常有個守護程序。也就是說,伺服器監聽乙個或多個客戶端的訊息(tcp請求或udp資料報),而客戶端先開口說話。

即使用者報文協議,它簡單地封裝了ip層的功能,提供無連線的通訊服務。udp可能會出現丟包、亂序,也無法處理網路擁堵。而這些處理只能由使用它的上層應用實現。總而言之,udp就是個輕量快速的協議,它往往應用於以下幾個方面:

tcp則是一種相當可靠的協議。它是面向連線的,並且有丟包重發,亂序整理,擁塞控制等功能。下面我們來分別介紹它是怎麼做的。

首先,首部校驗和這個技術肯定是有的。從物理層、資料鏈路層、網路層,甚至udp都是具備的。只有它能防止內容出錯。

連線管理

就是幾乎家喻戶曉的三次握手和四次揮手。上圖:

三次握手簡單來說就是客戶端問服務端在嗎?服務端回答我在,收到吱一聲。客戶端:吱。然後連線就建立了。當然中間有一些商量mtu(最大傳輸單元),同步傳送和ack序號的過程,略去不表。再看四次揮手:

四次揮手的過程相當於你和老闆 1 on 1 結束時的場景。開始是你們你一句我一句,然後你對老闆說:我沒話了,你呢?老闆:收到。但是我還有幾件事要交代,bla bla... 最後,老闆:好了我也說完了,你可以滾了。你:好的。

解決亂序和丟包

tcp為每段傳送的資料都標上相對開頭的位元組偏移,接收端收到後則要響應乙個ack訊息,告訴傳送端自己收到了哪段資料。傳送端傳送了一段資料後遲遲沒有收到確認訊息,就會重發。而接收端反正有各個訊息的序號,即使到達的資料亂序,也能正確地處理。如果收到重複的資料,就直接丟棄。這種技術就稱為確認-重傳機制。

超時檢測是通過定時器實現的,而定時器的時常不是固定的,而是根據估算的往返時間(rtt)動態調整。這也是tcp的nb之處。

滑動視窗

你以為確認-重發機制就這麼簡單?真實的情形遠比上圖的複雜。tcp採用滑動窗**術來實現其收發機制。

tcp連線的每一端都維護了乙個接收視窗。它的意思就是所期望收到的下一段資料的序號範圍。當資料到達時,序號超出這個視窗的都被丟棄。然後如果視窗的前幾個位元組已經收到了,就通知應用程式讀取,再向後滑動視窗,然後傳送ack訊息通知對端下乙個期待的序號。

如上圖,(a)表示希望接收到的下乙個位元組序號是4,並且可以接受9個位元組。(b)表示收到了4,5,6,7幾個位元組後,接收視窗向後移動了4個位元組,並且傳送的ack將表明它接下來期望收到序號8.

同理,傳送端也會維護乙個傳送視窗,而它又分為兩部分:已傳送但未收到確認的位元組,和可以傳送但未傳送的位元組。

如上圖,位元組1~3已經收到了確認訊息。(a)表示當前的傳送視窗。在位元組4~7傳送之後,被確認之前,傳送視窗如(b)所示。此時,tcp還可以傳送8~12而無須等待對方的ack。但傳送這些位元組之後,定時器就會啟動,如果超時之前還沒有收到ack,這段資料就會重發。

(c)表示位元組4~7收到確認後傳送視窗後移。

通過滑動視窗,可以解決簡單的傳送-應答機制每次只能傳送一段資料,等待太多,效率太低的問題。現在的通訊狀況如下:

流控制和擁塞控制

流控制就是考慮接受端的接收能力,不要發的太快,不然接收不過來也是白白浪費網路流量。方法就是接收方把自己的接收視窗告訴傳送方。

tcp採用慢啟動,最終會趨向於佔滿頻寬。具體演算法不再研究。

套接字即socket api,它起初發源於unix,後來又被移植到windows上成為winsock。也就是說,六合之內,它是網路層程式設計的唯一介面。

本人目前沒有直接對套接字程式設計的需求,在此只作簡單介紹。

對伺服器程式來說,基本的操作是先獲得socket結構體,接著呼叫bind繫結位址和埠,然後就監聽在埠上。這個過程阻塞。當有連線進來時,程式繼續,呼叫accept獲得對方的socket,然後就可以呼叫recv和send進行通訊。

對客戶端程式來說,基本的操作是先獲得socket結構體,再呼叫connect連線伺服器,成功後呼叫recv和send進行通訊。

套接字api封裝了前面講解的滑動視窗等各種機制,對程式來說,只能讀取到資料流。因為tcp就是個流協議,無法控制資料段到達對端的方式。同樣的,應用程式把資料傳送給底層後,也無法控制資料如何被傳送,如被打包還是分拆。

因此,讀取這種位元組流時,如果是定長報文就很好辦,每次讀取固定位元組即可。而如果報文內容是可變的,則往往採用這樣一種方式:在每條報文前面加上乙個首部,其中包含本記錄的長度。這樣接收端就可以分兩次讀取報文。第一次先用定長方式讀取首部,取出長度,然後第二次讀取全部報文。

這讓我想起了以前似懂非懂地修改過的公司某產品的通訊協議…

tcp完全可靠,不需要應用程式考慮任何事情?當然沒有這麼神奇的事情。最簡單地,如果兩個端點通訊不可達,tcp就毫無辦法。另外,應用程式是針對套接字程式設計,也要考慮對端的特殊輸入、不友好動作等錯誤處理。具體可見《tcp/ip高效程式設計》的技巧9,11.

網路協議不同於我們在一台機器上的程式設計約定和規範——後者總是相當可控的。舉個極端的例子,你在 word 程式裡寫了個你的銀行密碼,然後你不想再讓第二個人知道。你可以刪除這個字串,或者刪除文件,甚至在緊急情況下把電腦砸了。究其根源,是你從物理上擁有這台電腦。而網路協議,你把乙個資料報發出去,然後事情就脫離了你的控制。剩下的任務就依賴於別的組織、個人、裝置能正常盡職的工作,履行交付的承諾。這裡面大量依賴了約定和信任。當然,任何乙個不能遵守這些協議的公司的產品,也不可能有消費者會買單。想一想,我們每個月付給運營商一些網費,就可以無限量地傳輸任何資料到任何位址,這不是乙個神奇的事情嗎?

網路基礎 傳輸層

傳輸層負責資料能夠從傳送端傳輸接收端。埠號 port 標識了乙個主機上進行通訊的不同的應用程式。在tcp ip協議中,用 源ip 源埠號 統稱為源端套接字 目的ip 目的埠號 統稱為伺服器端套接字 協議號 這樣乙個五元組來標識乙個通訊,可通過netstat n檢視。協議號決定了使用傳輸層的哪個協議。...

網路基礎 傳輸層

傳輸層 解決如何傳輸,協議都不可變 五元組織 源ip 源埠號 目的ip 目的埠號 協議號 udp報文 報頭 源埠,目的埠 16位udp長度 16位udp校驗和 解決有效載荷與報頭分離 基於udp的應 用層協議 nfs 網路檔案系統 tftp 簡單檔案傳輸協議 dhcp 動態主機配置協議 向路由申請i...

網路基礎筆記 傳輸層

跟蹤各個會話,讀個應用程式同屬在網路上通行時,傳輸層負責管理這些應用程式的多道路通行流 分段資料,將大量的資料拆分成小的分段,更適合傳輸。這一過程傳輸層在每個分段上新增報頭,關聯與該分段的通訊 重組資料段,通過編號與排序分段,資料層能保證分段能以正確的順序重組,然後傳給適當的應用程式。傳輸層的協議描...