自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

TCP協(xié)議疑難雜癥全景解析

網(wǎng)絡(luò) 網(wǎng)絡(luò)管理
ISO提出了OSI分層網(wǎng)絡(luò)模型,這種分層模型是理論上的,TCP/IP最終實(shí)現(xiàn)了一個(gè)分層的協(xié)議模型,每一個(gè)層次對(duì)應(yīng)一組網(wǎng)絡(luò)協(xié)議完成一組特定的功能,該組網(wǎng)絡(luò)協(xié)議被其下的層次復(fù)用和解復(fù)用。這就是分層模型的本質(zhì),最終所有的邏輯被編碼到線纜或者電磁波。

1.網(wǎng)絡(luò)協(xié)議設(shè)計(jì)

ISO提出了OSI分層網(wǎng)絡(luò)模型,這種分層模型是理論上的,TCP/IP最終實(shí)現(xiàn)了一個(gè)分層的協(xié)議模型,每一個(gè)層次對(duì)應(yīng)一組網(wǎng)絡(luò)協(xié)議完成一組特定的功能,該組網(wǎng)絡(luò)協(xié)議被其下的層次復(fù)用和解復(fù)用。這就是分層模型的本質(zhì),最終所有的邏輯被編碼到線纜或者電磁波。

分層模型是很好理解的,然而對(duì)于每一層的協(xié)議設(shè)計(jì)卻不是那么容易。TCP/IP的漂亮之處在于:協(xié)議越往上層越復(fù)雜。我們把網(wǎng)絡(luò)定義為互相連接在一起的設(shè)備,網(wǎng)絡(luò)的本質(zhì)作用還是“端到端”的通信,然而希望互相通信的設(shè)備并不一定要“直接”連接在一起,因此必然需要一些中間的設(shè)備負(fù)責(zé)轉(zhuǎn)發(fā)數(shù)據(jù),因此就把連接這些中間設(shè)備的線纜上跑的協(xié)議定義為鏈路層協(xié)議,實(shí)際上所謂鏈路其實(shí)就是始發(fā)與一個(gè)設(shè)備,通過(guò)一根線,終止于另一個(gè)設(shè)備。我們把一條鏈路稱為“一跳”。因此一個(gè)端到端的網(wǎng)絡(luò)包含了“很多跳”。

 [[148999]]

2.TCP和IP協(xié)議

終止于IP協(xié)議,我們已經(jīng)可以完成一個(gè)端到端的通信,為何還需要TCP協(xié)議?這是一個(gè)問題,理解了這個(gè)問題,我們就能理解TCP協(xié)議為何成了現(xiàn)在這個(gè)樣子,為何如此“復(fù)雜”,為何又如此簡(jiǎn)單。

正如其名字所展示的那樣,TCP的作用是傳輸控制,也就是控制端到端的傳輸,那為何這種控制不在IP協(xié)議中實(shí)現(xiàn)的。答案很簡(jiǎn)單,那就是這會(huì)增加IP協(xié)議的復(fù)雜性,而IP協(xié)議需要的就是簡(jiǎn)單。這是什么原因造成的呢?

首先我們認(rèn)識(shí)一下為何IP協(xié)議是沙漏的細(xì)腰部分。它的下層是繁多的鏈路層協(xié)議,這些鏈路提供了相互截然不同且相差很遠(yuǎn)的語(yǔ)義,為了互聯(lián)這些異構(gòu)的網(wǎng)絡(luò),我們需要一個(gè)網(wǎng)絡(luò)層協(xié)議起碼要提供一些適配的功能,另外它必然不能提供太多的“保證性服務(wù)”,因?yàn)樯蠈拥谋WC性依賴下層的約束性更強(qiáng)的保證性,你永遠(yuǎn)無(wú)法在一個(gè)100M吞吐量的鏈路之上實(shí)現(xiàn)的IP協(xié)議保證1000M的吞吐量...

IP協(xié)議設(shè)計(jì)為分組轉(zhuǎn)發(fā)協(xié)議,每一跳都要經(jīng)過(guò)一個(gè)中間節(jié)點(diǎn),路由的設(shè)計(jì)是TCP/IP網(wǎng)絡(luò)的另一大創(chuàng)舉,這樣,IP協(xié)議就無(wú)需方向性,路由信息和協(xié)議本身不再?gòu)?qiáng)關(guān)聯(lián),它們僅僅通過(guò)IP地址來(lái)關(guān)聯(lián),因此,IP協(xié)議更加簡(jiǎn)單。路由器作為中間節(jié)點(diǎn)也不能太復(fù)雜,這涉及到成本問題,因此路由器只負(fù)責(zé)選路以及轉(zhuǎn)發(fā)數(shù)據(jù)包。

因此傳輸控制協(xié)議必然需要在端點(diǎn)實(shí)現(xiàn)。在我們?cè)斦凾CP協(xié)議之前,首先要看一下它不能做什么,由于IP協(xié)議不提供保證,TCP也不能提供依賴于IP下層鏈路的這種保證,比如帶寬,比如時(shí)延,這些都是鏈路層決定的,既然IP協(xié)議無(wú)法修補(bǔ),TCP也不能,然而它卻能修正始于IP層的一些“不可保證性質(zhì)”,這些性質(zhì)包括IP層的不可靠,IP層的不按順序,IP層的無(wú)方向/無(wú)連接。

將該小節(jié)總結(jié)一下,TCP/IP模型從下往上,功能增加,需要實(shí)現(xiàn)的設(shè)備減少,然而設(shè)備的復(fù)雜性卻在增加,這樣保證了成本的最小化,至于性能或者因素,靠軟件來(lái)調(diào)節(jié)吧,TCP協(xié)議就是這樣的軟件,實(shí)際上最開始的時(shí)候,TCP并不考慮性能,效率,公平性,正是考慮了這些,TCP協(xié)議才復(fù)雜了起來(lái)。

3.TCP協(xié)議

這是一個(gè)純軟件協(xié)議,為何將其設(shè)計(jì)上兩個(gè)端點(diǎn),參見上一小節(jié),本節(jié)詳述TCP協(xié)議,中間也穿插一些簡(jiǎn)短的論述。

3.1.TCP協(xié)議

確切的說(shuō),TCP協(xié)議有兩重身份,作為網(wǎng)絡(luò)協(xié)議,它彌補(bǔ)了IP協(xié)議盡力而為服務(wù)的不足,實(shí)現(xiàn)了有連接,可靠傳輸,報(bào)文按序到達(dá)。作為一個(gè)主機(jī)軟件,它和UDP以及左右的傳輸層協(xié)議隔離了主機(jī)服務(wù)和網(wǎng)絡(luò),它們可以被看做是一個(gè)多路復(fù)用/解復(fù)用器,將諸多的主機(jī)進(jìn)程數(shù)據(jù)復(fù)用/解復(fù)用到IP層??梢钥闯觯还軓哪膫€(gè)角度,TCP都作為一個(gè)接口存在,作為網(wǎng)絡(luò)協(xié)議,它和對(duì)端的TCP接口,實(shí)現(xiàn)TCP的控制邏輯,作為多路復(fù)用/解復(fù)用器,它和下層IP協(xié)議接口,實(shí)現(xiàn)協(xié)議棧的功能,而這正是分層網(wǎng)絡(luò)協(xié)議模型的基本定義(兩類接口,一類和下層接口,另一類和對(duì)等層接口)。

我們習(xí)慣于將TCP作為協(xié)議棧的最頂端,而不把應(yīng)用層協(xié)議當(dāng)成協(xié)議棧的一部分,這部分是因?yàn)閼?yīng)用層被TCP/UDP解復(fù)用了之后,呈現(xiàn)出了一種太復(fù)雜的局面,應(yīng)用層協(xié)議用一種不同截然不同的方式被解釋,應(yīng)用層協(xié)議習(xí)慣于用類似ASN.1標(biāo)準(zhǔn)來(lái)封裝,這正體現(xiàn)了TCP協(xié)議作為多路復(fù)用/解復(fù)用器的重要性,由于直接和應(yīng)用接口,它可以很容易直接被應(yīng)用控制,實(shí)現(xiàn)不同的傳輸控制策略,這也是TCP被設(shè)計(jì)到離應(yīng)用不太遠(yuǎn)的地方的原因之一。

總之,TCP要點(diǎn)有四,一曰有連接,二曰可靠傳輸,三曰數(shù)據(jù)按照到達(dá),四曰端到端流量控制。注意,TCP被設(shè)計(jì)時(shí)只保證這四點(diǎn),此時(shí)它雖然也有些問題,然而很簡(jiǎn)單,然而更大的問題很快呈現(xiàn)出來(lái),使之不得不考慮和IP網(wǎng)絡(luò)相關(guān)的東西,比如公平性,效率,因此增加了擁塞控制,這樣TCP就成了現(xiàn)在這個(gè)樣子。

3.2.有連接,可靠傳輸,數(shù)據(jù)按序到達(dá)的TCP

IP協(xié)議是沒有方向的,數(shù)據(jù)報(bào)傳輸能到達(dá)對(duì)端全靠路由,因此它是一跳一跳地到達(dá)對(duì)端的,只要有一跳沒有到達(dá)對(duì)端的路由,那么數(shù)據(jù)傳輸將失敗,其實(shí)路由也是互聯(lián)網(wǎng)的核心之一,實(shí)際上IP層提供的核心基本功能有兩點(diǎn),第一點(diǎn)是地址管理,第二點(diǎn)就是路由選路。TCP利用了IP路由這個(gè)簡(jiǎn)單的功能,因此TCP不必考慮選路,這又一個(gè)它被設(shè)計(jì)成端到端協(xié)議的原因。

