傳輸控制通訊協定(Transmission Control Protocol, TCP) (下)

來源:互聯網
上載者:User
3.4. 建立一個串連

建立串連應用的是三訊息握手。如果雙方同時都發送SYN也沒有關係,雙方會發現這個SYN中沒有確認,於是就知道了這種情況,通常來說,應該發送一個"reset"段來解決這種情況。三訊息握手減少了串連失敗的可能性。下面就是一個例子,在角括弧是的就是資料區段中的內容和標記。其它的就不多說了。

在第2行,TCP A發送SYN初始化序號,表示它要使用序號100;第3行中,TCP B給出確認,並且期待著A的帶有序號101的資料區段;第4行,TCP A給出確認,而在第5行,它也給出確認,並發送了一些資料,注意第4行的序號與第5號的一樣,因為ACK資訊不佔用序號空間內的序號。同時產生請求的情況如所示,只複雜一點。

使用三訊息握手的主要原因是為了防止使用到期的資料區段。為了這個目的,必須引入新的控制訊息,RESET。如果接收TCP處理非同步狀態,在接收到RESET後返回到LISTEN狀態。如果TCP處理下面幾種狀態ESTABLISHED,FIN-WAIT-1,FIN-WAIT-2,CLOSE-WAIT,CLOSING,LAST-ACK,TIME-WAIT時,放棄串連並通過使用者。我們下面就詳細說明後一種情況。

通過上面的例子,我們可以看出TCP串連是如何從到期資料區段的幹擾下恢複的。請注意第4行和第5行中的RST(RESET訊號)。

半開串連和其它非正常狀態

如果一方在未通過另一方的情況下關閉串連,或雙方雖然失敗而不同步的情況我們稱為半開串連狀態。在一方試圖發送資料時串連會自動RESET。然而這種情況畢竟屬於不正常情況。應該做出相應的處理。如果A處的串連已經關閉,B處並不知道。當B希望發送資料到A時,就會收到RESET訊號,表示這個TCP串連有誤,要中止當前串連。

假設A和B兩個進程相互連信的時候A的TCP發生了失敗,A依靠作業系統支援TCP的存在,通常這種情況下會有恢複機制起作用,當TCP重新恢複的時候,A可能希望從復原點開始工作。這樣A可能會試圖OPEN串連,然後在這個它認為還是開啟的串連上傳送資料,這時A會從本地(也就是A的)TCP上獲得錯誤訊息“未開啟串連”。A的TCP將發送包括SYN的資料區段。下面的例子將顯示這一過程:

上面這個例子中,A方收到的資訊並沒有確認任何東西,這時候A發現出了問題,於是發送了RST控制資訊。另一種情況是發生在A失敗,而B方仍然試圖發送資料時,下面的例子可以表示這種情況,請注意第2行中A對B發送來的資訊不知所云。

在下面的例子中,A方和B方進行的被動串連,它們都在等待SYN資訊。到期的包傳送到B方使B回應了,而收到回應的A卻發現不對頭,傳送RST控制資訊,B方返回被動LISTEN狀態。

現實中的情況太多了,我們列舉一些產生RST控制資訊的規則如下:通常情況下,RST在收到的資訊不是期待的資訊時產生。如果在不能確定時不要輕易發送RST控制資訊。下面有三類情況:

如果串連已經不存在,而發送來的訊息又不是RST,那麼要返回RST。如果想拒絕對不存在的串連進行SYN,可以使用這種辦法。如果到達的資訊有一個ACK域,返回的RST資訊可以從ACK域中取得序號,如果沒有這個域,就把RST的序號設定為0,ACK域被裝置為序號和到達段長度之和。串連仍然處於CLOSE狀態。

如果串連處於非同步狀態(LISTEN,SYN-SENT,SYN-RECEIVED),而且收到的確認是對未發出包的確認或是接收到資料區段的安全層級與不能串連要求的相一一致時,就發送RST。如果SYN未被確認時,而且收到的資料區段的優先順序比要求的優先順序要高,那麼要麼提高本地優先順序(得事先徵得使用者和系統的許可)要麼發送RST;如果接收資料區段的優先順序比要求的優先順序低,就算是匹配了,當然如果對方發現優先順序不對提高了優先順序,在下一個包中提高了優先順序,這就不算是匹配了。如果串連已經進入SYN,那麼接收到資料區段的優先順序必須和本地優先順序一樣,否則發送RST。如果到達的資訊有一個ACK域,返回的RST資訊可以從ACK域中取得序號,如果沒有這個域,就把RST的序號設定為0,ACK域被裝置為序號和到達段長度之和。串連仍然處於與原來相同的狀態。

