Android網絡編程隨想錄(1)

        本系列文章對整個Android網絡編程進行了總結,包括基本的TCP/IP協議,HTTP協議,HTTPS協議,HttpClient,UrlConnection,一些網絡通訊的庫到棉花糖新加入的OKHTTP。算法

        本文主要對TCP協議的鏈接管理和擁塞控制兩部分知識進行總結。編程

鏈接管理

        TCP協議是傳輸層的重要協議,負責端到端的通訊。爲了實現面向鏈接的可靠傳輸,TCP協議使用「三次握手」和「四次揮手」的方式來建立鏈接,結束鏈接。緩存

        三次握手:服務器

    • 第一次握手:創建鏈接時,客戶端C發起創建鏈接請求(SYN=1)到服務器S,並進入SYN_SEND狀態,等待服務器返回確認。
    • 第二次握手:服務器S收到客戶端C發來的鏈接請求後,返回確認報文(SYN=1,ACK),並進入SYN_RECV狀態。
    • 第三次握手:客戶端C收到服務器S發來的確認報文後,也要返回一個確認(SYN=0,ACK),進入ESTABLISHED狀態,開始傳送數據。

        這裏須要提一下的是確認號數值ACK=指望對方下次發來的字節序號。網絡

        當須要斷開鏈接時候,採用「四次揮手」的方式:socket

    • 第一次揮手:客戶端C發送完數據後,發起釋放鏈接請求(FIN=1),表示要關閉數據傳送,進入FIN_WAIT1狀態。
    • 第二次揮手:服務端S收到請求後,會繼續發送以前未發完的數據(ACK)並進入CLOSE_WAIT狀態,關閉讀通道,也就是不能再從這個連接上讀取數據。C收到對本身釋放鏈接請求的ACK後,關閉寫通道,再也不向鏈接中寫數據,進入FIN_WAIT2狀態。
    • 第三次揮手:服務端S發送完要發送的數據後,發送會關閉寫通道(FIN=1)報文,進入LAST_ACK狀態。而此時客戶端接到該報文後,關閉讀通道,進入TIME_WAIT狀態。
    • 第四次揮手:客戶端C發送對上一步服務器的FIN報文的ACK,而後在等待2個MSL的時間後,進入CLOSED狀態。而服務器S在收到該ACK後也進入CLOSED狀態。

image

        關於鏈接創建和釋放過程當中,有兩個狀態須要說明一下:spa

    • SYN_RECV:服務器S收到了來自客戶端的創建鏈接請求,此時稱爲半鏈接狀態,存儲在服務器端的一個半鏈接隊列中。當收到C發來的ACK報文後,會在該隊列中查找並移除。若是受到flood SYN攻擊,半鏈接隊列溢出,後續鏈接請求則會被丟棄。能夠經過SYN Cookie來防止flood SYN攻擊。
    • TIME_WAIT:客戶端C在發送對服務器S的FIN報文的確認ACK後,進入了TIME_WAIT狀態。客戶端會維持這個狀態2MSL後才釋放socket。這個機制從邏輯上保證了從新被分配的socket不會受到以前殘留的延遲重發報文的影響。若是直接關閉客戶端C,假如服務器S並未收到C對以前FIN報文的確認,則會從新發送FIN報文給C,可是此時C已經CLOSED了,沒法找到此鏈接只好返回RST(reset)給S。這樣雖然沒有數據丟失,可是不符合可靠鏈接的要求。另外,若是C直接關閉後,又從新向server創建了一個鏈接,端口號又相同,可是以前上一個socket有些滯留數據也會發送到server。這時,服務器就會認爲這些滯留數據是新鏈接發來的,產生混淆。等待2MSL能夠保證這些數據消失。

擁塞控制與流量控制

        擁塞控制就是防止過多數據注入到網絡中,這樣可使網絡中的路由器和鏈路不至於過載。它是一個全局性的過程,涉及到鏈路上全部的主機和路由器。而流量控制是點對點通訊量的控制,是爲了防止發送端數據發送過快接收端來不及接收。TCP協議採用慢開始、擁塞避免、快重傳以及快恢復的算法進行擁塞控制。發送端維持了一個稱爲「擁塞窗口」的狀態變量cwnd,它隨着網絡擁塞程度動態變化,這裏咱們先不去考慮流量控制以及接收方的接收能力,而是讓發送方的發送窗口等於擁塞窗口。server

慢開始和擁塞避免算法

        當主機開始發送數據的時候並不知道網絡負荷情況,因此由小到大逐漸增大發送窗口,即由小到大增大擁塞窗口cwnd。初始設置cwnd=1MSS,發送一個報文給接收方。接收方收到該報文後,會返回確認。發送方每次收到一個對新報文段的確認,就將cwnd增長1.所以,慢開始算法每通過一個傳輸輪次RTT,擁塞窗口加倍:1,2,4…因此說「慢開始」不是說cwnd增加速度慢,而是說在開始發送的時候cwnd=1進行網絡試探。blog

爲了防止cwnd過速增加,須要設置一個慢開始閾值ssthresh狀態變量:隊列

  • 當cwnd<ssthresh時,使用慢開始算法。
  • 當cwnd>ssthresh時,改用擁塞避免算法。

        這裏擁塞避免算法與慢開始算法不一樣,每通過一個傳輸輪次RTT發送方的擁塞窗口cwnd增長1,而不是加倍,同時ssthresh的值也加1.不管是在慢開始算法仍是在擁塞避免算法階段,一旦發生擁塞(是否按時收到確認報文),則把ssthresh值設置爲擁塞時cwnd值的1/2,而後cwnd設置爲1,從新開始慢開始算法。(這是不使用快重傳的思路)

image

快重傳和快恢復

        在傳輸過程當中,若是發送方在計時器時限已到仍未收到確認,則可能出現了擁塞。對於這種可能出現的擁塞,上面所述狀況未使用快重傳算法。而對於快重傳算法,首先要求接收方在每收到一個失序報文,都會發出重複確認,而不是等本身發數據時候才捎帶發送ack。當接收方連續收到3個重複確認,應當當即重傳該報文而沒必要等待計時器時間到。

        快重傳算法須要和快恢復算法配合使用。在連續收到3個確認報文並重發該報文的同時,爲了預防擁塞發生,把慢開始閾值ssthresh減半。此時並不去執行慢開始算法(cwnd=1),而是把cwnd設置爲ssthresh減半後的數值,而後執行擁塞避免算法。在採用快恢復的算法時候,慢開始算法只是在TCP鏈接創建時和網絡出現超時時才使用。

        咱們在談論上面四種算法的時候,假設接收方擁有足夠大的緩存來接收數據。可是實際上接收方緩存有限,因此須要設定一個接收窗口rwnd,在每次向發送方返回確認的時候傳送給發送方。這個接收窗口又稱爲通知窗口,從流量控制的角度發送方的發送窗口不能超過接收方的rwnd值。

        綜合擁塞控制和流量控制兩方面考慮,發送窗口值=min{rwnd,cwnd}。

image

 

         下一篇文章中將對http協議和HTTPS協議進行總結。

相關文章
相關標籤/搜索