看到題目,大家是不是認為根據上一篇(兩萬字長文50+張趣圖帶你領悟網路編程的內功心法)一樣,其實不然,我們上一邊介紹的是網路編程的基本功,有了這些基本功之后,我們就可以在此之上構建更加接近實際應用的web程式了,為了快速展示他們的層次關系,我用幾本書疊了起來進行說明,順便給大家推薦這幾本基本算是這些領域比較權威的書籍,如下圖,由下往上看:

- TCP/IP構成了網路編程的基礎設施;
- Socket套接字編程為應用層提供了訪問TCP/IP協議堆疊的介面;
- 在應用層上面,指定了面向Web編程的HTTP協議;
- Tomcat是實作HTTP協議的一個應用服務器,
在 兩萬字長文50+張趣圖帶你領悟網路編程的內功心法 一文中,我們詳細介紹了TCP/IP協議,從物理層一直講到了應用層,在應用層可以利用TCP/IP底層的能力,實作豐富的功能,而本文,我們就重點講解構建在應用層上的協議:HTTP協議,
首先,我們來思考一個問題,HTTP是怎么來的,為什么要創造HTTP,HTTP接下來會怎么發展呢?這就得聊聊HTTP的發展演變史了,
閱讀本文的同時,我們可以看到整個HTTP的發展演變史,可以發現,假設規范是一個小伙子,一般來說,一個優秀的小伙子從來不是出生之后就是優秀的,而是隨著業務場景,技術挑戰的產生,不斷的被拉去勞改,學習,在憂患中蛻變進化,所以現在所謂的標準、成熟的技術,未必符合所有的場景,是技術的挑戰與創新促成了新事務的發展,
(前方高能預警:此處有篇高考高分作文??...)如果Google只滿足于HTTP/1.1,就不會推出SPDY促進HTTP/2的誕生了;如果Google只滿足于SPDY,就不會推出QUIC促進HTTP/3的誕生了;如果快手只滿足于HTTP/1.1,就不會自己實作一套kQUIC了;如果我只滿足于通過HttpClient發起HTTP呼叫,就不會寫這篇文章了,
還記得那個學術風濃厚的OSI網路模型嗎,最終是被TCP/IP給蓋過了風頭,深入應用場景,深入業務,挖掘痛點,探索折騰起來吧,哦對了,最重要的一點:計算機基礎知識得打牢固,
1、HTTP發展演變史
話不多少,我直接畫了一個圖,總結一下HTTP的演變史,一個從誕生之日開始就不斷被勞改的小伙子,一路被互聯網巨頭和互聯網標準化組織IETF逐漸帶上正軌的心酸歷史,它還有很長一段路需要走:


1.1、時代背景
在HTTP協議誕生以前,都有哪些事情的發生,為其做好了鋪墊呢?下面來看看,

接下來,我會請出我們的機器人為我們總結每個小節的技術,格式如下:

每個版本的協議都會有很多特性,這個章節會把相關特性或者技術點描述出來,但是在發展演變史這章節不會細講,我們后面會有專門章節為你揭秘HTTP技術點的詳細實作原理,
所以,本章節主要是為您梳理HTTP的發展演變史,知道技術的來龍去脈,以及接下來的發展趨勢,
1.1.1、ARPANET
ARPANET(Advanced Research Projects Agency Network)是第一個具有分布式控制的廣域分組交換網路,該網路由美國國防部高級研究計劃局建立,
為了實作對遠程計算機的訪問,美國互聯網先驅 Bob Taylor 在1966年啟動了ARPANET專案,1969年連接了第一臺計算機,在1970年實作了網路控制程式,
關于為何要搞這樣的技術,據ARPA的總監Charles Herzfeld說:因為當時美國直郵數量有限的大型的研究計算機,而許多應該使用這些計算機的研究人員由于地理空間問題導致不能很好使用起來,這使他們感到很挫敗,所以就提出了這個研究計劃,當然也有傳言是處于軍事目的,實作對核力量的控制,改善軍事戰術和管理決策,但不管怎樣,網路世界從此往前邁進了一大步,

