1. 程式人生 > >【網路】HTTP協議中的長連線和短連線(keep-alive狀態)

【網路】HTTP協議中的長連線和短連線(keep-alive狀態)

 HTTP1.1規定了預設保持長連線(HTTP persistent connection ,也有翻譯為持久連線),資料傳輸完成了保持TCP連線不斷開(不發RST包、不四次握手),等待在同域名下繼續用這個通道傳輸資料;相反的就是短連線。

 HTTP首部的Connection: Keep-alive是HTTP1.0瀏覽器和伺服器的實驗性擴充套件,當前的HTTP1.1 RFC2616文件沒有對它做說明,因為它所需要的功能已經預設開啟,無須帶著它,但是實踐中可以發現,瀏覽器的報文請求都會帶上它。如果HTTP1.1版本的HTTP請求報文不希望使用長連線,則要在HTTP請求報文首部加上Connection: close。《HTTP權威指南》提到,有部分古老的HTTP1.0 代理不理解Keep-alive,而導致長連線失效:客戶端-->代理-->服務端,客戶端帶有Keep-alive,而代理不認識,於是將報文原封不動轉給了服務端,服務端響應了Keep-alive,也被代理轉發給了客戶端,於是保持了“客戶端-->代理”連線和“代理-->服務端”連線不關閉,但是,當客戶端第傳送第二次請求時,代理會認為當前連線不會有請求了,於是忽略了它,長連線失效。書上也介紹瞭解決方案:當發現HTTP版本為1.0時,就忽略Keep-alive,客戶端就知道當前不該使用長連線。其實,在實際使用中不需要考慮這麼多,很多時候代理是我們自己控制的,如Nginx代理,代理伺服器有長連線處理邏輯,服務端無需做patch處理,常見的是客戶端跟Nginx代理伺服器使用HTTP1.1協議&長連線,而Nginx代理伺服器跟後端伺服器使用HTTP1.0協議&短連線。

    在實際使用中,HTTP頭部有了Keep-Alive這個值並不代表一定會使用長連線,客戶端和伺服器端都可以無視這個值,也就是不按標準來,譬如我自己寫的HTTP客戶端多執行緒去下載檔案,就可以不遵循這個標準,併發的或者連續的多次GET請求,都分開在多個TCP通道中,每一條TCP通道,只有一次GET,GET完之後,立即有TCP關閉的四次握手,這樣寫程式碼更簡單,這時候雖然HTTP頭有Connection: Keep-alive,但不能說是長連線。正常情況下客戶端瀏覽器、web服務端都有實現這個標準,因為它們的檔案又小又多,保持長連線減少重新開TCP連線的開銷很有價值。

     以前使用
libcurl做的上傳
/下載,就是短連線,抓包可以看到:1、每一條TCP通道只有一個POST;2、在資料傳輸完畢可以看到四次握手包。只要不呼叫curl_easy_cleanup,curl的handle就可能一直有效,可複用。這裡說可能,因為連線是雙方的,如果伺服器那邊關掉了,那麼我客戶端這邊保留著也不能實現長連線。    
    如果是使用windows的WinHTTP庫,則在POST/GET資料的時候,雖然我關閉了控制代碼,但這時候TCP連線並不會立即關閉,而是等一小會兒,這時候是WinHTTP庫底層支援了跟Keep-alive所需要的功能:即便沒有Keep-alive,WinHTTP庫也可能會加上這種TCP通道複用的功能,而其它的網路庫像libcurl則不會這麼做。

長連線的過期時間