既然IP已經(jīng)能盡力讓單獨(dú)的數(shù)據(jù)報(bào)到達(dá)對(duì)端,那么TCP就可以在這種盡力而為的網(wǎng)絡(luò)上實(shí)現(xiàn)其它的更加嚴(yán)格的控制功能。TCP給無(wú)連接的IP網(wǎng)絡(luò)通信增加了連接性,確認(rèn)了已經(jīng)發(fā)送出去的數(shù)據(jù)的狀態(tài),并且保證了數(shù)據(jù)的順序。

3.2.1.有連接

這是TCP的基本,因?yàn)楹罄m(xù)的傳輸?shù)目煽啃砸约皵?shù)據(jù)順序性都依賴于一條連接,這是最簡(jiǎn)單的實(shí)現(xiàn)方式,因此TCP被設(shè)計(jì)成一種基于流的協(xié)議,既然TCP需要事先建立連接,之后傳輸多少數(shù)據(jù)就無(wú)所謂了,只要是同一連接的數(shù)據(jù)能識(shí)別出來(lái)即可。

疑難雜癥1:3次握手和4次揮手

TCP使用3次握手建立一條連接,該握手初始化了傳輸可靠性以及數(shù)據(jù)順序性必要的信息,這些信息包括兩個(gè)方向的初始序列號(hào),確認(rèn)號(hào)由初始序列號(hào)生成,使用3次握手是因?yàn)?次握手已經(jīng)準(zhǔn)備好了傳輸可靠性以及數(shù)據(jù)順序性所必要的信息,該握手的第3次實(shí)際上并不是需要單獨(dú)傳輸?shù)模耆梢院蛿?shù)據(jù)一起傳輸。

TCP使用4次揮手拆除一條連接,為何需要4次呢?因?yàn)門CP是一個(gè)全雙工協(xié)議,必須單獨(dú)拆除每一條信道。注意,4次揮手和3次握手的意義是不同的,很多人都會(huì)問為何建立連接是3次握手,而拆除連接是4次揮手。3次握手的目的很簡(jiǎn)單,就是分配資源,初始化序列號(hào),這時(shí)還不涉及數(shù)據(jù)傳輸,3次就足夠做到這個(gè)了,而4次揮手的目的是終止數(shù)據(jù)傳輸,并回收資源,此時(shí)兩個(gè)端點(diǎn)兩個(gè)方向的序列號(hào)已經(jīng)沒有了任何關(guān)系,必須等待兩方向都沒有數(shù)據(jù)傳輸時(shí)才能拆除虛鏈路,不像初始化時(shí)那么簡(jiǎn)單,發(fā)現(xiàn)SYN標(biāo)志就初始化一個(gè)序列號(hào)并確認(rèn)SYN的序列號(hào)。因此必須單獨(dú)分別在一個(gè)方向上終止該方向的數(shù)據(jù)傳輸。

疑難雜癥2:TIME_WAIT狀態(tài)

為何要有這個(gè)狀態(tài),原因很簡(jiǎn)單,那就是每次建立連接的時(shí)候序列號(hào)都是隨機(jī)產(chǎn)生的,并且這個(gè)序列號(hào)是32位的,會(huì)回繞?,F(xiàn)在我來(lái)解釋這和TIME_WAIT有什么關(guān)系。

任何的TCP分段都要在盡力而為的IP網(wǎng)絡(luò)上傳輸,中間的路由器可能會(huì)隨意的緩存任何的IP數(shù)據(jù)報(bào),它并不管這個(gè)IP數(shù)據(jù)報(bào)上被承載的是什么數(shù)據(jù),然而根據(jù)經(jīng)驗(yàn)和互聯(lián)網(wǎng)的大小,一個(gè)IP數(shù)據(jù)報(bào)最多存活MSL(這是根據(jù)地球表面積,電磁波在各種介質(zhì)中的傳輸速率以及IP協(xié)議的TTL等綜合推算出來(lái)的,如果在火星上,這個(gè)MSL會(huì)大得多...)。

現(xiàn)在我們考慮終止連接時(shí)的被動(dòng)方發(fā)送了一個(gè)FIN,然后主動(dòng)方回復(fù)了一個(gè)ACK,然而這個(gè)ACK可能會(huì)丟失,這會(huì)造成被動(dòng)方重發(fā)FIN,這個(gè)FIN可能會(huì)在互聯(lián)網(wǎng)上存活MSL。

如果沒有TIME_WAIT的話,假設(shè)連接1已經(jīng)斷開,然而其被動(dòng)方最后重發(fā)的那個(gè)FIN(或者FIN之前發(fā)送的任何TCP分段)還在網(wǎng)絡(luò)上,然而連接2重用了連接1的所有的5元素(源IP,目的IP,TCP,源端口,目的端口),剛剛將建立好連接,連接1遲到的FIN到達(dá)了,這個(gè)FIN將以比較低但是確實(shí)可能的概率終止掉連接2.

為何說(shuō)是概率比較低呢?這涉及到一個(gè)匹配問題,遲到的FIN分段的序列號(hào)必須落在連接2的一方的期望序列號(hào)范圍之內(nèi)。雖然這種巧合很少發(fā)生,但確實(shí)會(huì)發(fā)生,畢竟初始序列號(hào)是隨機(jī)產(chǎn)生了。因此終止連接的主動(dòng)方必須在接受了被動(dòng)方且回復(fù)了ACK之后等待2*MSL時(shí)間才能進(jìn)入CLOSE狀態(tài),之所以乘以2是因?yàn)檫@是保守的算法,最壞情況下,針對(duì)被動(dòng)方的ACK在以最長(zhǎng)路線(經(jīng)歷一個(gè)MSL)經(jīng)過(guò)互聯(lián)網(wǎng)馬上到達(dá)被動(dòng)方時(shí)丟失。

為了應(yīng)對(duì)這個(gè)問題,RFC793對(duì)初始序列號(hào)的生成有個(gè)建議,那就是設(shè)定一個(gè)基準(zhǔn),在這個(gè)基準(zhǔn)之上搞隨機(jī),這個(gè)基準(zhǔn)就是時(shí)間,我們知道時(shí)間是單調(diào)遞增的。然而這仍然有問題,那就是回繞問題,如果發(fā)生回繞,那么新的序列號(hào)將會(huì)落到一個(gè)很低的值。因此最好的辦法就是避開“重疊”,其含義就是基準(zhǔn)之上的隨機(jī)要設(shè)定一個(gè)范圍。

要知道,很多人很不喜歡看到服務(wù)器上出現(xiàn)大量的TIME_WAIT狀態(tài)的連接,因此他們將TIME_WAIT的值設(shè)置的很低,這雖然在大多數(shù)情況下可行,然而確實(shí)也是一種冒險(xiǎn)行為。最好的方式就是,不要重用一個(gè)連接。

疑難雜癥3:重用一個(gè)連接和重用一個(gè)套接字

這是根本不同的,單獨(dú)重用一個(gè)套接字一般不會(huì)有任何問題,因?yàn)門CP是基于連接的。比如在服務(wù)器端出現(xiàn)了一個(gè)TIME_WAIT連接,那么該連接標(biāo)識(shí)了一個(gè)五元素,只要客戶端不使用相同的源端口,連接服務(wù)器是沒有問題的,因?yàn)檫t到的FIN永遠(yuǎn)不會(huì)到達(dá)這個(gè)連接。記住,一個(gè)五元素標(biāo)識(shí)了一個(gè)連接,而不是一個(gè)套接字(當(dāng)然,對(duì)于BSD套接字而言,服務(wù)端的accept套接字確實(shí)標(biāo)識(shí)了一個(gè)連接)。

3.2.2.傳輸可靠性

基本上傳輸可靠性是靠確認(rèn)號(hào)實(shí)現(xiàn)的,也就是說(shuō),每發(fā)送一個(gè)分段,接下來(lái)接收端必然要發(fā)送一個(gè)確認(rèn),發(fā)送端收到確認(rèn)后才可以發(fā)送下一個(gè)字節(jié)。這個(gè)原則最簡(jiǎn)單不過(guò)了,教科書上的“停止-等待”協(xié)議就是這個(gè)原則的字節(jié)版本,只是TCP使用了滑動(dòng)窗口機(jī)制使得每次不一定發(fā)送一個(gè)字節(jié),但是這是后話,本節(jié)僅僅談一下確認(rèn)的超時(shí)機(jī)制。

怎么知道數(shù)據(jù)到達(dá)對(duì)端呢?那就是對(duì)端發(fā)送一個(gè)確認(rèn),但是如果一直收不到對(duì)端的確認(rèn),發(fā)送端等多久呢?如果一直等下去,那么將無(wú)法發(fā)現(xiàn)數(shù)據(jù)的丟失,協(xié)議將不可用,如果等待時(shí)間過(guò)短,可能確認(rèn)還在路上,因此等待時(shí)間是個(gè)問題,另外如何去管理這個(gè)超時(shí)時(shí)間也是一個(gè)問題。

疑難雜癥4:超時(shí)時(shí)間的計(jì)算