1.1.2、TCP/IP
在70年代的時候,基于ARPA網路的發展,研究人員指定了傳輸控制方案,最終演變成了一個協議,通過該協議可以將多個單獨的網路合成一個網路,這個協議也就是TCP/IP,
在1983年UNIX作業系統BSD誕生了,其內核就包含了網路編程套接字的設計和實作,TCP/IP就這么被BSD帶起來了,最終逐漸成為了事實的標準,
可以說UNIX套接字聯網API就是網路編程的一個源頭了,所以大學老師教網路編程的時候大概率會推薦這本書:《UNIX網路編程 卷1:套接字聯網API》,當時我們老師也推薦了這本書,雖然當時大概率不會細看,但是遲早會用到的,

1.1.3、OSI參考模型
兩萬字長文50+張趣圖帶你領悟網路編程的內功心法 一文我們也提到了,為了制定一個統一的計算機網路體系,國際標準化組織ISO提出了一個試圖使各種計算機可以在世界范圍內互聯成網的標準框架:OSI/RM(Open System Interconnection Reference Model 開放系統互連基本參考模型),
不過嘛,這個標準是1984年發布的,此時TCP/IP已占據大半江山,逐漸成為了事實的標準,而且OSI更加學術,上一篇文章我們也提到了OSI的一些缺點,導致其不能取代TCP/IP,TCP/IP則是在實踐中得到了驗證,
1.1.4、World Wide Web
好了,萬事具備,我們離HTTP的誕生越來越接近了,
在1989年,英國工程師兼計算機科學家 Timothy Berners-Lee 在1989年發明了World Wide Web萬維網,萬維網是資訊時代發展的核心,他開發了三種基礎技術:
- URI:統一資源識別符號;
- HTML:超文本標記語言;
- HTTP:超文本傳輸協議;
是什么促成了 Timothy Berners-Lee 發明萬維網呢?在CERN作業的時候,他對查找存盤在不同計算機上的資訊所帶來的低效率和困難感到沮喪,于是,他想CERN管理層提交了一份備忘錄:《資訊管理:一項提案》,逐漸促成了可以在檔案中通過單擊滑鼠跳轉到其他參考的檔案的系統的實作,這種呈現形式的檔案被稱為超文本,
HTTP誕生了,

1.2、HTTP/0.9
1991年,是一個單純的年代,網上只有文字,看不了圖,看不了片,在如此單純的環境下,Timothy Berners-Lee設計了HTTP協議的0.9版本,為啥不給多個0.1湊個整呢,因為跟我們現在用的HTTP1.1+協議比起來實在是簡單多了:
- 基于客戶端服務端的請求回應協議;
- 沒有首部;
- 沒有狀態碼;
- 只支持純文本,其設計目標是獲取HTML;
- 只支持GET方法;
- 每次請求都建立新的TCP連接;
但是這也是滿足那個純真年代的需求了,保持簡單,避免過度設計也好,為后續擴展留了個口子,

1.2.1、報文示例
HTTP/0.9協議下通過瀏覽器訪問:https://www.itzhai.com/hello-world.html
在建立了TCP連接之后,最終瀏覽器會發送報文如下:
GET /hello-world.html
GET后面為什么是資源路徑,而不是URL呢?
因為瀏覽器首先是拿到了URL對應的IP地址,然后建立TCP連接,一旦連接到服務器,就不需要協議,服務器,和埠號了,第二節我們會抓包演示,
回應也非常簡單,僅僅由HTML檔案本身組成:
<html>
<body>
welcome to itzhai (www.itzhai.com), wechat account: itread.
</body>
</html>
可以發現:
- 沒有HTTP首部,也就意味著只能傳輸HTML檔案;
- 沒有狀態碼:出現問題的時候,只能發送一個特定的HTML檔案,其中包含問題的描述,以供人們解讀錯誤資訊,
1.3、HTTP/1.0
人們的欲望是那么的沒有止境呀,后來又想在網上看小圖片,又想聽音樂,不單單只是看文字了,還想自己寫段子到網上,這么多需求來了,只能升級HTTP協議了,在1996年5月,HTTP作業組發布了RFC 1945[1],在該檔案中記錄了許多HTTP/1.0實作的通用方法,于是HTTP/1.0就誕生了,
HTTP/1.0跟我現在用的HTTP/1.1比接近了,加了如下概念:
-
增加了首部:
- Allow
- Authorization
- Content-Encoding
- Content-Length
- Content-Type
- Date
- Expires
- From
-
增加了16個回應狀態碼;
-
引入了重定向;
-
內容編碼(壓縮):
-
content-coding = "x-gzip" | "x-compress" | token
-
-
更多的請求方法:GET,HEAD,POST;
-
傳輸資料不限于文本;
更詳細的內容,參考RFC 1945[1:1],
但是,HTTP/1.0并不是一個正是規范或Interger標準,只是一個已有實踐的參考檔案,沒有約束力,對當時的互聯網來說沒有太大的推進作用,
另外,HTTP/1.0也是有很多瑕疵的,比如不能讓多個請求共用一個TCP連接,缺少強制的Host首部,并且快取比較控制比較粗糙,

