TCP/IP 的鏈路層是可靠的嗎?

如果是可靠的,可靠到什麼程度呢?什麼異常情況下會變得不可靠?
TCP/IP詳解(卷1)鏈路層章節中,給出的鏈路層幀結構中並無如何分幀的信息,接收端如何完成分幀呢?小於46位元組情況下需要填充,填充信息在幀結構中也沒有,接收端如何移除填充呢?


寫完這篇文章,昏昏欲睡,為了提神,上一幅風景畫。

問題一:鏈路可靠性

總體來說,網線比無線可靠,但網線也不是100%可靠,在交換機的入埠錯誤統計上,CRC Error 一般都是名列前茅,造成CRC Error 的原因有:網卡的軟體故障、硬體故障、網線質量、信號干擾。


曾經在數據中心裡,接入層的交換機某些入口有1.5%% 的CRC Error,先換網線,情況依然。到最後把伺服器重啟,CRC Error 消失,過幾天故障依然。後來發現這種情況只發生在某個型號,特定版本的伺服器上,解決方案是升級軟體版本,故障消失。


無線是很不可靠的,可以在電腦上ping 無線路由器,ping 100個包,一般都會丟幾個。造成丟失的原因:因為周圍有很多工作在同一個頻端的無線路由器,互相會干擾,造成無線信號不可用,從而丟棄。


還有一個原因,無線路由器與電腦之間有很多牆,信號衰減很多,再加上干擾,最後變得面目可憎而被拋棄。

問題二:如何分幀?


首先乙太網幀是段狀結構,不是連續的,幀與幀之間有一個時間間隙(Time Slot)

如上圖,這個Inter packet gap 就是間隙,在10/100/1000/10000 G的乙太網上,這12 byte 對應的是不同的時間間隙,速率越高,時間間隙越小。

問題三: 位填充


IP層做位填充

IP層處理IP包是以32 bit (4 byte)為一個單位,所以IP包的總長度如果不是 4 byte 的整數倍,則需要填充至整數倍,填充內容為0x00(16進位)。


網卡做位填充

乙太網幀如果長度小於64 byte(其中包括乙太網頭部14 byte,幀校驗FCS 4 byte),網卡需要將其填充到至少64 byte,滿足網卡對最小幀長度的限制。


假設IP層發給網卡的包長只有40 byte, 則網卡需要填充至少 6個 byte 的 0x00(16進位)。


乙太網頭 + IP + 0x 00 00 00 00 00 00 + FCS

問題四:如何讓接收方知道位填充的長度?


IP包頭有IP包總長度,那位填充的長度就可以根據這個等式得到:


位填充長度 = 乙太網卡提交給IP層的包長 - IP包總長度


其中

乙太網卡提交給IP層的包長 = 網卡接收幀 - 乙太網幀頭 - FCS


1. 不可靠。
2. 分幀是硬體完成的,例如乙太網是靠 frame 之間的 gap。
3. 接收端的網路層(IP 層)會丟棄多餘的填充位元組,因為 IP header 里有長度欄位。


在tcp/ip協議棧中,除了傳輸層的tcp協議,傳輸層的udp、以及傳輸層之下的網路層、數據鏈路層都是「盡最大努力交付」。盡最大努力交付的協議都有校驗位,來確認數據傳輸過程中是否發生了位翻轉。 比如在數據鏈路層是用csc進行校驗,在網路層和傳輸層是利用checksum層進行校驗。
什麼異常情況下會變得不可靠?
數據鏈路層處理的是 一個節點通過鏈路到達另一個節點的問題,也就是一跳,能夠影響到這一跳的數據的幾個要素有以下幾個:
1、物理鏈路的質量
2、最大傳輸速率
3、雜訊(雜訊是不可避免,但是可以通過信噪比降低雜訊的影響)
上面這幾個要素是影響數據在物理鏈路上傳輸的幾個重要的因素。重點說,現在鏈路的質量完全可以讓我們放心傳輸的過程中碼元不會失真或者說碼元失真的概率非常小)
這裡還要結合曼徹斯特編碼來講可能會清楚一點,不過這個是物理層方面的知識。


給出的鏈路層幀結構中並無如何分幀的信息,接收端如何完成分幀呢?