絕對(duì)不能隨意去揣測(cè)超時(shí)的時(shí)間,而應(yīng)該給出一個(gè)精確的算法去計(jì)算。毫無(wú)疑問,一個(gè)TCP分段的回復(fù)到達(dá)的時(shí)間就是一個(gè)數(shù)據(jù)報(bào)往返的時(shí)間,因此標(biāo)準(zhǔn)定義了一個(gè)新的名詞RTT,代表一個(gè)TCP分段的往返時(shí)間。然而我們知道,IP網(wǎng)絡(luò)是盡力而為的,并且路由是動(dòng)態(tài)的,且路由器會(huì)毫無(wú)先兆的緩存或者丟棄任何的數(shù)據(jù)報(bào),因此這個(gè)RTT是需要?jiǎng)討B(tài)測(cè)量的,也就是說(shuō)起碼每隔一段時(shí)間就要測(cè)量一次,如果每次都一樣,萬(wàn)事大吉,然而世界并非如你所愿,因此我們需要找到的恰恰的一個(gè)“平均值”,而不是一個(gè)準(zhǔn)確值。

這個(gè)平均值如果僅僅直接通過(guò)計(jì)算多次測(cè)量值取算術(shù)平均,那是不恰當(dāng)?shù)模驗(yàn)閷?duì)于數(shù)據(jù)傳輸延時(shí),我們必須考慮的路徑延遲的瞬間抖動(dòng),否則如果兩次測(cè)量值分別為2和98,那么超時(shí)值將是50,這個(gè)值對(duì)于2而言,太大了,結(jié)果造成了數(shù)據(jù)的延遲過(guò)大(本該重傳的等待了好久才重傳),然而對(duì)于98而言,太小了,結(jié)果造成了過(guò)度重傳(路途遙遠(yuǎn),本該很慢,結(jié)果大量重傳已經(jīng)正確確認(rèn)但是遲到的TCP分段)。

因此,除了考慮每?jī)纱螠y(cè)量值的偏差之外,其變化率也應(yīng)該考慮在內(nèi),如果變化率過(guò)大,則通過(guò)以變化率為自變量的函數(shù)為主計(jì)算RTT(如果陡然增大,則取值為比較大的正數(shù),如果陡然減小,則取值為比較小的負(fù)數(shù),然后和平均值加權(quán)求和),反之如果變化率很小,則取測(cè)量平均值。這是不言而喻的,這個(gè)算法至今仍然工作的很好。

疑難雜癥5:超時(shí)計(jì)時(shí)器的管理-每連接單一計(jì)時(shí)器

很顯然,對(duì)每一個(gè)TCP分段都生成一個(gè)計(jì)時(shí)器是最直接的方式,每個(gè)計(jì)時(shí)器在RTT時(shí)間后到期,如果沒有收到確認(rèn),則重傳。然而這只是理論上的合理,對(duì)于大多數(shù)操作系統(tǒng)而言,這將帶來(lái)巨大的內(nèi)存開銷和調(diào)度開銷,因此采取每一個(gè)TCP連接單一計(jì)時(shí)器的設(shè)計(jì)則成了一個(gè)默認(rèn)的選擇??墒菃我坏挠?jì)時(shí)器怎么管理如此多的發(fā)出去的TCP分段呢?又該如何來(lái)設(shè)計(jì)單一的計(jì)時(shí)器呢。

設(shè)計(jì)單一計(jì)時(shí)器有兩個(gè)原則:1.每一個(gè)報(bào)文在長(zhǎng)期收不到確認(rèn)都必須可以超時(shí);2.這個(gè)長(zhǎng)期收不到中長(zhǎng)期不能和測(cè)量的RTT相隔太遠(yuǎn)。因此RFC2988定義一套很簡(jiǎn)單的原則:

a.發(fā)送TCP分段時(shí),如果還沒有重傳定時(shí)器開啟,那么開啟它。

b.發(fā)送TCP分段時(shí),如果已經(jīng)有重傳定時(shí)器開啟,不再開啟它。

c.收到一個(gè)非冗余ACK時(shí),如果有數(shù)據(jù)在傳輸中,重新開啟重傳定時(shí)器。

d.收到一個(gè)非冗余ACK時(shí),如果沒有數(shù)據(jù)在傳輸中,則關(guān)閉重傳定時(shí)器。

我們看看這4條規(guī)則是如何做到以上兩點(diǎn)的,根據(jù)a和c(在c中,注意到ACK是非冗余的),任何TCP分段只要不被確認(rèn),超時(shí)定時(shí)器總會(huì)超時(shí)的。然而為何需要c呢?只有規(guī)則a存在的話,也可以做到原則1。實(shí)際上確實(shí)是這樣的,但是為了不會(huì)出現(xiàn)過(guò)早重傳,才添加了規(guī)則c,如果沒有規(guī)則c,那么萬(wàn)一在重傳定時(shí)器到期前,發(fā)送了一些數(shù)據(jù),這樣在定時(shí)器到期后,除了很早發(fā)送的數(shù)據(jù)能收到ACK外,其它稍晚些發(fā)送的數(shù)據(jù)的ACK都將不會(huì)到來(lái),因此這些數(shù)據(jù)都將被重傳。有了規(guī)則c之后,只要有分段ACK到來(lái),則重置重傳定時(shí)器,這很合理,因此大多數(shù)正常情況下,從數(shù)據(jù)的發(fā)出到ACK的到來(lái)這段時(shí)間以及計(jì)算得到的RTT以及重傳定時(shí)器超時(shí)的時(shí)間這三者相差并不大,一個(gè)ACK到來(lái)后重置定時(shí)器可以保護(hù)后發(fā)的數(shù)據(jù)不被過(guò)早重傳。

這里面還有一些細(xì)節(jié)需要說(shuō)明。一個(gè)ACK到來(lái)了,說(shuō)明后續(xù)的ACK很可能會(huì)依次到來(lái),也就是說(shuō)丟失的可能性并不大,另外,即使真的有后發(fā)的TCP分段丟失現(xiàn)象發(fā)生,也會(huì)在最多2倍定時(shí)器超時(shí)時(shí)間的范圍內(nèi)被重傳(假設(shè)該報(bào)文是第一個(gè)報(bào)文發(fā)出啟動(dòng)定時(shí)器之后馬上發(fā)出的,丟失了,第一個(gè)報(bào)文的ACK到來(lái)后又重啟了定時(shí)器,又經(jīng)過(guò)了一個(gè)超時(shí)時(shí)間才會(huì)被重傳)。雖然這里還沒有涉及擁塞控制,但是可見網(wǎng)絡(luò)擁塞會(huì)引起丟包,丟包會(huì)引起重傳,過(guò)度重傳反過(guò)來(lái)加重網(wǎng)絡(luò)擁塞,設(shè)置規(guī)則c的結(jié)果可以緩解過(guò)多的重傳,畢竟將啟動(dòng)定時(shí)器之后發(fā)送的數(shù)據(jù)的重傳超時(shí)時(shí)間拉長(zhǎng)了最多一倍左右。最多一倍左右的超時(shí)偏差做到了原則2,即“這個(gè)長(zhǎng)期收不到中長(zhǎng)期不能和測(cè)量的RTT相隔太遠(yuǎn)”。

還有一點(diǎn),如果是一個(gè)發(fā)送序列的最后一個(gè)分段丟失了,后面就不會(huì)收到冗余ACK,這樣就只能等到超時(shí)了,并且超時(shí)時(shí)間幾乎是肯定會(huì)比定時(shí)器超時(shí)時(shí)間更長(zhǎng)。如果這個(gè)分段是在發(fā)送序列的靠后的時(shí)間發(fā)送的且和前面的發(fā)送時(shí)間相隔時(shí)間較遠(yuǎn),則其超時(shí)時(shí)間不會(huì)很大,反之就會(huì)比較大。

疑難雜癥6:何時(shí)測(cè)量RTT

目前很多TCP實(shí)現(xiàn)了時(shí)間戳,這樣就方便多了,發(fā)送端再也不需要保存發(fā)送分段的時(shí)間了,只需要將其放入?yún)f(xié)議頭的時(shí)間戳字段,然后接收端將其回顯在ACK即可,然后發(fā)送端收到ACK后,取出時(shí)間戳,和當(dāng)前時(shí)間做算術(shù)差,即可完成一次RTT的測(cè)量。

3.2.3.數(shù)據(jù)順序性

基本上傳輸可靠性是靠序列號(hào)實(shí)現(xiàn)的。

疑難雜癥7:確認(rèn)號(hào)和超時(shí)重傳

確認(rèn)號(hào)是一個(gè)很詭異的東西,因?yàn)門CP的發(fā)送端對(duì)于發(fā)送出去的一個(gè)數(shù)據(jù)序列,它只要收到一個(gè)確認(rèn)號(hào)就認(rèn)為確認(rèn)號(hào)前面的數(shù)據(jù)都被收到了,即使前面的某個(gè)確認(rèn)號(hào)丟失了,也就是說(shuō),發(fā)送端只認(rèn)最后一個(gè)確認(rèn)號(hào)。這是合理的,因?yàn)榇_認(rèn)號(hào)是接收端發(fā)出的,接收端只確認(rèn)按序到達(dá)的最后一個(gè)TCP分段。

另外,發(fā)送端重發(fā)了一個(gè)TCP報(bào)文并且接收到該TCP分段的確認(rèn)號(hào),并不能說(shuō)明這個(gè)重發(fā)的報(bào)文被接收了,也可能是數(shù)據(jù)早就被接收了,只是由于其ACK丟失或者其ACK延遲到達(dá)導(dǎo)致了超時(shí)。值得說(shuō)明的是,接收端會(huì)丟棄任何重復(fù)的數(shù)據(jù),即使丟棄了重復(fù)的數(shù)據(jù),其ACK還是會(huì)照發(fā)不誤的。

