HTTP長連接和短連接

主頁:www.howardliu.cn
博文:HTTP長連接和短連接

一直聽別人說HTTP長連接,只知道長連接比短連接更節省資源、更快捷,但是並不真的知道原因。知其然不知其所以然,對於技術來說,這種狀態是比較危險的。所以,還是要挖一下原理,即使挖的比較淺,也要邁出這一步。

HTTP是應用層協議,傳輸層使用的是TCP協議,網絡層使用的是IP協議。

IP協議主要解決網絡路由和尋址問題,TCP協議主要解決如何在IP層之上可靠的傳遞數據包,使在網絡上的另一端收到發送端發出的所有包,並且順序與發出順序一致,HTTP協議主要基於TCP協議完成數據傳遞。

OSI參考模型與TCP/IP模型

首先說下TCP連接與斷開。

TCP的生命週期被戲稱爲三次握手和四次揮手,每次握手(揮手)都需要通信雙方交互數據,所以TCP連接傳輸數據是比較耗費資源的,也就是通常所說的成本較高。

TCP的三次握手和四次揮手

然後,HTTP協議是無狀態的、面向連接的,即協議本身不具備記憶能力,兩次不同的HTTP請求之間沒有任何聯繫。

在HTTP/1.1之前,一個網頁加載資源的時候,每需要加載一個資源,就需要進行一次HTTP請求,建立一次連接,請求結束就斷開連接,而每次連接(TCP連接)都需要耗費資源(時間資源、網絡資源等)。

所以後來在HTTP/1.1中引入持久連接(persistent connection),即TCP連接默認不關閉,可以被多個請求複用,不用聲明Connection: keep-alive,也就是常說的長連接。

這裏所說的長連接,其實本身是TCP長連接。比如發起一次HTTP請求時,客戶端與服務端創建TCP連接,在得到響應結果後,不進行TCP的四次揮手斷開連接,而是會保持一段時間的TCP連接。此時,如果又有一次HTTP請求相同的服務端,就會繼續使用這一個TCP連接。這樣,節省了TCP連接的消耗。

當然,爲了資源的有效利用,在一段時間(超時時間,請求頭中Keep-alive: timeout=10進行設置)沒有活動時,客戶端或服務端會主動斷開TCP連接。建議的做法是,在客戶端最後一次請求時,請求頭中發送Connection: close,明確要求關閉TCP連接。


補充下TCP三次握手、四次揮手的知識。

三次握手建立連接:

  1. 第一次握手:客戶端發送SYN包(seq=x)到服務器,並進入SYN_SEND狀態,等待服務器確認;
  2. 第二次握手:服務器收到SYN包,必須確認客戶的SYN(ACK=x+1),同時自己也發送一個SYN包(seq=y),即SYN+ACK包,此時服務器進入SYN_RECV狀態;
  3. 第三次握手:客戶端收到服務器的SYN+ACK包,向服務器發送確認包ACK(ACK=y+1),此包發送完畢,客戶端和服務器進入ESTABLISHED狀態,完成三次握手。

握手過程中傳送的包裏不包含數據,三次握手完畢後,客戶端與服務器才正式開始傳送數據。理想狀態下,TCP連接一旦建立,在通信雙方中的任何一方主動關閉連接之前,TCP 連接都將被一直保持下去。

四次揮手斷開連接
1. 第一次揮手:主動關閉方發送一個FIN,用來關閉主動方到被動關閉方的數據傳送,也就是主動關閉方告訴被動關閉方:我已經不會再給你發數據了(當然,在FIN包之前發送出去的數據,如果沒有收到對應的ACK確認報文,主動關閉方依然會重發這些數據),但此時主動關閉方還可以接受數據。
2. 第二次揮手:被動關閉方收到FIN包後,發送一個ACK給對方,確認序號爲收到序號+1(與SYN相同,一個FIN佔用一個序號)。
3. 第三次揮手:被動關閉方發送一個FIN,用來關閉被動關閉方到主動關閉方的數據傳送,也就是告訴主動關閉方,我的數據也發送完了,不會再給你發數據了。
4. 第四次揮手:主動關閉方收到FIN後,發送一個ACK給被動關閉方,確認序號爲收到序號+1,至此,完成四次揮手。

注意:中斷連接端可以是Client端,也可以是Server端。

詳細的狀態說明

  • SYN_SEND:客戶端嘗試鏈接服務端,通過open方法。也就是TCP三次握手中的第1步之後,注意是客戶端狀態
  • SYN_RECEIVED: 服務接受創建請求的SYN後,也就是TCP三次握手中的第2步,發送ACK數據包之前。注意是服務端狀態,一般15個左右正常,如果很大,懷疑遭受SYN_FLOOD攻擊
  • ESTABLISHED:客戶端接受到服務端的ACK包後的狀態,服務端在發出ACK在一定時間後即爲ESTABLISHED
  • FIN_WAIT1:主動關閉的一方,在發出FIN請求之後,也就是在TCP四次揮手的第1步
  • CLOSE_WAIT:被動關閉的一方,在接受到客戶端的FIN後,也就是在TCP四次揮手的第2步
  • FIN_WAIT2:主動關閉的一方,在接受到被動關閉一方的ACK後,也就是TCP四次揮手的第2步。可以設定被動關閉方返回FIN後的超時時間,有效回收鏈接,避免syn-flood.
  • LASK_ACK:被動關閉的一方,在發送ACK後一段時間後(確保客戶端已收到),再發起一個FIN請求。也就是TCP四次揮手的第3步
  • TIME_WAIT:主動關閉的一方,在收到被動關閉的FIN包後,發送ACK。也就是TCP四次揮手的第4步
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章