如何復用TCP連接?
有些瀏覽器在請求的時候,會使用一個非標準的Connection欄位:
Connection: keep-alive這個表示客戶端端要求服務器不要關閉TCP連接,以便其他請求可以復用,服務器同樣的回應這個欄位,
1.3.1、報文示例
HTTP/1.0協議下通過瀏覽器訪問:https://www.itzhai.com/hello-world2.html
請求報文如下所示:
GET /hello-world2.html HTTP/1.0
User-Agent: NCSA_Mosaic/2.0 (Windows 3.1)
Accept: */*
回應報文如下所示:
200 OK
Date: Tue, 15 Nov 1996 08:00:00 GMT
Server: Apache 0.84
Content-Type: text/html
<html>
<body>
welcome to itzhai (www.itzhai.com), wechat account: itread.<br/>
<img src="https://www.itzhai.com/resources/images/itzhai_qrcode.jpeg" width="100px">
</body>
</html>
由于瀏覽器拿到回應的HTML之后,決議到里面還有一個img圖片請求,于是又發起了第二個連接獲取圖片:
GET /resources/images/itzhai_qrcode.jpeg HTTP/1.0
User-Agent: NCSA_Mosaic/2.0 (Windows 3.1)
回應報文如下所示:
200 OK
Date: Tue, 15 Nov 1996 08:00:01 GMT
Server: Apache 0.84
Content-Type: image/jpeg
(image content)
1.4、HTTP/1.1
將HTTP轉變為正式的IETF Internet標準的作業與圍繞HTTP/1.0檔案編制作業并行進行,
有道是,有競爭才會有進步,微軟在1995年推出的Windows系統中發布了IE瀏覽器,與當時的瀏覽器霸主Netscape瀏覽器展開對抗,IE逐步占有了更多的市場,直到1998年Netscape被AOL收購后,IE的市場還在不斷攀升,在兩大瀏覽器互相廝殺期間,HTTP/1.1誕生了,

在1997年1月,發布了HTTP/1.1的第一個正式標準 RFC2068[2],然后,在兩年半之后的1999年6月,許多改進和更新被納入該標準,并以 RFC 2616[3]的形式發布,
HTTP/1.1有如下特性:
-
新增了POTIONS、PUT、DELETE、TRACE、CONNECT等新方法;
-
強化了快取管理和控制;
-
支持維持持久連接,支持通知服務器棄用連接;也就是說TCP連接默認不關閉,可以被多個請求復用,不用宣告
Connection: keep-alive; -
請求HTML檔案的時候要求攜帶編碼、字符集、cookie元資料等資訊;
-
支持原始HTML請求的分塊回應,利于傳輸大檔案;
就這樣,一個最穩定版本的HTTP協議誕生了,直到現在,仍然有很多網站在使用HTTP/1.1協議,

在HTTP/1.1期間,涌現了很多互聯網企業,如,Google,騰訊,百度,阿里,淘寶,美團頭條等,

1.4.1、報文示例
請求報文:
GET /hello-world2.html HTTP/1.1
Host: www.itzhai.com
Connection: keep-alive
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.125 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7
If-None-Match: "9a3bee90-q1"
If-Modified-Since: Tue, 18 Aug 2020 15:06:33 GMT
回應報文:
HTTP/1.1 200 OK
Date: Tue, 18 Aug 2020 15:30:57 GMT
Last-Modified: Tue, 18 Aug 2020 15:06:33 GMT
Content-Type: text/html
Content-Length: 192
ETag: "5f3bee79-c0"
Accept-Ranges: bytes
<html>
<body>
welcome to itzhai (www.itzhai.com), wechat account: itread.<br/>
<img src="https://www.itzhai.com/resources/images/itzhai_qrcode.jpeg" width="200px">
</body>
</html>
HTTP/1.1具體特性說明我們第二節會講到,
本文首次發表于: HTTP發表演變史 以及公眾號 Java架構雜談,未經許可,不得轉載,
1.5、HTTP/2
當然,HTTP/1.1的問題也是很多的,主要是連接緩慢,服務器只能按順序回應,如果某個請求花了很長時間,就會出現請求隊頭阻塞,從而影響其他請求,
這個時期出現了很多各式的前端優化小技巧,當年搞過一段時間前端,也對這些技術略知一二,如:
- 為了增加并發請求,做域名拆分;
- CSS、JS等資源行內到HTML中,或者進行資源合并;
- 生成精靈圖,一次性傳輸所有小圖示;
- 資源預取...
最終,為了推進從協議上進行優化,Google跳出來了,推出了SPDY協議,
1.5.1、SPDY
為啥Google敢推出這樣的協議呢,主要還是因為在2008年誕生的Chrome瀏覽器迅速占據了市場,擁有了大部分用戶,挾天子以令諸侯,嘗試推廣新技術是水到渠成的事情,

SPDY是Google開發,用于傳輸Web內容的協議,SPDY協議減少了網頁加載延遲,并且提高了We標的安全性,
SPDY主要通過幀和首部壓縮、多路復用和優先級屬性降低等待時間,
SPDY誕生之后,很快被整合進Chrome和Firefox,最終被所有主流瀏覽器所采用,另外服務器和網路代理也對SPDY提供了必要的支持,
SPDY的核心人員后來都參與到了HTTP/2的開發,在2015年2月,Google宣布最終批準HTTP/2標準之后,也就不再繼續支持SPDY協議了,并且最終在Google Chrome 51中洗掉了SPDY的支持,
1.5.2、HTTP/2
HTTP/2又解決了HTTP/1.1面臨的大部分問題,主要有如下功能:
- 使用虛擬的流傳輸訊息,解決了HTTP一個連接中應用層的隊頭阻塞的問題;
- 使用了二進制協議,不再是純文本,避免文本歧義,縮小了請求體積;
- 實作了多路復用,提高了連接的利用率,在擁塞控制方面有了更好的能力提升;
- 使用HPACK首部壓縮方案壓縮頭部資訊,大大節約了帶寬;
- 增強了安全性,使用HTTP/2,要求必須至少用TLS1.2;
- 允許服務器主動向客戶端推送資料;

1.6、HTTP/3
HTTP/2還在草案的時候,Google又發現新的問題了,那就是由于HTTP/2依賴于TCP,TCP有什么問題,那么HTTP/2就會存在什么問題,最主要的問題還是隊頭阻塞問題:隊頭阻塞問題在應用層解決了,但是在TCP協議層并沒有解決:
- 上一篇文章我們提到過TCP在丟包的時候會進行重傳,前面有一個包沒有接收到,就只能把后面的包先放到緩沖區里面,應用層實際上是無法取資料的,也就是說HTTP / 2的多路復用的并行性對于TCP的丟失恢復機制不管用,因此丟失或者重新排序的資料報都會導致所有活動事務陷入停頓,
為了解決以上問題,于是Google發明了gQUIC(Quick UDP Internet Connection)協議,
1.6.1、QUIC
QUIC是最初由Google開發的一種傳輸層網路協議,在QUIC協議中,傳輸層用UDP替換掉了TCP,并在用戶空間實作了一套擁塞控制演算法,從而避免了TCP的隊頭阻塞問題,
在UDP之上,QUIC實作了連接管理、擁塞視窗、流量控制等,
后來IETF HTTP和QUIC作業組主席Mark Nottingham提出了正式請求,將HTTP-over-QUIC重命名為HTTP/3,
1.6.2、HTTP/3
HTTP / 3使用與HTTP/1.1和HTTP/2相同的語意(相同的操作,例如GET和POST)和相同的回應代碼(例如200或404),但是使用QUIC傳輸協議協議,以及采用類似于HTTP/2的內部成幀層提供HTTP語意的傳輸,

HTTP/3進展如何?
截止到2020年8月,HTTP/3協議已經成為Internet草案,并且具有多種實作方案,前1000萬個網站中有6.7%支持HTTP / 3,在瀏覽器方面,Firefox和Chrome穩定版本都支持HTTP/3,但是默認情況下是禁用的,Safari 14將默認啟用HTTP/3,
想進一步了解,可以閱讀最新的發布于2020年8月14日的HTTP/3草案:Hypertext Transfer Protocol Version 3 (HTTP/3)[4]
目前我們使用最廣發的還是HTTP/1.1,接下來我就基于HTTP/1.1來介紹下HTTP協議,
接下來,由于篇幅所限,為了給大家呈現更好的閱讀體驗,我把后續的內容分為以下章節,深入細節更精彩,歡迎大家繼續閱讀:

這篇文章的內容就介紹到這里,能夠閱讀到這里的朋友真的是很有耐心,為你點個贊,
本文為arthinking基于相關技術資料和官方檔案撰寫而成,確保內容的準確性,如果你發現了有何錯漏之處,煩請高抬貴手幫忙指正,萬分感激,
如果您覺得讀完本文有所識訓的話,可以關注我的賬號,或者點贊吧,碼字不易,您的支持就是我寫作的最大動力,再次感謝!
為了把相關系列文章收集起來,方便后續查閱,這里我創建了一個Github倉庫,把發布的文章按照分類收集起來了,感興趣的朋友可以Star跟進:
https://github.com/arthinking/java-tech-stack

關注我的博客IT宅(itzhai.com)或者公眾號Java架構雜談,及時獲取最新的文章,我將持續更新后端相關技術,涉及JVM、Java基礎、架構設計、網路編程、資料結構、資料庫、演算法、并發編程、分布式系統等相關內容,
References
- 謝希仁. 計算機網路(第6版). 電子工業出版社.
- TCP/IP詳解 卷1:協議(原書第2版). 機械工業出版社.
- UNIX網路編程 卷1:套接字聯網API. 人民郵電出版社
- HTTP權威指南. 人民郵電出版社
- HTTP/2基礎教程. 人民郵電出版社
- 劉超. 趣談網路協議. 極客時間
- 羅劍鋒. 透視HTTP協議. 即可時間
本文同步發表于我的博客IT宅(itzhai.com)和公眾號(Java架構雜談)
作者:arthinking | 公眾號:Java架構雜談
博客鏈接:https://www.itzhai.com/articles/comprehend-the-underlying-principles-of-web-programming.html
著作權宣告: 著作權歸作者所有,未經許可不得轉載,侵權必究!聯系作者請加公眾號,
Hypertext Transfer Protocol -- HTTP/1.0 RFC 1945. Retrieved from https://datatracker.ietf.org/doc/rfc1945/ ?? ??
HypertextTransferProtocol--HTTP/1.1 2068. Retrieved from https://tools.ietf.org/html/rfc2068 ??
Hypertext Transfer Protocol -- HTTP/1.1 2616. Retrieved from https://tools.ietf.org/html/rfc2616 ??
Hypertext Transfer Protocol Version 3 (HTTP/3). Retrieved from https://quicwg.org/base-drafts/draft-ietf-quic-http.html ??
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/261613.html
標籤:Java
上一篇:java反射機制的學習心得
下一篇:spring框架構成