標(biāo)準(zhǔn)的早期TCP實(shí)現(xiàn)為,只要一個(gè)TCP分段丟失,即使后面的TCP分段都被完整收到,發(fā)送端還是會(huì)重傳從丟失分段開始的所有報(bào)文,這就會(huì)導(dǎo)致一個(gè)問題,那就是重傳風(fēng)暴,一個(gè)分段丟失,引起大量的重傳。這種風(fēng)暴實(shí)則不必要的,因?yàn)榇蠖鄶?shù)的TCP實(shí)現(xiàn)中,接收端已經(jīng)緩存了亂序的分段,這些被重傳的丟失分段之后的分段到達(dá)接收端之后,很大的可能性是被丟棄。關(guān)于這一點(diǎn)在擁塞控制被引入之后還會(huì)提及(問題先述為快:本來(lái)報(bào)文丟失導(dǎo)致超時(shí)就說(shuō)明網(wǎng)絡(luò)很可能已然擁塞,重傳風(fēng)暴只能加重其擁塞程度)。

疑難雜癥8:亂序數(shù)據(jù)緩存以及選擇確認(rèn)

TCP是保證數(shù)據(jù)順序的,但是并不意味著它總是會(huì)丟棄亂序的TCP分段,具體會(huì)不會(huì)丟棄是和具體實(shí)現(xiàn)相關(guān)的,RFC建議如果內(nèi)存允許,還是要緩存這些亂序到來(lái)的分段,然后實(shí)現(xiàn)一種機(jī)制等到可以拼接成一個(gè)按序序列的時(shí)候?qū)⒕彺娴姆侄纹唇?,這就類似于IP協(xié)議中的分片一樣,但是由于IP數(shù)據(jù)報(bào)是不確認(rèn)的,因此IP協(xié)議的實(shí)現(xiàn)必須緩存收到的任何分片而不能將其丟棄,因?yàn)閬G棄了一個(gè)IP分片,它就再也不會(huì)到來(lái)了。

現(xiàn)在,TCP實(shí)現(xiàn)了一種稱為選擇確認(rèn)的方式,接收端會(huì)顯式告訴發(fā)送端需要重傳哪些分段而不需要重傳哪些分段。這無(wú)疑避免了重傳風(fēng)暴。

疑難雜癥9:TCP序列號(hào)的回繞的問題

TCP的序列號(hào)回繞會(huì)引起很多的問題,比如序列號(hào)為s的分段發(fā)出之后,m秒后,序列號(hào)比s小的序列號(hào)為j的分段發(fā)出,只不過(guò)此時(shí)的j比上一個(gè)s多了一圈,這就是回繞問題,那么如果這后一個(gè)分段到達(dá)接收端,這就會(huì)引發(fā)徹底亂序-本來(lái)j該在s后面,結(jié)果反而到達(dá)前面了,這種亂序是TCP協(xié)議檢查不出來(lái)的。我們仔細(xì)想一下,這種情況確實(shí)會(huì)發(fā)生,數(shù)據(jù)分段并不是一個(gè)字節(jié)一個(gè)字節(jié)發(fā)送出去的,如果存在一個(gè)速率為1Gbps的網(wǎng)絡(luò),TCP發(fā)送端1秒會(huì)發(fā)送125MB的數(shù)據(jù),32位的序列號(hào)空間能傳輸2的32次方個(gè)字節(jié),也就是說(shuō)32秒左右就會(huì)發(fā)生回繞,我們知道這個(gè)值遠(yuǎn)小于MSL值,因此會(huì)發(fā)生的。

有個(gè)細(xì)節(jié)可能會(huì)引起誤會(huì),那就是TCP的窗口大小空間是序列號(hào)空間的一半,這樣恰好在滿載情況下,數(shù)據(jù)能填滿發(fā)送窗口和接收窗口,序列號(hào)空間正好夠用。然而事實(shí)上,TCP的初始序列號(hào)并不是從0開始的,而是隨機(jī)產(chǎn)生的(當(dāng)然要輔助一些更精妙的算法),因此如果初始序列號(hào)比較接近2的32次方,那么很快就會(huì)回繞。

當(dāng)然,如今可以用時(shí)間戳選項(xiàng)來(lái)輔助作為序列號(hào)的一個(gè)識(shí)別的部分,接收端遇到回繞的情況,需要比較時(shí)間戳,我們知道,時(shí)間戳是單調(diào)遞增的,雖然也會(huì)回繞,然而回繞時(shí)間卻要長(zhǎng)很多。這只是一種策略,在此不詳談。還有一個(gè)很現(xiàn)實(shí)的問題,理論上序列號(hào)會(huì)回繞,但是實(shí)際上,有多少TCP的端點(diǎn)主機(jī)直接架設(shè)在1G的網(wǎng)絡(luò)線纜兩端并且接收方和發(fā)送方的窗口還能恰好被同時(shí)填滿。另外,就算發(fā)生了回繞,也不是一件特別的事情,回繞在計(jì)算機(jī)里面太常見了,只需要能識(shí)別出來(lái)即可解決,對(duì)于TCP的序列號(hào)而言,在高速網(wǎng)絡(luò)(點(diǎn)對(duì)點(diǎn)網(wǎng)絡(luò)或者以太網(wǎng))的兩端,數(shù)據(jù)發(fā)生亂序的可能性很小,因此當(dāng)收到一個(gè)序列號(hào)突然變?yōu)?或者終止序列號(hào)小于起始序列號(hào)的情況后,很容易辨別出來(lái),只需要和前一個(gè)確認(rèn)的分段比較即可,如果在一個(gè)經(jīng)過(guò)路由器的網(wǎng)絡(luò)兩端,會(huì)引發(fā)IP數(shù)據(jù)報(bào)的順序重排,對(duì)于TCP而言,雖然還會(huì)發(fā)生回繞,也會(huì)慢得多,且考慮到擁塞窗口(目前還沒有引入)一般不會(huì)太大,窗口也很難被填滿到65536。

#p#

3.2.4.端到端的流量控制

端到端的流量控制使用滑動(dòng)窗口來(lái)實(shí)現(xiàn)。滑動(dòng)窗口的原理非常簡(jiǎn)單,基本就是一個(gè)生產(chǎn)者/消費(fèi)者模型

疑難雜癥10:流量控制的真實(shí)意義

很多人以為流量控制會(huì)很有效的協(xié)調(diào)兩端的流量匹配,確實(shí)是這樣,但是如果你考慮到網(wǎng)絡(luò)的利用率問題,TCP的流量控制機(jī)制就不那么完美了,造成這種局面的原因在于,滑動(dòng)窗口只是限制了最大發(fā)送的數(shù)據(jù),卻沒有限制最小發(fā)送的數(shù)據(jù),結(jié)果導(dǎo)致一些很小的數(shù)據(jù)被封裝成TCP分段,報(bào)文協(xié)議頭所占的比例過(guò)于大,造成網(wǎng)絡(luò)利用率下降,這就引出了接下來(lái)的內(nèi)容,那就是端到端意義的TCP協(xié)議效率。

~~~~~~~~~~~~~~~~~~~~

承上啟下

終于到了闡述問題的時(shí)候了,以上的TCP協(xié)議實(shí)現(xiàn)的非常簡(jiǎn)單,這也是TCP的標(biāo)準(zhǔn)實(shí)現(xiàn),然而很快我們就會(huì)發(fā)現(xiàn)各種各樣的問題。這些問題導(dǎo)致了標(biāo)準(zhǔn)化協(xié)會(huì)對(duì)TCP協(xié)議進(jìn)行了大量的修補(bǔ),這些修補(bǔ)雜糅在一起讓人們有些云里霧里,不知所措。本文檔就旨在分離這些雜亂的情況,實(shí)際上,根據(jù)RFC,這些雜亂的情況都是可以找到其單獨(dú)的發(fā)展軌跡的。

~~~~~~~~~~~~~~~~~~~~

4.端到端意義上的TCP協(xié)議效率

4.1.三個(gè)問題以及解決

問題1描述:接收端處理慢,導(dǎo)致接收窗口被填滿

這明顯是速率不匹配引發(fā)的問題,然而即使速率不匹配,只要滑動(dòng)窗口能協(xié)調(diào)好它們的速率就好,要快都快,要慢都慢,事實(shí)上滑動(dòng)窗口在這一點(diǎn)上做的很好。但是如果我們不得不從效率上來(lái)考慮問題的話,事實(shí)就不那么樂觀了??紤]此時(shí)接收窗口已然被填滿,慢速的應(yīng)用程序慢騰騰的讀取了一個(gè)字節(jié),空出一個(gè)位置,然后通告給TCP的發(fā)送端,發(fā)送端得知空出一個(gè)位置,馬上發(fā)出一個(gè)字節(jié),又將接收端填滿,然后接收應(yīng)用程序又一次慢騰騰...這就是糊涂窗口綜合癥,一個(gè)大多數(shù)人都很熟悉的詞。這個(gè)問題極大的浪費(fèi)了網(wǎng)絡(luò)帶寬,降低了網(wǎng)絡(luò)利用率。好比從大同拉100噸煤到北京需要一輛車,拉1Kg煤到北京也需要一輛車(超級(jí)夸張的一個(gè)例子,請(qǐng)不要相信),但是一輛車開到北京的開銷是一定的...

問題1解決:窗口通告

