TCP任何保證可靠的數據傳輸?

什麼是可靠,所謂的可靠就是說發送方發送的數據到達接收方的時候不會發生錯誤,不會丟失,不會亂序。

在網絡層表現看來是這樣的,當從運輸層傳下報文段之後,封裝成ip數據報,然後經過複雜的網絡傳輸到目的主機,在傳輸過程中可能在這個複雜的大網絡中發生數據報的分片,丟失的情況。當到達目的主機後,在目的主機的網絡層進行對收到的數據報進行拼裝,發現這個報文段缺少了一些部分不完整,所以在目的主機的網絡層就是吧這個報恩段丟棄,傳送給源主機一個ICMP報文段請求源主機重新發送這個報文。當這個報文安全無誤的到達目的主機的網絡層之後然後去掉首部直接上相交付給運輸層的接受緩存中。但是在向上交付報文段的時候可能接受緩存滿了導致這個報文段丟棄或者在硬件傳出過程中發生了比特差錯這也不是不可能的。爲了避免數據不可拋傳輸,那麼在運輸層就要對數據的可靠性做一個保證。

 

在運輸層分爲兩個協議UDP和TCP,UDP是一個不可靠的協議,也就是說他僅僅提供複用和分用的功能但是對於比特差錯或者丟棄不做任何處理。但是TCP是一個面向連接的協議,他能夠保證從源主機交付的數據正確無誤的傳輸到目的主機的對應的進程中。所以接下來將要介紹的是TCP是如何保證數據可靠的傳輸的。

 

1.TCP是怎麼保證沒有比特差錯的?

爲了保證接受的報文段是沒有比特差錯的,TCP中引入了這三個機制:

①差錯檢測:也就是引入校驗和。在TCP的首部中有一個佔據16爲的空間用來放置校驗和的結果。在源主機的運輸層開始接受到一個從應用進程傳下來的數據的時候,會將他封裝成一個報文段,加上至少20字節的首部。同時會將這個報文段首部和數據還有僞首部部分一起根據取反碼和的形式計算出校驗和添加到首部中。傳輸到目的主機的運輸層之後,會計算這個通過這個校驗和檢查是否存在比特差錯。

控制消息:當檢測到發生比特差錯之後要對發送發進行信息的反饋使得能夠根據返回決定是否進行重傳。一般理論上會有兩種返回一種是肯定的反饋ACK,在TCP中反饋信息是接收到的分許中最後一個字節序號的下一位。一種是否定反饋,但是爲了減少網絡中的注入分組的數量減少負擔取而代之的是通過發送上一個分組的確認信息表明當下這個分組沒有正確的接收。

重傳:如果接收方接收到的是一個換掉的ACK或者上一個分組的確認之後意味着要再發一遍這個分許。怎麼發後面將分析到。

 

 

2.TCP是怎麼保證重傳的?

發送發重傳之後,接收方值怎麼知道這個分組是重傳的分許,或者說接收方怎麼知道我是不是已經接受了這個分組的?引入了序列化的機制。由於TCP是面向字節流的協議,所以會爲每一個字節編制一個序號。同時在TCP首部中也會有這個序號字段。但是由於一個分組中包含了多個字節,所以說這個TCP首部中的序號是分組中發送多個字節的第一個字節的序號值。

 

3.TCP是怎麼處理分組丟棄的問題的?

以上這幾個問題是基於分組沒有丟棄但是僅僅發生比特差錯的時候。如果發生比特差錯怎麼辦。協議張引入了定時器這個機制。也就是說在某一時刻設置一個定時器,只要在定時器設置的時間內沒有收到對應分組的確認信息,那麼就會重傳對應的一個或者幾個分組。

 

 

4.TCP是如何提高傳輸性能的?

在TCP協議中爲了提高傳輸性能是不可能一次只能發送一個分組介紹到這個分組確認之後在發送下一個分組的,因爲這樣對於信道的利用效率會大大減少,所以爲了提高信道的利用率一般一次發送多個分組,並且將這幾個分組爲單位開始設置定時器。

同時也引入了快速重傳的機制。

 

5.TCP爲什麼引入接受緩存這個數據結構?

 

如果沒有接受緩存的話,或者說只有一個緩存的話,爲了保證接受的數據是按順序傳輸的,所以如果位於x序號之後的序號分組先到達目的主機的運輸層的話必然丟棄,這樣的話將在重傳上花費很大的開銷,所以一般如果有過大的序號達到接收端,那麼會按照序號緩存起來等待之前的序號分許到達,然後一併交付到應用進程。

 

 

TCP可靠傳輸的詳細過程:

 

發送發僞代碼:

NextSeqNum = InitialSeqNumber
SendBase = InitiSeqNumber

loop(forever){
	switch(event){

		event: 接收來自應用程序產生的數據data放入到發送緩存中
				if(定時器沒有開啓)
					start_timer
				將包裝後的報文段交付給網絡層形成IP數據報
				NextSeqNum = NextSeqNum + length(data)
		break;

		event:如果定時器超時
			  發送那個沒有確認的序號最小的分組
			  start_timer
		break;

		event:接收到ACK,將ACK中的確認號賦給y
			  if(y > SendBase){
			  	SendBase = y;
			  	if(目前還有尚未確認的部分){
			  		start_timer
			  	}
			  }else {
			  	開始對y進行計數
			  	if(發送ACK的確認號爲y的個數爲3個的時候){
			  		重新發送序號爲y的哪一個分組
			  	}
			  }
		break;
	}
}


接收方:

若分組在之前未被接收過,則被緩存並且發送ACK(這個ACK是上一個完整交付了的最後一個分組的序號);如果檢查序號接受過則丟棄。

若該分組的序號等於接收窗口的繼續號,則該分組以及以前緩存的序號連續的分組(交付給上層)。發送ACK。

其他情況,忽略該分組。

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章