分幀的過程是有網路適配器完成的,網路適配器有自己的處理器和存儲器,能夠緩存處理上層(網路層)傳下來的數據。
這裡補充一下(發現沒有寫完整)。
數據鏈路層的三個基本問題,其中一個就是封裝成幀,我們知道執行封裝的這個動作是由網路適配器來完成。但是我們首先要先確定一個問題,就是接收方的網路適配器接受到一段數據,怎麼確定這一段數據是一個完整的幀呢?
這裡面會用到幀界定符,即在幀的頭部和尾部加上一個特殊的控制字元以識別這個幀。
比如:我們假設幀的數據部分(除了各種協議的頭部)裡面的信息是ascii文本,我們知道ascii碼是7位編碼,一共有128個字元,其中99個是列印字元,另外的29個是非列印字元,那麼我們就從非列印字元中抽出一個兩個字元SOH和EOT作為幀的界定符。
但是這樣會出現一個問題,就是 如果數據部分是圖片或者視頻的編碼,那麼這些編碼中可能會出現SOH和EOT,這樣就會導致接收方誤判這是一個幀,從而使得數據出錯。
那麼怎麼解決這個問題呢?這個問題就是數據鏈路層基本問題中的第二個:叫做透明傳輸。
發送方網路適配器在封裝成幀的時候,就會檢驗在數據部分是否有出現界定符,如果出現就在前面加上一個轉義字元,但是我們不能確定數據部分不會出現轉義字元呀,怎麼辦呢?就是在轉義字元前再加上一個轉義字元,只要接收方接受到幀,只要檢測到第一個轉義字元,不管接下來的那個是什麼,只要把第一個轉義字元刪掉就ok了。

使用幀界定符最大的好處,就是讓接收方知道,比如數據只收到一半,那麼接收方就知道這不是一個完整的幀,就會這部分的數據丟棄。
在幀頭幀尾添加界定符的方式,在點對點鏈路中比較常見。

使用界定符來區分幀固然是一種非常好的方式,但是結合到透明傳輸的問題,你不覺得很複雜么。

所以提出了一種比較簡答單的辨別一個幀的方法,就是發送方沒法送一個幀,就等待9us(一段時間間隔)再發送下一幀。這樣的話,就不用使用界定符來界定,因為接收方連續接收到的數據必然是一個幀,這也是建立在物理鏈路可靠的基礎上(假設每一幀的數據在物理鏈路上不會丟失)

這樣的話,也就不存在透明傳輸的問題了。這種方式比較常見在廣播鏈路中

當然還有前導碼的知識,我這裡就不再細講了。

小於46位元組情況下需要填充。
數據鏈路層 規定 一幀的數據部分最小是46位元組---1500位元組,數據部分不到46位元組的會填充到46個位元組。加上18個位元組的幀頭和幀尾,一共是64位元組---1518位元組。

填充信息在幀結構中也沒有,接收端如何移除填充呢?
這個問題的答案在數據段本身,比如數據段部分是ip協議數據報,那麼ip數據報協議頭中有協議的長度信息,這個就是接收端移除填充信息的依據。

但是我這裡想補充一部分,為什麼一幀的最小長度要規定為64位元組呢?
這個點在謝希仁的《計算機網路》這本書中並沒有針對性的講解,但是在廣播鏈路隨機接入的CSMA/CD有提到一部分,在隨機接入的廣播鏈路中,有一個概念叫做碰撞,為了對碰撞的狀況進行分析而引入爭用期(爭用期可以簡單的理解為一根線的端到另一端的往返時間)的概念,規定爭用期時間是5.12us,如果在傳輸速率的10Mb/s的鏈路上,那就5.12us能夠發送512位數據,也就是64個位元組。
只要在5.12us時間內,區域網沒有發生碰撞,那麼發送方之後發送的數據就不會發生碰撞。
只要發生碰撞,一定是發送方發送64個位元組內,所以規定一幀的最小是64位元組。

ps:最後一塊是我自己整理完謝希仁《計算機網路》關於數據鏈路層的一點猜想,有不對希望大家給予指點,謝謝


TCP/IP沒有規定鏈路層,現有的鏈路層和物理層協議一般是乙太網。TCP/IP協議簇關注的是網際互聯和應用到應用的通信。所以TCP/IP協議簇嚴格來講只想解決互聯問題。也就是各種不同體系結構的網路的互聯。只是目前互聯網的下兩層已經基本被乙太網佔領,所以才會有一種鏈路層是TCP/IP一部分的錯覺。乙太網的鏈路層是不可靠的無連接無狀態的不可靠服務,這在乙太網幀格式上就表現出來了。但是TCP可以實現可靠傳輸,雖然在底層沒有實現可靠鏈路。這主要是因為要實現可靠傳輸需要付出很大的代價,參考TCP協議的格式和運作方式就能明白。所以TCP/IP的核心思想是把複雜的東西放在端系統處理,其他地方盡量簡單。這也是網路分層原理的魅力所在,把什麼問題放在什麼地方處理會更加高效合理。當然你也可以發明一個不分層的網路體系。