對(duì)于問題1,很顯然問題出在接收端,我們沒有辦法限制發(fā)送端不發(fā)送小分段,但是卻可以限制接收端通告小窗口,這是合理的,這并不影響應(yīng)用程序,此時(shí)經(jīng)典的延遲/吞吐量反比律將不再適用,因?yàn)榻邮沾翱谑菨M的,其空出一半空間表示還有一半空間有數(shù)據(jù)沒有被應(yīng)用讀取,和其空出一個(gè)字節(jié)的空間的效果是一樣的,因此可以限制接收端當(dāng)窗口為0時(shí),直接通告給發(fā)送端以阻止其繼續(xù)發(fā)送數(shù)據(jù),只有當(dāng)其接收窗口再次達(dá)到MSS的一半大小的時(shí)候才通告一個(gè)不為0的窗口,此前對(duì)于所有的發(fā)送端的窗口probe分段(用于探測(cè)接收端窗口大小的probe分段,由TCP標(biāo)準(zhǔn)規(guī)定),全部通告窗口為0,這樣發(fā)送端在收到窗口不為0的通告,那么肯定是一個(gè)比較大的窗口,因此發(fā)送端可以一次性發(fā)出一個(gè)很大的TCP分段,包含大量數(shù)據(jù),也即拉了好幾十噸的煤到北京,而不是只拉了幾公斤。

即,限制窗口通告時(shí)機(jī),解決糊涂窗口綜合癥

問題2描述:發(fā)送端持續(xù)發(fā)送小包,導(dǎo)致窗口閑置

這明顯是發(fā)送端引起的問題,此時(shí)接收端的窗口開得很大,然而發(fā)送端卻不積累數(shù)據(jù),還是一味的發(fā)送小塊數(shù)據(jù)分段。只要發(fā)送了任和的分段,接收端都要無(wú)條件接收并且確認(rèn),這完全符合TCP規(guī)范,因此必然要限制發(fā)送端不發(fā)送這樣的小分段。

問題2解決:Nagle算法

Nagel算法很簡(jiǎn)單,標(biāo)準(zhǔn)的Nagle算法為:

IF 數(shù)據(jù)的大小和窗口的大小都超過(guò)了MSS

Then 發(fā)送數(shù)據(jù)分段

ELSE

IF 還有發(fā)出的TCP分段的確認(rèn)沒有到來(lái)

Then 積累數(shù)據(jù)到發(fā)送隊(duì)列的末尾的TCP分段

ELSE

發(fā)送數(shù)據(jù)分段

EndIF

EndIF

可是后來(lái),這個(gè)算法變了,變得更加靈活了,其中的:

IF 還有發(fā)出的TCP分段的確認(rèn)沒有到來(lái)

變成了

IF 還有發(fā)出的不足MSS大小的TCP分段的確認(rèn)沒有到來(lái)

這樣如果發(fā)出了一個(gè)MSS大小的分段還沒有被確認(rèn),后面也是可以隨時(shí)發(fā)送一個(gè)小分段的,這個(gè)改進(jìn)降低了算法對(duì)延遲時(shí)間的影響。這個(gè)算法體現(xiàn)了一種自適應(yīng)的策略,越是確認(rèn)的快,越是發(fā)送的快,雖然Nagle算法看起來(lái)在積累數(shù)據(jù)增加吞吐量的同時(shí)也加大的時(shí)延,可事實(shí)上,如果對(duì)于類似交互式的應(yīng)用,時(shí)延并不會(huì)增加,因?yàn)檫@類應(yīng)用回復(fù)數(shù)據(jù)也是很快的,比如Telnet之類的服務(wù)必然需要回顯字符,因此能和對(duì)端進(jìn)行自適應(yīng)協(xié)調(diào)。

注意,Nagle算法是默認(rèn)開啟的,但是卻可以關(guān)閉。如果在開啟的情況下,那么它就嚴(yán)格按照上述的算法來(lái)執(zhí)行。

問題3.確認(rèn)號(hào)(ACK)本身就是不含數(shù)據(jù)的分段,因此大量的確認(rèn)號(hào)消耗了大量的帶寬

這是TCP為了確保可靠性傳輸?shù)囊?guī)范,然而大多數(shù)情況下,ACK還是可以和數(shù)據(jù)一起捎帶傳輸?shù)?。如果沒有捎帶傳輸,那么就只能單獨(dú)回來(lái)一個(gè)ACK,如果這樣的分段太多,網(wǎng)絡(luò)的利用率就會(huì)下降。從大同用火車?yán)奖本?00噸煤,為了確認(rèn)煤已收到,北京需要派一輛同樣的火車空載開到大同去復(fù)命,因?yàn)闆]有別的交通工具,只有火車。如果這位復(fù)命者剛開著一列火車走,又從大同來(lái)了一車煤,這拉煤的哥們兒又要開一列空車去復(fù)命了。

問題3的解決:

RFC建議了一種延遲的ACK,也就是說(shuō),ACK在收到數(shù)據(jù)后并不馬上回復(fù),而是延遲一段可以接受的時(shí)間,延遲一段時(shí)間的目的是看能不能和接收方要發(fā)給發(fā)送方的數(shù)據(jù)一起回去,因?yàn)門CP協(xié)議頭中總是包含確認(rèn)號(hào)的,如果能的話,就將ACK一起捎帶回去,這樣網(wǎng)絡(luò)利用率就提高了。往大同復(fù)命的確認(rèn)者不必開一輛空載火車回大同了,此時(shí)北京正好有一批貨物要送往大同,這位復(fù)命者搭著這批貨的火車返回大同。

如果等了一段可以接受的時(shí)間,還是沒有數(shù)據(jù)要發(fā)往發(fā)送端,此時(shí)就需要單獨(dú)發(fā)送一個(gè)ACK了,然而即使如此,這個(gè)延遲的ACK雖然沒有等到可以被捎帶的數(shù)據(jù)分段,也可能等到了后續(xù)到來(lái)的TCP分段,這樣它們就可以取最大者一起返回了,要知道,TCP的確認(rèn)號(hào)是收到的按序報(bào)文的最后一個(gè)字節(jié)的后一個(gè)字節(jié)。最后,RFC建議,延遲的ACK最多等待兩個(gè)分段的積累確認(rèn)。

4.2.分析三個(gè)問題之間的關(guān)聯(lián)

三個(gè)問題導(dǎo)致的結(jié)果是相同的,但是要知道它們的原因本質(zhì)上是不同的,問題1幾乎總是出現(xiàn)在接收端窗口滿的情況下,而問題2幾乎總是發(fā)生在窗口閑置的情況下,問題3看起來(lái)是最無(wú)聊的,然而由于TCP的要求,必須要有確認(rèn)號(hào),而且一個(gè)確認(rèn)號(hào)就需要一個(gè)TCP分段,這個(gè)分段不含數(shù)據(jù),無(wú)疑是很小的。

三個(gè)問題都導(dǎo)致了網(wǎng)絡(luò)利用率的降低。雖然兩個(gè)問題導(dǎo)致了同樣的結(jié)果,但是必須認(rèn)識(shí)到它們是不同的問題,很自然的將這些問題的解決方案匯總在一起,形成一個(gè)全局的解決方案,這就是如今的操作系統(tǒng)中的解決方案。

4.3.問題的雜糅情況

疑難雜癥11:糊涂窗口解決方案和Nagle算法

糊涂窗口綜合癥患者希望發(fā)送端積累TCP分段,而Nagle算法確實(shí)保證了一定的TCP分段在發(fā)送端的積累,另外在延遲ACK的延遲的那一會(huì)時(shí)間,發(fā)送端會(huì)利用這段時(shí)間積累數(shù)據(jù)。然而這卻是三個(gè)不同的問題。Nagle算法可以緩解糊涂窗口綜合癥,卻不是治本的良藥。

疑難雜癥12:Nagle算法和延遲ACK

延遲ACK會(huì)延長(zhǎng)ACK到達(dá)發(fā)送端的時(shí)間,由于標(biāo)準(zhǔn)Nagle算法只允許一個(gè)未被確認(rèn)的TCP分段,那無(wú)疑在接收端,這個(gè)延遲的ACK是毫無(wú)希望等待后續(xù)數(shù)據(jù)到來(lái)最終進(jìn)行積累確認(rèn)的,如果沒有數(shù)據(jù)可以捎帶這個(gè)ACK,那么這個(gè)ACK只有在延遲確認(rèn)定時(shí)器超時(shí)的時(shí)候才會(huì)發(fā)出,這樣在等待這個(gè)ACK的過(guò)程中,發(fā)送端又積累了一些數(shù)據(jù),因此延遲ACK實(shí)際上是在增加延遲的代價(jià)下加強(qiáng)了Nagle算法。在延遲ACK加Nagle算法的情況下,接收端只有不斷有數(shù)據(jù)要發(fā)回,才能同時(shí)既保證了發(fā)送端的分段積累,又保證了延遲不增加,同時(shí)還沒有或者很少有空載的ACK。

要知道,延遲ACK和Nagle是兩個(gè)問題的解決方案。

疑難雜癥13:到底何時(shí)可以發(fā)送數(shù)據(jù)

到底何時(shí)才能發(fā)送數(shù)據(jù)呢?如果單從Nagle算法上看,很簡(jiǎn)單,然而事實(shí)證明,情況還要更復(fù)雜些。如果發(fā)送端已經(jīng)排列了3個(gè)TCP分段,分段1,分段2,分段3依次被排入,三個(gè)分段都是小分段(不符合Nagle算法中立即發(fā)送的標(biāo)準(zhǔn)),此時(shí)已經(jīng)有一個(gè)分段被發(fā)出了,且其確認(rèn)還沒有到來(lái),請(qǐng)問此時(shí)能發(fā)送分段1和2嗎?如果按照Nagle算法,是不能發(fā)送的,但實(shí)際上它們是可以發(fā)送的,因?yàn)檫@兩個(gè)分段已經(jīng)沒有任何機(jī)會(huì)再積累新的數(shù)據(jù)了,新的數(shù)據(jù)肯定都積累在分段3上了。問題在于,分段還沒有積累到一定大小時(shí),怎么還可以產(chǎn)生新的分段?這是可能的,但這是另一個(gè)問題,在此不談。