如果串連處於同步狀態(ESTABLISHED,FIN-WAIT-1,FIN-WAIT-2,CLOSE-WAIT,CLOSING,LAST-ACK,TIME-WAIT),任何超出接收視窗的序號的資料區段都產生如下結果:發出一個空確認資料區段,此段中包括當前發送序號,另外還包括一個確認指出希望接收的下一個資料區段的序號,串連仍然儲存在原來的狀態。如果因為安全級,優先順序之類的問題,那就發送RST訊號然後進入CLOSED狀態。

RST過程

除了SYN-SENT狀態外的其它狀態中,所有的RST資料區段可以通過檢查SEQ域查明。如果序號在接收視窗中,RST是有效。當串連處於SYN-SENT狀態時,如果ACK域確認SYN,那麼RST也是合法的。

RST的接收方首先確認它的合法性,然後進行狀態轉換。如果接收方處於LISTEN狀態,它就忽略RST包。如果接收方處於SYN-RECEIVED狀態,而且以前處於LISTEN狀態,接收方返回LISTEN狀態,否則接收方關閉串連進入CLOSED狀態。當接收方處於其它狀態時,直接關閉串連回到CLOSED狀態。

 

3.5. 關閉串連

CLOSE是一個操作,它的意思就是“本方已經有資料發送”。由於是全雙工系統的,所以會造成一些麻煩,因為接收方對於處理接收方的串連有點麻煩。我們以一種簡單的方式對待CLOSE,發送CLOSE的一方在接收到對方的CLOSED之前,還要繼續接收資料。因此程式可以在一個CLOSE之後初始化幾個SEND,然後開始RECEIVE,直到接收到對方的CLOSED而RECEIVE失敗為止。我們假設TCP可以通知使用者串連關閉,即使仍在RECEIVE也可以,這樣使用者就可以正常關閉了。這樣,TCP可以在串連關閉前可靠地發送資料。下面列舉了三種基本情況:

情況1:本機使用者關閉

這種情況下,可以建立一個FIN段放入發送隊列。TCP不再接收使用者的SEND指令,TCP進入FIN-WAIT-1狀態。RECEIVE在這種狀態下是允許的。所有資料區段和FIN在未接收到確認以前會一直發送。當另一個TCP確認FIN,並發送自己的FIN後,本地的TCP可以確認這個FIN了。請注意,TCP也可以在確認FIN時不返回自己的FIN,直到使用者關閉串連時再返回自己的FIN。

情況2:TCP從網路上接收到一個FIN

如果在沒有請求的情況下收到FIN,TCP可以返回ACK並通知使用者串連已經關閉。使用者可以以CLOSE響應,TCP在發送完剩下的資料後發送自己的FIN,然後TCP等待對這個FIN的確認,在接收到後,它關閉串連。如果確認逾時,可以關閉串連並通知使用者完事。

情況3:雙方同時關閉

雙方同時關閉會導致交換FIN。雙方會在收到對自己FIN的確認後關閉串連。

 

3.6. 優先和安全

TCP的操作必須在兩個優先順序相同的連接埠間進行。TCP使用的優先和安全參數在IP協議中定義。我們這裡所說的安全/間隔就是指的IP中定義的優先,使用者組和處理規定。如果不符合則發送RST。這些內容請大家看上一節中的敘述。TCP在操作過程中也會檢查接收資料區段的優先順序,還可以在操作中提高優先順序。雖然運行在無安全環境中,主機也必須能夠處理安全參數。

3.7. 資料通訊

建立了串連以後就是傳送資料了,TCP通過重新傳送保證每個資料區段到達對方,因為有了重新傳送,所以對方可能接收到兩個相同的包,那就必鬚根據內部的序號判斷哪個資料區段是可以接收的。發送方通過使用SND.NXT跟蹤下一個要發送的資料區段,而接收方則跟蹤RCV.NXT來知道下一個要接收的資料區段。發送方要還未確認的最老的序號儲存於SND.UNA。

當發送方形成資料區段並發送它後SND.NXT增大;當接收方接收到資料區段後RCV.NXT增大並發送確認;當發送方接收到確認後SND.UNA增大。它們三者在不同的時間增大,這是因為傳送時延造成的。而增大多少則由資料區段中資料的大小決定。注意:串連進入ESTABLISHED狀態後,所有的段必須包括當前的確認資訊。而CLOSE使用者操作的性質類型於推操作,這和在接收到的資料區段中的FIN標記一樣。

