前提:
HTTP/1.1中,默認開啟長連接,如客戶端不需要,需要加上請求首部connection:close告知服務器。如服務器不支持長連接,則需要加上響應首部connection:close告知客戶端,否則需要加上響應首部connection:keep-alive
HTTP/1.0中,默認不開啟長連接,如客戶端需要,需要加上請求首部connection:keep-alive告知服務器。如服務器不支持長連接,則需要加上響應首部connection:close告知客戶端,否則需要加上響應首部connection:keep-alive
所謂連接並不是一個水管連接起來,而是人們想象出來的東西。
傳統的短連接只是在發送真正的數據包前,加了一個發送握手數據包的過程。而在發送完數據包之后,加了一個揮手數據包的過程。
而長連接也只是在發送完數據包后,不着急發送揮手數據包,繼續發送數據包。
請注意,長連接是tcp/ip層面的東西,http應用只是根據connection首部去控制tcp/ip層數據包而已,這一點非常重要。
在HTTP中代理要用什么方式去連接server,代理說了算。客戶端能控制的只是自己與代理之間的連接。
HTTP代理
首先看普通的CS模型

然后來看一下中間有代理的

有區別的地方我用紅框標出來了,第一個紅框不難理解,先解釋第二個紅框吧
代理服務多種多樣,有聰明的即能完整做到http協議的,也有笨的只能做到一部分http協議的,我們稱之為盲中繼。
在http協議中,代理層是不允許轉發connection首部,而盲中繼則會轉發connection首部
如果轉發了connection首部,意味着客戶端可以控制代理層與server之間的連接,讓我們來看看問題

以上圖為例,盲中繼會將connection首部進行轉發,並且往往在響應和請求時都只支持http1.0
帶來的結果是:服務器認為自己在進行長連接,客戶端也認為自己在進行長連接,但代理層根本不知道什么長連接
於是代理層認為server應該關閉連接,於是該連接掛起。與此同時客戶端認為自己在進行長連接,於是繼續發送http事物給代理,代理層則忽略客戶端發來的任何請求,於是一直在打圈,在超時后,連接斷開。
這種問題我們是不想看到的,雖然我們規定了代理層不允許轉發connection首部,但我們又不能要求所有人都不使用盲中繼,於是就有了上面的那種解決方案:
當代理層理解http事物時,他將請求頭改成了connection:keep-alive發送給Server。
盲中繼則是繼續無腦轉發,而proxy-connection只被服務器當成了一個普通首部而不會影響
注意上面幾張圖http協議版本號的轉化
最后說說第三個框,squid代理中,響應請求使用的是http1.0,發送請求時使用的是http1.1,具體為什么,可能是因為我的squid版本比較老造成的,我們要知道,發請求遠比處理請求簡單的多。據說squid3.0可以完美支持http1.1響應了。
最后我們在命令行中證明一下上面的結論。
不經過代理
HTTPS代理
HTTPS只是在http與tcp之間加了一個ssl層,
重要的是,在客戶端與代理建立連接后,客戶端發往代理的http事務數據是經過加密的,請看下圖
注意加密的只是http事務數據,tcp/ip的數據包是不會被加密的,否則路由器理解不了,這一點在之后理解長連接短連接非常重要。
在http中通過代理時,應將數據發往誰,是在http首部中定義的,如
而在https中,代理收到的http請求全是加密的,因此代理不知道該發往誰
所以代理層是這么處理的:客戶端在發送真正數據包之前,以明文方式告訴代理應將報文發往誰即可,請看下圖。
也就是說,客戶端先使用connect方法讓代理與server事先建立好一個連接,代理收到同一客戶端的后續請求,只需使用事先建立好的連接即可。
因此https代理必須支持connect方法
最后在命令行中驗證一下
telnet 實現
由於代理層收到的都是加密的http報文,因此代理能做到的僅僅是無腦轉發http報文,這種行為我們叫做隧道。
但是注意只是http報文被加密了,tcp/ip報文依然是明文的,如果連tcp/ip報文都被加密,路由器就無法理解了,也就無法傳遞了。
而tcp長短連接,是在tcp/ip報文中控制的。
在http中,client和server可以根據connection首部來判斷后發送相應的tcp/ip報文。
由於代理無法理解http行為,因此也無法在http層面上根據connection頭來控制長連接。
因此長短連接均由cilent和server的connection控制,這點是與http有決定性不同的
因此如果一條連接發生了斷開請求,另一端一定會立刻開始斷開,可以說,https中代理的兩側連接是同步的,來看一下。
HTTP代理:由於代理層可以理解http報文,則可能出現客戶端與代理通信是短連接,而代理與服務器間通信是長連接的情況。
HTTPS代理:由於代理詞只能收到加密的http報文,無法根據connection首部判斷發送相應的tcp/ip報文,只能根據client或者server的tcp/ip報文來轉發,因此兩側的連接狀態是相同的。
最后,同樣由於https代理是無法添加http首部的,所以server無法獲得client的ip,而http中是可以的。
over