Linux的TCP實(shí)現(xiàn)在這個(gè)問題上表現(xiàn)的更加靈活,它是這么判斷能否發(fā)送的(在開啟了Nagle的情況下):

IF (沒有超過(guò)擁塞窗口大小的數(shù)據(jù)分段未確認(rèn) || 數(shù)據(jù)分段中包含F(xiàn)IN ) &&

數(shù)據(jù)分段沒有超越窗口邊界

Then

IF 分段在中間(上述例子中的分段1和2) ||

分段是緊急模式 ||

通過(guò)上述的Nagle算法(改進(jìn)后的Nagle算法)

Then 發(fā)送分段

EndIF

EndIF

曾經(jīng)我也改過(guò)Nagle算法,確切的說(shuō)不是修改Nagle算法,而是修改了“到底何時(shí)能發(fā)送數(shù)據(jù)”的策略,以往都是發(fā)送端判斷能否發(fā)送數(shù)據(jù)的,可是如果此時(shí)有延遲ACK在等待被捎帶,而待發(fā)送的數(shù)據(jù)又由于積累不夠或者其它原因不能發(fā)送,因此兩邊都在等,這其實(shí)在某些情況下不是很好。我所做的改進(jìn)中對(duì)待何時(shí)能發(fā)送數(shù)據(jù)又增加了一種情況,這就是“ACK拉”的情況,一旦有延遲ACK等待發(fā)送,判斷一下有沒有數(shù)據(jù)也在等待發(fā)送,如果有的話,看看數(shù)據(jù)是否大到了一定程度,在此,我選擇的是MSS的一半:

IF (沒有超過(guò)擁塞窗口大小的數(shù)據(jù)分段未確認(rèn) || 數(shù)據(jù)分段中包含F(xiàn)IN ) &&

數(shù)據(jù)分段沒有超越窗口邊界

Then

IF 分段在中間(上述例子中的分段1和2) ||

分段是緊急模式 ||

通過(guò)上述的Nagle算法(改進(jìn)后的Nagle算法)

Then 發(fā)送分段

EndIF

ELSE IF 有延遲ACK等待傳輸 &&

發(fā)送隊(duì)列中有待發(fā)送的TCP分段 &&

發(fā)送隊(duì)列的頭分段大小大于MSS的一半

Then 發(fā)送隊(duì)列頭分段且捎帶延遲ACK

EndIF

另外,發(fā)送隊(duì)列頭分段的大小是可以在統(tǒng)計(jì)意義上動(dòng)態(tài)計(jì)算的,也不一定非要是MSS大小的一半。我們發(fā)現(xiàn),這種算法對(duì)于交互式網(wǎng)路應(yīng)用是自適應(yīng)的,你打字越快,特定時(shí)間內(nèi)積累的分段就越長(zhǎng),對(duì)端回復(fù)的越快(可以捎帶ACK),本端發(fā)送的也就越快(以Echo舉例會(huì)更好理解)。

疑難雜癥14:《TCP/IP詳解(卷一)》中Nagle算法的例子解讀

這個(gè)問題在網(wǎng)上搜了很多的答案,有的說(shuō)RFC的建議,有的說(shuō)別的??墒菍?shí)際上這就是一個(gè)典型的“競(jìng)態(tài)問題”:

首先服務(wù)器發(fā)了兩個(gè)分段:

數(shù)據(jù)段12:ack 14

數(shù)據(jù)段13:ack 14,54:56

然后客戶端發(fā)了兩個(gè)分段:

數(shù)據(jù)段14:ack 54,14:17

數(shù)據(jù)段15:ack 56,17:18

可以看到數(shù)據(jù)段14本來(lái)應(yīng)該確認(rèn)56的,但是確認(rèn)的卻是54。也就是說(shuō),數(shù)據(jù)段已經(jīng)移出隊(duì)列將要發(fā)送但還未發(fā)送的時(shí)候,數(shù)據(jù)段13才到來(lái),軟中斷處理程序搶占了數(shù)據(jù)段14的發(fā)送進(jìn)程,要知道此時(shí)只是把數(shù)據(jù)段14移出了隊(duì)列,還沒有更新任何的狀態(tài)信息,比如“發(fā)出但未被確認(rèn)的分段數(shù)量”,此時(shí)軟中斷處理程序順利接收了分段13,然后更新窗口信息,并且檢查看有沒有數(shù)據(jù)要發(fā)送,由于分段14已經(jīng)移出隊(duì)列,下一個(gè)接受發(fā)送檢查的就是分段15了,由于狀態(tài)信息還沒有更新,因此分段15順利通過(guò)發(fā)送檢測(cè),發(fā)送完成。

可以看Linux的源代碼了解相關(guān)信息,tcp_write_xmit這個(gè)函數(shù)在兩個(gè)地方會(huì)被調(diào)用,一個(gè)是TCP的發(fā)送進(jìn)程中,另一個(gè)就是軟中斷的接收處理中,兩者在調(diào)用中的競(jìng)態(tài)就會(huì)引起《詳解》中的那種情況。注意,這種不加鎖的發(fā)送方式是合理的,也是最高效的,因此TCP的處理語(yǔ)義會(huì)做出判斷,丟棄一切不該接收或者重復(fù)接收的分段的。

#p#

~~~~~~~~~~~~~~~~~~~~

承上啟下

又到了該承上啟下,到此為止,我們敘述的TCP還都是簡(jiǎn)單的TCP,就算是簡(jiǎn)單的TCP,也存在上述的諸多問題,就更別提繼續(xù)增加TCP的復(fù)雜性了。到此為止,我們的TCP都是端到端意義上的,然而實(shí)際上TCP要跑在IP網(wǎng)絡(luò)之上的,而IP網(wǎng)絡(luò)的問題是很多的,是一個(gè)很擁堵網(wǎng)絡(luò)。不幸的是,TCP的有些關(guān)于確認(rèn)和可靠性的機(jī)制還會(huì)加重IP網(wǎng)絡(luò)的擁堵。

~~~~~~~~~~~~~~~~~~~~

5.IP網(wǎng)絡(luò)之上的TCP

5.1.端到端的TCP協(xié)議和IP協(xié)議之間的矛盾

端到端的TCP只能看到兩個(gè)節(jié)點(diǎn),那就是自己和對(duì)方,它們是看不到任何中間的路徑的??墒荌P網(wǎng)絡(luò)卻是一跳一跳的,它們的矛盾之處在于TCP的端到端流量控制必然會(huì)導(dǎo)致網(wǎng)絡(luò)擁堵。因?yàn)槊織lTCP連接的一端只知道它對(duì)端還有多少空間用于接收數(shù)據(jù),它們并不管到達(dá)對(duì)端的路徑上是否還有這么大的容量,事實(shí)上所有連接的這些空間加在一起將瞬間超過(guò)IP網(wǎng)絡(luò)的容量,因此TCP也不可能按照滑動(dòng)窗口流量控制機(jī)制很理想的運(yùn)行。

勢(shì)必需要一種擁塞控制機(jī)制,反應(yīng)路徑的擁塞情況。

疑難雜癥15:擁塞控制的本質(zhì)

由于TCP是端到端協(xié)議,因此兩端之間的控制范疇屬于流量控制,IP網(wǎng)絡(luò)的擁塞會(huì)導(dǎo)致TCP分段的丟失,由于TCP看不到中間的路由器,因此這種丟失只會(huì)發(fā)生中間路由器,當(dāng)然兩個(gè)端點(diǎn)的網(wǎng)卡或者IP層丟掉數(shù)據(jù)分段也是TCP看不到的。因此擁塞控制必然作用于IP鏈路。事實(shí)上我們可以得知,只有在以下情況下?lián)砣刂撇艜?huì)起作用:

a.兩個(gè)或兩個(gè)以上的連接(其中一個(gè)一定要是TCP,另一個(gè)可以是任意連接)經(jīng)過(guò)同一個(gè)路由器或者同一個(gè)鏈路時(shí);

b.只有一個(gè)TCP連接,然而它經(jīng)過(guò)了一個(gè)路由器時(shí)。

其它情況下是不會(huì)擁塞的。因?yàn)橐粋€(gè)TCP總是希望獨(dú)享整條網(wǎng)絡(luò)通路,而這對(duì)于多個(gè)連接而言是不可能的,必須保證TCP的公平性,這樣這種擁塞控制機(jī)制才合理。本質(zhì)上,擁塞的原因就是大家都想獨(dú)享全部帶寬資源,結(jié)果導(dǎo)致?lián)砣?,這也是合理的,畢竟TCP看不到網(wǎng)絡(luò)的狀態(tài),同時(shí)這也決定了TCP的擁塞控制必須采用試探性的方式,最終到達(dá)一個(gè)足以引起其“反應(yīng)”的“刺激點(diǎn)”。

擁塞控制需要完成以下兩個(gè)任務(wù):1.公平性;2.擁塞之后退出擁塞狀態(tài)。

疑難雜癥16:影響擁塞的因素

