Ø Nagle算法分析。
Nagle算法主要用來預防小分組的產生。在廣域網上,大量TCP小分組極有可能造成網絡的擁塞。
Nagle時針對每一個TCP連接的。它要求一個TCP連接上最多只能有一個未被確認的小分組。在改分組的確認到達之前不能發送其他小分組。TCP會搜集這些小的分組,然后在之前小分組的確認到達后將剛才搜集的小分組合并發送出去。
有時候我們必須要關閉Nagle算法,特別是在一些對時延要求較高的交互式操作環境中,所有的小分組必須盡快發送出去。
我們可以通過編程取消Nagle算法,利用TCP_NODELAY選項來關閉Nagle算法。
TCP成塊數據流 和TCP成塊數據流相關的東西有很多,比如流量控制,緊急數據傳輸,數據窗口大小調整等等。
Ø 正常數據流
TCP通常不會對每個到達的數據分段進行確認操作,通常一個ACK報文可以確認多個成塊數據段報文,通常情況下是兩個成塊數據報文段需要一個ACK報文確認。通常是由下面的原有造成的 :當收到一個報文后,此TCP連接被標識未一個未完成的時延確認,當再次收到一個數據報文后,此連接有兩個未確認的報文段,TCP馬上發送一個ACK,當第三個數據報文到達后,第四個報文到達前,通常此TCP連接已經經過了200ms延時,因此一個ACK被發送,這樣的循環周而復始,從而出現了一個ACK確認兩個數據報文的情況。當然,ACK的產生很大程度上和其接收數據報文段的時間緊密相關,也就是和Client段發送數據的頻率相關,和網絡擁塞程度相關,和Client與Server兩端的處理能力相關,總是是一個多因素決定的結果。
Ø TCP的滑動窗口協議
TCP使用滑動窗口協議來進行流量控制。特別需要注意的是,滑動窗口是一個抽象的概念,它是針對每一個TCP連接的,而且是有方向的,一個TCP連接應該有兩個滑動窗口,每個數據傳輸方向上有一個,而不是針對連接的每一端的。
窗口左邊沿向右邊滑動叫做窗口合攏,表示發送方發送了數據或者接收到了確認;窗口右邊沿向右邊滑動叫做窗口的張開,表示數據已經被用戶空間進程接收并且釋放了緩存;窗口左邊沿向左移動則表明此ACK是重復ACK,應該丟棄;窗口右邊沿向左移動叫做窗口收縮,一般不會有人這樣做。
當左邊沿和右邊沿重合的時候表明窗口大小是0,此時發送方不應該在發送數據了,因為接收方的接收緩沖區已滿,用戶進程還沒以接收。當用戶進程接收完成后,接收方應該發送一個ACK,表明此時的接收窗口已經恢復,此ACK的序號同前一個win為0的ACK相同。
同樣,在實現中,發送方不必發送一個全窗口的數據,但是它當然可以這樣做。ACK總是將窗口向右邊滑動,窗口的大小可以減小,接收方在發送ACK之前不必等待窗口被填滿(即變為0),很多實現是收到兩個數據報文段后立刻發送ACK。
Ø TCP窗口大小的調整
TCP窗口的大小通常由接收端來確認,也就是在TCP建立連接的第二個SYN+ACK報文的Win字段來確認。
當然,程序可以隨時改變這個窗口(緩存)的大小。默認的窗口大小是4096字節,但是對于文件傳輸來說這并不是一個理想的數字,如果程序的主要目的是傳輸文件,那么最好將這個緩存設置到最大,但是這樣可能會造成發送端連續發送多個數據報文段后,接收方才反饋一個ACK的情況,當然,這也沒有什么不可以的,只要不超時,就不算錯。
Ø TCP的PUSH包
PUSH是TCP報頭中的一個標志位,發送方在發送數據的時候可以設置這個標志位。該標志通知接收方將接收到的數據全部提交給接收進程。這里所說的數據包括與此PUSH包一起傳輸的數據以及之前就為該進程傳輸過來的數據。
當Server端收到這些數據后,它需要立刻將這些數據提交給應用層進程,而不再等待是否還有額外的數據到達。
那么應該合適設置PUSH標志呢?實際上現在的TCP協議棧基本上都可以自行處理這個問題,而不是交給應用層處理。如果待發送的數據會清空發送緩存,那么棧就會自動為此包設置PUSH標志,源于BSD的棧一般都會這么做,而且,BSD TCP STACK也從來不會將收到的數據推遲提交給應用程序,因此,在BSD TCP STACK中,PUSH位是被忽略的,因為根本就沒有用。
Ø TCP的慢啟動(擁塞窗口)
TCP在局域網環境中的效率是很高的,但是到了廣域網的環境中情況就不同了,在發送方和接收方之間可能存在多個Router以及一些速率比較慢的鏈路,而且一些中繼路由器必須緩存分組,還可能分片,所以在廣域網的環境中,TCP的效率可能出現問題。
為了解決這個問題,現在的TCP棧都支持“慢啟動”算法,即擁塞窗口控制算法。該算法通過觀察到新分組進入網絡的速率與另一端返回ACK的速率相同而工作。其實,擁塞窗口是發送方使用的一種流量控制算法。
慢啟動為TCP的發送方增加了一個擁塞窗口,當連接建立時,擁塞窗口被初始化為一個報文段大小,每收到一個ACK,擁塞窗口就會增加一個報文段,發送方取擁塞窗口與通過窗口的最小值作為發送的上限。
Ø TCP成塊數據吞吐量
TCP窗口大小,窗口流量控制,慢啟動對TCP的成塊數據傳輸綜合作用,可能對TCP的數據傳輸有意想不到的影響。
RTT(Round-Trip Time) :往返時間。是指一個報文段從發出去到收到此報文段的ACK所經歷的時間。通常一個報文段的RTT與傳播時延和發送時延兩個因素相關。
在發送的過程中有可能發生這樣的情況,即TCP兩端的傳輸“管道”被填滿,即整個管道上都有數據在跑,此時不管擁塞窗口和通告窗口是多少,管道上都不能在容納更多的數據了。此時每當接收方從網絡上移去一個報文段,發送方就發送一個,但是管道上的ACK總是固定的,這種情況就是連接的理想穩定狀態。
一般情況下帶寬*時延就是一條線路的容量,因此吧RTT減小可以增加一條線路的容量,注意RTT加大的意思時傳輸時間減小!
當數據由一個大的管道向一個小的管道傳輸時,就有可能發生擁塞,例如,當若干輸入流到達一個路由器,而此路由器的輸出帶寬小于這些輸入流的帶寬總和時,就會發生擁塞。這種情況普遍見于局域網與廣域網的接口處。如果發送方處于局域網,而且不使用慢啟動,使用局域網的帶寬盡快的發送報文,那么返回的ACK之間的間隔與最慢的廣域網鏈路一致。而且,由于路由器轉發包速度慢,所以路由器就有可能主動丟失分組包。
Ø TCP的緊急方式
TCP提供了一種“緊急方式”的數據傳輸方式,TCP的一端可以告訴另一端有些具有某種方式的緊急數據被放在了普通的數據流中,接收方可以自行選擇處理。緊急方式客廳通過設置TCP的URG標識位與緊急指針的偏移量來設置。這個緊急指針指向緊急數據的最后一個字節(也有可能是最后一個字節的下一個字節)。
現在有許多實現將緊急方式叫做“帶外數據”,其實這是不正確的。
目前緊急指針被用來禁止停止FTP的數據傳輸。不過總的來說,用的不多。
對于數據傳輸來說,如果用緊急數據來傳輸大量數據,這種方法顯然是不可取的,再建立一個TCP連接不是更簡單有效嗎?