重傳逾時

因為網路中有不類型的網路,而使用TCP的範圍又很廣,因此重傳逾時必須動態決定。下面給出一個例子,通過例子可以看出確定重傳逾時的過程。下面有兩個變數說明時延的問題,一個是環路時間(RTT),它是由一個序列碼得到的,這個序列碼在發送時給出,在接收到確認時被覆蓋;另一個平滑環路時間(SRTT):

SRTT = ( ALPHA * SRTT ) + ((1-ALPHA) * RTT)

通過上面的式子,可以得到重傳逾時(RTO):

RTO = min[UBOUND,max[LBOUND,(BETA*SRTT)}

其中UBOUND是逾時的上界(如1分鐘),LBOUND是逾時的下界(如1秒鐘),ALPHA是平滑因子(如0.8到0.9),BETA是延時變數(如1.3到2.0)。

傳送緊急訊息

TCP的緊急機制是允許寄件者使接收者接收一些緊急訊息,並讓接收方在接收到這一訊息後立刻通知使用者。這種機制是在資料流是加入一個點,指出這是緊急資料的結束點,當接收方要接收到這個點之前,它會通知使用者進入緊急狀態,在接收到這個點的資料後,它會通知使用者進入通常狀態。如果這個緊急點在使用者進入緊急狀態時更新,這個更新必須對使用者透明。

應用一個緊急域的方法可以達到上述目的,而URG控制標記則指明緊急域是否被使用,而且在資料區段中必須加入指示緊急點的序號,如果沒有這個標記則說明沒有緊急點。如果需要發送緊急資料,發送方必須起碼發送一個位元組。

管理視窗

如果我們學習過網路基礎,我們一定知道有一個視窗協議,TCP中每個資料區段都包括下一個希望接收到的序號。視窗比較大會提高傳送速度,如果傳送過來的資料超過的視窗大小,資料會被拋棄。這樣會加重網路負擔。如果TCP開始時的接收視窗比較大,而到最後這個視窗縮小了,這種作法可不是好辦法。對於健壯的TCP來說,最好不要自己縮小視窗,但要做要準備對方的TCP縮小視窗。

即使發送視窗大小為零,發送TCP也必須做好準備接收資料並且可以發送至少一位新資料。即使接收視窗為零,發送方也會重發,重發間的間隔時間一般為兩分鐘。當接收TCP的接收視窗為零時,在它接收到資料時,它依然會返回確認,其中包括希望收到的序列碼和當前視窗大小(為零)。

發送TCP將資料打成符合當前大小的包,但在重新傳送隊列中可能重新打包。這種重新打包並不是必須的,但是會很有好處。如果一個串連只有單向資料流,視窗資訊可以在確認資訊中得到,這些的序號都是一個,因此沒法區別出誰先誰後。但這並不是一個嚴重的問題。改進的方法是在資料區段中加入最新的期待序號,這樣就可以區別出誰先誰後了。視窗管理對傳送效率有很大影響,下面是一些建議:

當使用更少的大資料而要獲得高效率時分配非常小的視窗使資料以許多小段傳送。對於寄件者來說要避免在發送小資料區段時必須等到視窗大到一定程度再進行。確認不要被延時。接收視窗如果大小為零時,要傳送的資料區段可能被分成越來越小的段。如果發送TCP僅僅發送視窗允許大小的資料區段,可能這些資料區段會被換成比這個段大(或者小)的資料區段發送。接收方時不時地進行視窗大小調整會使大資料區段分為小段,而不成對。盡量把小的視窗合成大的視窗。

3.8. 介面

網路通訊協定的分層結構決定了TCP有兩個介面,向上的使用者介面和下面的介面。對下層接收口的描述不是很清楚,這個工作由下層協議來描述,但是這裡我們也描述一些TCP要使用要的參數。

使用者/TCP介面

下面描述一些TCP命令,這些命令是功能性的,因各系統不同具體實現可能不同。最後,我們必須清楚,不同的TCP實現可能有不同的使用者介面,但是有一些功能是最基本的,本節描述的功能便是這個準系統集。

TCP使用者命令

下面定義的命令與其它進階語言中定義的方法差不多,但有些陷井操作需要的,如SVC,UUO,EMT。下面只是一個功能介紹,具體實現可能大為不同,如有些系統會把這裡的多條命令結合成一條命令使用。為了實現通訊功能,TCP不能只會接收命令,而且能夠返回訊息給它服務的進程,這些訊息包括:

(a) 關於串連的通常訊息,如中斷,遠程關閉等等;

(b) 對使用者命令做出應答,是成功還是失敗。

Open

格式:OPEN (local port, foreign socket, active/passive [, timeout] [, precedence] [, security/compartment] [, options]) -> local connection name

我們假定本地TCP注意到它所服務的進程標記,而且將檢查進程的認證。因實現不同,本網和源地址的TCP認證可能由TCP進行也可以由下層協議進行(如IP協議)。這些考慮主要是基於安全性的考慮。

如果active/passive標記設定為passive,TCP會檢測到達的串連請求,它是被動的,被動的串連可以有一個完全指定的外通訊端用於等待特定的串連或未指定的外通訊端來等待任何呼叫。一個完全定義的被動呼叫可以通過執行一系列的SEND命令而變為主動的。建立一個傳輸控制塊(TCB),其中一部分參數是由OPEN命令參數而來。在主動OPEN時,TCP會立刻開始同步串連。如果給出參數timeout,會允許呼叫者應用於所有TCP資料。如果在timeout規定的時間內還未把資料送到目的地,就關閉串連,一般的預設值是5分鐘。

參數precedence或security/compartment是用於規範使用者對某一串連的安全性的,如果沒有指定則使用預設值。TCP會匹配這兩個參數,只有在security/compartment一致而且接收到的precedence小於等於要求的precedence時才會開啟串連。當串連的precedence大於要求的值時,從接收到的資料區段中取得這一值,並在串連中一直使用這個比較大的值。具體實現時可以給使用者權力控制precedence的決定過程。例如,使用者可以要求precedence必須安全一致,或在提升precedence時要通知使用者。

本地串連名(local connection name)由TCP返回使用者,它可以代替<本地通訊端,外通訊端>標記一個串連。

Send

格式:SEND (local connection name, buffer address, byte count, PUSH flag, URGENT flag [,timeout])

這個命令使指定緩衝區內的資料發向指定串連,如果串連未開啟則返回一個錯誤,一些實現中可能在開啟串連以前調用SEND,由SEND自動開啟串連。如果設定了PUSH標記,資料必須立刻傳送給接收者,而且PUSH位在緩衝區中的最後一個段是必須設定。如果沒有設定,此資料區段就會因為效率的考慮而和下一個SEND命令傳送的資料一起傳送。如果設定了URGENT標記,那就必須象上面所述的一樣緊急處理。傳送方設定的URGENT數目不一定非要等於通知接收方使用者的次數。

如果在OPEN中沒有指定外通訊端,那緩衝區資料會被發送到隱式外通訊端。未使用外通訊端開啟串連的使用者仍然可以SEND,而不用知道外通訊端地址。但是,如果在指定外通訊端前進行SEND,則會出錯。使用者可以使用STATUES確定串連狀態。如果指定了timeout,對於當前串連的目前使用者timeout會更改為新的串連。

最簡單的實現方法就是在沒有把資料發送完畢以前,SEND不把控制權交給發送進程,但是這樣可能會造成死結(例如,雙方都試圖SEND,而不準備RECEIVE),效率也不好。好的實現方法是在發送一段資料後返回控制權給發送進程,當然如果能夠多個SEND同時發送,那更好不過了。有多個SEND需要服務時一般採取先來先服務。

對於本地來說,我們現在假定的是SEND在發送資料後會產生類似中斷的東西告訴發送進程資料發送的情況;當然SEND也可以在發送完後立刻告知進行資料發送的情況。我們可以樂觀地認為發送是成功的,如果發送失敗,串連會因為逾時而關閉。在實現中,即使是同步返回情況,也需要一些非同步訊號,但這些非同步訊號是用於處理串連的,而不是用於處理資料發送的。既然允許多個SEND同時工作,因此有必要區別返回的資訊是哪一個SEND的。具體的情況下面會討論到。

Receive

格式: RECEIVE (local connection name, buffer address, byte count) -> byte count, urgent flag, push flag

此命令分配一個接收緩衝區給指定的串連。如果下面不是一個OPEN命令或者此調用進行未被授權使用此串連返回錯誤。最簡單的實現方法是在緩衝區沒有填充完以前不返回控制權,但這樣可能會造成嚴重的死結。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.