我們必須認(rèn)識(shí)到擁塞控制是一個(gè)整體的機(jī)制,它不偏向于任何TCP連接,因此這個(gè)機(jī)制內(nèi)在的就包含了公平性。那么影響擁塞的因素都有什么呢?具有諷刺意味的是,起初TCP并沒有擁塞控制機(jī)制,正是TCP的超時(shí)重傳風(fēng)暴(一個(gè)分段丟失造成后續(xù)的已經(jīng)發(fā)送的分段均被重傳,而這些重傳大多數(shù)是不必要的)加重了網(wǎng)絡(luò)的擁塞。因此重傳必然不能過(guò)頻,必須把重傳定時(shí)器的超時(shí)時(shí)間設(shè)置的稍微長(zhǎng)一些,而這一點(diǎn)在單一重傳定時(shí)器的設(shè)計(jì)中得到了加強(qiáng)。除此TCP自身的因素之外,其它所有的擁塞都可以靠擁塞控制機(jī)制來(lái)自動(dòng)完成。

另外,不要把路由器想成一種線速轉(zhuǎn)發(fā)設(shè)備,再好的路由器只要接入網(wǎng)絡(luò),總是會(huì)拉低網(wǎng)絡(luò)的總帶寬,因此即使只有一個(gè)TCP連接,由于TCP的發(fā)送方總是以發(fā)送鏈路的帶寬發(fā)送分段,這些分段在經(jīng)過(guò)路由器的時(shí)候排隊(duì)和處理總是會(huì)有時(shí)延,因此最終肯定會(huì)丟包的。

最后,丟包的延后性也會(huì)加重?fù)砣?。假設(shè)一個(gè)TCP連接經(jīng)過(guò)了N個(gè)路由器,前N-1個(gè)路由器都能順利轉(zhuǎn)發(fā)TCP分段,但是最后一個(gè)路由器丟失了一個(gè)分段,這就導(dǎo)致了這些丟失的分段浪費(fèi)了前面路由器的大量帶寬。

5.2.擁塞控制的策略

在介紹擁塞控制之前,首先介紹一下?lián)砣翱冢鼘?shí)際上表示的也是“可以發(fā)送多少數(shù)據(jù)”,然而這個(gè)和接收端通告的接收窗口意義是不一樣的,后者是流量控制用的窗口,而前者是擁塞控制用的窗口,體現(xiàn)了網(wǎng)絡(luò)擁塞程度。

擁塞控制整體上分為兩類,一類是試探性的擁塞探測(cè),另一類則是擁塞避免(注意,不是常規(guī)意義上的擁塞避免)。

5.2.1.試探性的擁塞探測(cè)分為兩類,之一是慢啟動(dòng),之二是擁塞窗口加性擴(kuò)大(也就是熟知的擁塞避免,然而這種方式是避免不了擁塞的)。

5.2.2.擁塞避免方式擁塞控制旨在還沒有發(fā)生擁塞的時(shí)候就先提醒發(fā)送端,網(wǎng)絡(luò)擁塞了,這樣發(fā)送端就要么可以進(jìn)入快速重傳/快速恢復(fù)或者顯式的減小擁塞窗口,這樣就避免網(wǎng)絡(luò)擁塞的一沓糊涂之后出現(xiàn)超時(shí),從而進(jìn)入慢啟動(dòng)階段。

5.2.3.快速重傳和快速恢復(fù)。所謂快速重傳/快速恢復(fù)是針對(duì)慢啟動(dòng)的,我們知道慢啟動(dòng)要從1個(gè)MSS開始增加擁塞窗口,而快速重傳/快速恢復(fù)則是一旦收到3個(gè)冗余ACK,不必進(jìn)入慢啟動(dòng),而是將擁塞窗口縮小為當(dāng)前閥值的一半加上3,然后如果繼續(xù)收到冗余ACK,則將擁塞窗口加1個(gè)MSS,直到收到一個(gè)新的數(shù)據(jù)ACK,將窗口設(shè)置成正常的閥值,開始加性增加的階段。

當(dāng)進(jìn)入快速重傳時(shí),為何要將擁塞窗口縮小為當(dāng)前閥值的一半加上3呢?加上3是基于數(shù)據(jù)包守恒來(lái)說(shuō)的,既然已經(jīng)收到了3個(gè)冗余ACK,說(shuō)明有三個(gè)數(shù)據(jù)分段已經(jīng)到達(dá)了接收端,既然三個(gè)分段已經(jīng)離開了網(wǎng)絡(luò),那么就是說(shuō)可以在發(fā)送3個(gè)分段了,只要再收到一個(gè)冗余ACK,這也說(shuō)明1個(gè)分段已經(jīng)離開了網(wǎng)絡(luò),因此就將擁塞窗口加1個(gè)MSS。直到收到新的ACK,說(shuō)明直到收到第三個(gè)冗余ACK時(shí)期發(fā)送的TCP分段都已經(jīng)到達(dá)對(duì)端了,此時(shí)進(jìn)入正常階段開始加性增加擁塞窗口。

疑難雜癥17:超時(shí)重傳和收到3個(gè)冗余ACK后重傳

這兩種重傳的意義是不同的,超時(shí)重傳一般是因?yàn)榫W(wǎng)絡(luò)出現(xiàn)了嚴(yán)重?fù)砣?沒有一個(gè)分段到達(dá),如果有的話,肯定會(huì)有ACK的,若是正常ACK,則重置重傳定時(shí)器,若是冗余ACK,則可能是個(gè)別報(bào)文丟失或者被重排序,若連續(xù)3個(gè)冗余ACK,則很有可能是個(gè)別分段丟失),此時(shí)需要更加嚴(yán)厲的縮小擁塞窗口,因此此時(shí)進(jìn)入慢啟動(dòng)階段。而收到3個(gè)冗余ACK后說(shuō)明確實(shí)有中間的分段丟失,然而后面的分段確實(shí)到達(dá)了接收端,這因?yàn)檫@樣才會(huì)發(fā)送冗余ACK,這一般是路由器故障或者輕度擁塞或者其它不太嚴(yán)重的原因引起的,因此此時(shí)擁塞窗口縮小的幅度就不能太大,此時(shí)進(jìn)入快速重傳/快速恢復(fù)階段。

疑難雜癥18:為何收到3個(gè)冗余ACK后才重傳

這是一種權(quán)衡的結(jié)構(gòu),收到兩個(gè)或者一個(gè)冗余ACK也可以重傳,但是這樣的話可能或造成不必要的重傳,因?yàn)閮蓚€(gè)數(shù)據(jù)分段發(fā)生亂序的可能性不大,超過(guò)三個(gè)分段發(fā)生亂序的可能性才大,換句話說(shuō),如果僅僅收到一個(gè)亂序的分段,那很可能被中間路由器重排了,那么另一個(gè)分段很可能馬上就到,然而如果連續(xù)收到了3個(gè)分段都沒能彌補(bǔ)那個(gè)缺漏,那很可能是它丟失了,需要重傳。因此3個(gè)冗余ACK是一種權(quán)衡,在減少不必要重傳和確實(shí)能檢測(cè)出單個(gè)分段丟失之間所作的權(quán)衡。

注意,冗余ACK是不能捎帶的。

疑難雜癥19:乘性減和加性增的深層含義

為什么是乘性減而加性增呢?擁塞窗口的增加受惠的只是自己,而擁塞窗口減少受益的大家,可是自己卻受到了傷害。哪一點(diǎn)更重要呢?我們知道TCP的擁塞控制中內(nèi)置了公平性,恰恰就是這種乘性減實(shí)現(xiàn)了公平性。擁塞窗口的1個(gè)MSS的改變影響一個(gè)TCP發(fā)送者,為了使得自己擁塞窗口的減少影響更多的TCP發(fā)送者-讓更多的發(fā)送者受益,那么采取了乘性減的策略。

當(dāng)然,BIC算法提高了加性增的效率,不再一個(gè)一個(gè)MSS的加,而是一次加比較多的MSS,采取二分查找的方式逐步找到不丟包的點(diǎn),然后加性增。

疑難雜癥20:TCP連接的傳輸穩(wěn)定狀態(tài)是什么

首先,先說(shuō)一下發(fā)送端的發(fā)送窗口怎么確定,它取的是擁塞窗口和接收端通告窗口的最小值。然后,我們提出三種發(fā)送窗口的穩(wěn)定狀態(tài):

a.IP互聯(lián)網(wǎng)絡(luò)上接收端擁有大窗口的經(jīng)典鋸齒狀

b.IP互聯(lián)網(wǎng)絡(luò)上接收端擁有小窗口的直線狀態(tài)

c.直連網(wǎng)絡(luò)端點(diǎn)間的滿載狀態(tài)下的直線狀態(tài)

其中a是大多數(shù)的狀態(tài),因?yàn)橐话愣?,TCP連接都是建立在互聯(lián)網(wǎng)上的,而且是大量的,比如Web瀏覽,電子郵件,網(wǎng)絡(luò)游戲,F(xiàn)tp下載等等。TCP發(fā)送端用慢啟動(dòng)或者擁塞避免方式不斷增加其擁塞窗口,直到丟包的發(fā)生,然后進(jìn)入慢啟動(dòng)或者擁塞避免階段(要看是由于超時(shí)丟包還是由于冗余ACK丟包),此時(shí)發(fā)送窗口將下降到1或者下降一半,這種情況下,一般接收端的接收窗口是比較大的,畢竟IP網(wǎng)絡(luò)并不是什么很快速的網(wǎng)絡(luò),一般的機(jī)器處理速度都很快。