手機打字費力,先強答一點,佔個坑。
TCP/IP 設計出來的時候就說的是 OSI 七層標準里網路層以及以上的層。TCP/IP 設計的目的就是在各種不同的網路實體間互聯的。對於TCP/IP 來說,只要數據鏈路層能傳遞IP數據包就行。
也就是說,數據鏈路層既可以是可靠的,也可以是不可靠的。底層的事對上層來說是透明的,也就是無所謂的,能提供服務點就行。


可靠性是一種相對說法,可靠性的來源一般是校驗和確認。
鏈路層的可靠性是相對於物理介質傳輸的不可靠來講的,在FCS校驗錯誤時,這個數據幀就會被丟棄,使得交給上層處理的數據幀正確的可能性更大。
幀起始位置是通過前導符實現的,最小報文長度的要求是為了避免碰撞,發送時會補足幀長度,上層協議會有長度欄位指明有效長度。
幀結束位置,要麼是通過幀結束定位符(PPP幀),要麼是通過時間間隔(MAC幀)確定的。


是不可靠的。
鏈路層在封幀時通過增加循環冗餘碼,在兩端進行校驗,可以實現差錯檢測,意思就是說接收端如果收到數據,那就一定是正確的數據(錯誤的被丟了),但並不能保證發動端發送的數據全部都能被收到。
至於想實現可靠傳輸要依靠運輸層TCP協議來實現。


鏈路層是不可靠的。

在光纖出現之前,鏈路上噪音是很大的,會帶來比較高的誤碼率。然後通常會使用ECC技術,把誤碼率降到一定值以下,但並不是零。而且,由於成本的原因,這個允許的誤碼值比較小但不是特別小。過了這一關,鏈路層的任務就完成了,交給上一層。如果上層需要更低的誤碼率,就由上層再想辦法處理。

光纖出現之後,就出現了大變化,光纖本身的誤碼率非常低。這樣鏈路層就相當可靠,需要上層處理的概率就比較小。我估計這是IP層/TCP層的校驗碼比較弱但大家仍然滿意的一個原因。

但整個廣域網不僅有光纖,還有很多電子設備,總的來看,還不能說鏈路層絕對可靠。


首先,network layer的傳輸是不可靠的,換言之,IP傳輸是不可靠的。而transport layer的TCP是可以實現可靠傳輸的。
其次,鏈路層也就是data link layer的傳輸更是不可靠的。
最後,幀填充,可以是IP在切片的時候,尾幀長度不夠,那麼可以理解成network layer做的填充,有效數據的最後一個位元組是特殊欄位。另外,也可以是物理層填充,在沒有路由器或者交換機的網路。
FYI: 最短幀的限制的歷史原因是802.3的CSMA/CD。在shared networks,發送幀的節點在發送當前幀結束前,要求幀頭已經傳到了bus/hub互聯的每個節點,也就是propagation time less than transmission time. 這樣,發送節點在檢測到collision的時候才能知道這是它發的幀和別人衝突了,因為它當前幀還沒發完。這也就要求節點是可以收發同時。這也就多帶出了一個概念,為什麼802.11協議不能用CDMA/CD,只能用CDMA/CA。


只有自己寫封信並親手交給對方是可靠的。無他


不可靠,錯了就丟棄,運輸層的tcp協議使之可靠.


鏈路層實現有很多,沒有重傳,哪來的可靠?


網卡物理層會把bit轉為電信號,網卡之間是有時鐘同步的,fram之間有間隔,為了把frame提出來,frame前還會有前導碼,到了TCPIP,前導碼會被剝離,拿到的就是鏈路層的幀。

對於多填充的幾個位元組,用wireshark抓包很容易看到,為了滿足鏈路層最小幀的限制,比較小的包,報文末尾會有4個0……這個4個0就是填充上去的。


推薦閱讀:

TCP/IP 協議棧中,為什麼選擇 IP 層負責分片?
網橋工作在數據鏈路層,屬於二層設備,但卻能連接不同網段的區域網,相當於三層交換機的功能,有點讓人費解?

TAG:計算機網路 | TCPIP | 網路工程 | 數據鏈路層 |