但是如果接收端特別破,處理速度很慢,就會(huì)導(dǎo)致其通告一個(gè)很小的窗口,這樣的話,即使擁塞窗口再大,發(fā)送端也還是以通告的接收窗口為發(fā)送窗口,這樣就不會(huì)發(fā)生擁塞。最后,如果唯一的TCP連接運(yùn)行在一個(gè)直連的兩臺(tái)主機(jī)上,那么它將獨(dú)享網(wǎng)絡(luò)帶寬,這樣該TCP的數(shù)據(jù)流在最好的情況下將填滿網(wǎng)絡(luò)管道(我們把網(wǎng)絡(luò)管道定義為帶寬和延時(shí)的乘積),其實(shí)在這種情況下是不存在擁塞的,就像你一個(gè)人獨(dú)自徘徊在飄雨黃昏的街頭一樣...

5.2.4.主動(dòng)的擁塞避免

前面我們描述的擁塞控制方式都是試探性的檢測(cè),然后擁塞窗口被動(dòng)的進(jìn)行乘性減,這樣在接收端窗口很大的情況下(一般都是這樣,網(wǎng)絡(luò)擁堵,分段就不會(huì)輕易到達(dá)接收端,導(dǎo)致接收端的窗口大量空置)就可能出現(xiàn)鋸齒形狀的“時(shí)間-窗口”圖,類似在一個(gè)擁堵的北京X環(huán)上開車,發(fā)送機(jī)發(fā)動(dòng),車開動(dòng),停止,等待,發(fā)動(dòng)機(jī)發(fā)動(dòng),車開動(dòng)...聽聲音也能聽出來(lái)。

雖然TCP看不到下面的IP網(wǎng)絡(luò),然而它還是可以通過(guò)檢測(cè)RTT的變化以及擁塞窗口的變化推算出IP網(wǎng)絡(luò)的擁堵情況的。就比方說(shuō)北京東四環(huán)一家快遞公司要持續(xù)送快遞到西四環(huán),當(dāng)發(fā)件人發(fā)現(xiàn)貨到時(shí)間越來(lái)越慢的時(shí)候,他會(huì)意識(shí)到“下班高峰期快到了”...

可以通過(guò)持續(xù)觀測(cè)RTT的方式來(lái)主動(dòng)調(diào)整擁塞窗口的大小而不是一味的加性增。然而還有更猛的算法,那就是計(jì)算兩個(gè)差值的乘積:

(當(dāng)前擁塞窗口-上一次擁塞窗口)x(當(dāng)前的RTT-上一次的RTT)

如果結(jié)果是正數(shù),則擁塞窗口減少1/8,若結(jié)果是負(fù)數(shù)或者0,則窗口增加一個(gè)MSS。注意,這回不再是乘性減了,可以看出,減的幅度比乘性減幅度小,這是因?yàn)檫@種擁塞控制是主動(dòng)的,而不是之前的那種被動(dòng)的試探方式。在試探方式中,乘性減以一種懲罰的方式實(shí)現(xiàn)了公平性,而在這里的主動(dòng)方式中,當(dāng)意識(shí)到要擁塞的時(shí)候,TCP發(fā)送者主動(dòng)的減少了擁塞窗口,為了對(duì)這種自首行為進(jìn)行鼓勵(lì),采用了小幅減少擁塞窗口的方式。需要注意的是,在擁塞窗口減小的過(guò)程中,乘積的前一個(gè)差值是負(fù)數(shù),如果后一個(gè)差值也是負(fù)數(shù),那么結(jié)果就是繼續(xù)縮減窗口,直到擁塞緩解或者窗口減少到了一定程度,使得后一個(gè)差值成了正數(shù)或者0,這種情況下,其實(shí)后一個(gè)差值只能變?yōu)?。

疑難雜癥21:路由器和TCP的互動(dòng)

雖然有了5.2.4節(jié)介紹的主動(dòng)的擁塞檢測(cè),那么路由器能不能做點(diǎn)什么幫助檢測(cè)擁塞呢?這種對(duì)路由器的擴(kuò)展是必要的,要知道,每天有無(wú)數(shù)的TCP要通過(guò)路由器,雖然路由器不管TCP協(xié)議的任何事(當(dāng)然排除連接跟蹤之類的,這里所說(shuō)的是標(biāo)準(zhǔn)的IP路由器),但是它卻能以一種很簡(jiǎn)單的方式告訴TCP的兩端IP網(wǎng)絡(luò)發(fā)生了擁堵,這種方式就是當(dāng)路由器檢測(cè)到自己發(fā)生輕微擁堵的時(shí)候隨機(jī)的丟包,隨機(jī)丟包而不是連續(xù)丟包對(duì)于TCP而言是有重大意義的,隨機(jī)丟包會(huì)使TCP發(fā)現(xiàn)丟棄了個(gè)別的分段而后續(xù)的分段仍然會(huì)到達(dá)接收端,這樣TCP發(fā)送端就會(huì)接收到3個(gè)冗余ACK,然后進(jìn)入快速重傳/快速恢復(fù)而不是慢啟動(dòng)。

這就是路由器能幫TCP做的事。

6.其它

疑難雜癥22:如何學(xué)習(xí)TCP

很多人發(fā)帖問TCP相關(guān)的內(nèi)容,接下來(lái)稀里嘩啦的就是讓看《TCP/IP詳解》和《Unix網(wǎng)絡(luò)編程》里面的特定章節(jié),我覺得這種回答很不負(fù)責(zé)任。因?yàn)槲也⒉徽J(rèn)為這兩本書有多大的幫助,寫得確實(shí)很不錯(cuò),然而可以看出Richard Stevens是一個(gè)實(shí)用主義者,他喜歡用實(shí)例來(lái)解釋一切,《詳解》通篇都是用tcpdump的輸出來(lái)講述的,這種方式只是適合于已經(jīng)對(duì)TCP很理解的人,然而大多數(shù)的人是看不明白的。

如果想從設(shè)計(jì)的角度來(lái)說(shuō),這兩本書都很爛。我覺得應(yīng)該先看點(diǎn)入門的,比如Wiki之類的,然后看RFC文檔,793,896,1122等),這樣你就明白TCP為何這么設(shè)計(jì)了,而這些你永遠(yuǎn)都不能在Richard Stevens的書中得到。最后,如果你想,那么就看一點(diǎn)Richard Stevens的書,最重要的還是寫點(diǎn)代碼或者敲點(diǎn)命令,然后抓包自己去分析。

疑難雜癥23:Linux,Windows和網(wǎng)絡(luò)編程

我覺得在Linux上寫點(diǎn)TCP的代碼是很不錯(cuò)的,如果有BSD那就更好了。不推薦用Winsock學(xué)習(xí)TCP。雖然微軟聲稱自己的API都是為了讓事情更簡(jiǎn)單,但實(shí)際上事情卻更復(fù)雜了,如果你用Winsock學(xué)習(xí),你就要花大量的時(shí)候去掌握一些和網(wǎng)絡(luò)編程無(wú)關(guān)但是windows平臺(tái)上卻少不了的東西

6.1.總結(jié)

TCP協(xié)議是一個(gè)端到端的協(xié)議,雖然話說(shuō)它是一個(gè)帶流量控制,擁塞控制的協(xié)議,然而正是因?yàn)檫@些所謂的控制才導(dǎo)致了TCP變得復(fù)雜。同時(shí)這些特性是互相雜糅的,流量控制帶來(lái)了很多問題,解決這些問題的方案最終又帶來(lái)了新的問題,這些問題在解決的時(shí)候都只考慮了端到端的意義,但實(shí)際上TCP需要盡力而為的IP提供的網(wǎng)絡(luò),因此擁塞成了最終的結(jié)癥,擁塞控制算法的改進(jìn)也成了一個(gè)單獨(dú)的領(lǐng)域。

在學(xué)習(xí)TCP的過(guò)程中,切忌一鍋粥一盤棋的方式,一定要分清楚每一個(gè)算法到底是解決什么問題的,每一個(gè)問題和其他問題到底有什么關(guān)聯(lián),這些問題的解決方案之間有什么關(guān)聯(lián),另外TCP的發(fā)展歷史也最好了解一下,這些都搞明白了,TCP協(xié)議就徹底被你掌控了。接下來(lái)你就可以學(xué)習(xí)Socket API了,然后高效的TCP程序出自你手!

責(zé)任編輯:何妍 來(lái)源: CSDN博客
相關(guān)推薦

2018-10-31 14:40:19

TCP協(xié)議ISO

2012-11-26 10:23:08

醫(yī)療大數(shù)據(jù)R統(tǒng)計(jì)語(yǔ)言

2009-02-05 10:12:00

2022-07-17 12:58:43

Docke技巧

2009-04-29 14:46:15

ADSL寬帶掉線

2022-04-06 13:55:22

DockerLinux

2015-09-06 11:41:15

快碼眾包加速器

2009-01-11 09:29:00

局域網(wǎng)共享?yè)芴?hào)

2022-01-20 22:05:19

ChromiumtransformCSS

2010-08-19 09:48:46

IE6

2019-02-21 09:32:13

MQ中間件SQL

2010-08-26 09:03:05

IE6

2014-06-23 13:59:18

互聯(lián)網(wǎng)電商運(yùn)營(yíng)

2022-07-28 14:29:38

機(jī)器學(xué)習(xí)技術(shù)

2016-08-19 12:59:06

醫(yī)療信息疑難雜癥

2018-04-11 07:48:16

2017-11-28 17:09:52

華為云

2018-11-20 09:25:00

2021-11-04 15:17:59

網(wǎng)絡(luò)數(shù)據(jù)技術(shù)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)