瀏覽器與服務器響應流程


前言

大三注定是一段不安定的日子。恰逢騰訊實習生招聘,這么好的機會,自己也是不甘人后,心里也很想通過這次機會來檢驗自己的學習成果的,年輕人,總得試試看。雖然最終進不了二面,但還是有所收獲的,寫下一些經驗看法,就當作是為未來攢RP吧。1. 不得不佩服大公司的面試流程很規范,雖然去筆試的時候,出現了來霸筆的同學拿不到試卷的情況(估計tx也沒想到來霸筆的人會有這么多),其他一切還是挺好的。2. 這次筆試的內容主要考了C,數據結構和算法,操作系統,計算機網絡,軟件工程(印象中沒有考數據庫,不過個人感覺數據庫也挺重要的),都是基礎,難度不是很大,可見大公司還是非常重視基礎的,我自己在做題的過程中,還是感覺基礎不夠扎實,特別是C這一塊,還有一些其他基本概念也沒有記牢,本以為筆試就不過的,后來發短信告訴我過了,我還是比較驚訝的(也許我還是有點基礎的,哈)。筆試的附加題是關於海量數據的處理的,第一道題是說QQ有30億用戶,有一個log文件是專門來儲存QQ登錄記錄的,記錄行包括QQ號碼,登錄時間,登出時間,IP地址。這個log文件非常大(具體我也忘了題目說的有多大),有一小題是這樣問的:如何找出一天登錄的用戶有多少(不重復),大概需要多少內存空間。我的大概思路是這樣的(沒看過正確答案,估計這種開放題也沒有所謂的正確答案,如果你有更好的實現方案,歡迎留言告訴我!):根據登錄時間找出所有當天登錄用戶QQ號碼 --> 剔除重復項 --> 統計個數。至於需要多少內存空間,我覺得統計的時候應該是在內存中統計的,所以我使用了位圖的數據結構,因為QQ號碼有一個特性:唯一不重復數字,這樣就可以用位置來表示QQ號碼,第1個比特位表示QQ號碼0,...第N個比特位表示QQ號碼N-1,如果這個號碼在當天登錄就把這個比特位記為1,沒有就為0,所以大概需要(30*10^9/8)個字節的存儲內存。3. 整個面試感覺自己的表達能力還行,也不是很緊張,但出現了兩個致命傷,一個是問數據庫物理索引和聚集索引區別是什么(這個我是真的沒接觸過),另一個是問TCP/IP三次握手的(!!我竟然回答我忘了,天吶,我真的忘了,其實去面試的時候我基本只准備了數據結構,結果數據結構一點也沒有問!),對后一個問題的回答基本宣告自掛東南枝了。(所以這篇文章的目的更多是計算機網絡方面的,也算是亡羊補牢吧。)4. .NET是我接觸比較多的技術,但現實情況是大公司招.NET的真的比較少(甚至不招),所以對於立志進大公司的人來說,.NET還是慎入,畢竟靠.NET的經歷進大公司難度更大。 

不知不覺就吹水了這么多,還是直接進入主題吧。當我們在瀏覽器中輸入了一個URL地址(如www.cnblogs.com),從等待到頁面顯示的過程中,后台究竟發生了什么處理呢?

一. 解析域名地址為IP地址

 

瀏覽器DNS緩存:以Chrome為例,在瀏覽器窗口中輸入chrome://net-internals/#dns,就可以查看當前瀏覽器DNS緩存記錄,chrome的DNS緩存過期時間還是比較短的,大約為1分鍾。

本機DNS緩存:在Windows命令行模式下輸入ipconfig /displaydns,就可以查看本機DNS緩存記錄。許多主機在啟動時從本地域名服務器下載域名和地址的全部數據庫,維護存放自己最近使用的域名的緩存。

本地域名服務器:在Windows命令行模式下輸入ipconfig /all,就可以查看本地DNS服務器的IP地址,一般而言本地域名服務器都是由ISP提供,主機通過UDP和本地域名服務器通信。如果在本地域名服務器高速緩存中搜索不到要轉換的域名,就向更高級別的域名服務器發起迭代查詢,按根域名服務器(一般查詢根域名服務器都是遵循就近原則,中國有3個根服務器,位置分別為北京,香港,台北)-> 頂級域名服務器-> 權限域名服務器的順序詢。假如本地域名服務器高速緩存中存在頂級域名服務器.com的IP地址,那么本地域名服務器可以不向根域名服務器進行查詢,而是直接向com頂級域名服務器發送UDP請求報文,這樣就可以大大減輕根域名服務器的負荷。維護本地域名服務器數據庫的主機自然應該定期地檢查域名服務器以獲取新的映射信息,而且主機必須從緩存中刪掉無效的項。

二. TCP 連接建立

由上一步獲取www.cnblogs.com的IP地址42.121.252.58后,客戶端主機就會選擇一個未使用的端口與42.121.252.58:80通信,在Windows命令行模式下輸入netstat,就可以查看當前正在活動的TCP連接。

Client首先發送一個連接試探,ACK=0 表示確認號無效,SYN = 1 表示這是一個連接請求或連接接受報文,同時表示這個數據報不能攜帶數據,seq = x 表示Client自己的初始序號。

Server監聽到連接請求報文后,如同意建立連接,則向Client發送確認。TCP報文首部中的SYN 和 ACK都置1 ,ack = x + 1表示期望收到對方下一個報文段的第一個數據字節序號是x+1,同時表明x為止的所有數據都已正確收到,seq = y 表示Server 自己的初始序號。

Client收到確認后還需再次發送確認,同時攜帶要發送給Server的數據。ACK 置1 表示確認號ack= y + 1 有效,Client自己的序號seq= x + 1。

三. 瀏覽器給服務器發送一個http請求

上一步中有提到Client收到確認后還需再次發送確認,這時就可以攜帶要發送給Server的數據,這個數據就是HTTP請求報文。

HTTP請求行:GET http://www.cnblogs.com/  HTTP/1.1

HTTP請求首部:

Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Charset: GBK,utf-8;q=0.7,*;q=0.3
Accept-Encoding: gzip,deflate,sdch
Accept-Language: zh-CN,zh;q=0.8
Connection: keep-alive
Cookie: 省略
Host: www.cnblogs.com
If-Modified-Since: Mon, 22 Apr 2013 09:12:11 GMT
User-Agent: Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.21 (KHTML, like Gecko) Chrome/25.0.1354.0 Safari/537.21

這里重點提一下Connection。

Connection設置為keep-alive,就是Server在發送響應后仍然在一段時間內保持這條連接,使同一Client可以繼續在這條連接上傳送后續的HTTP請求報文和響應報文。對於不同的web服務器,如IIS,Apache,都有不同的keep-alive 過期時間,當然如果過期時間太短,就達不到重用連接的效果,如果過期時間太長,則會造成占用資源的壞處。

四. 服務器給瀏覽器發送一個http響應

當Server接收到http請求的時候,就把請求交給專門的web服務器處理,並最終把數據發送給Client,這個數據就是HTTP響應報文。

HTTP狀態行:HTTP/1.1 200 OK

HTTP響應首部:

Cache-Control: public, max-age=62
Connection: keep-alive
Content-Encoding: gzip
Content-Type: text/html; charset=utf-8
Date: Wed, 24 Apr 2013 08:14:03 GMT
Expires: Wed, 24 Apr 2013 08:15:04 GMT
Last-Modified: Wed, 24 Apr 2013 08:13:04 GMT
Server: Tengine
Transfer-Encoding: chunked
Vary: Accept-Encoding
X-AspNet-Version: 4.0.30319
X-AspNetMvc-Version: 3.0
X-Powered-By: ASP.NET
X-UA-Compatible: IE=edge

最后就是HTTP響應主體內容--html文檔了,如果需要繼續獲取嵌套在html中的對象,且這些對象都存在於同一個服務器上時,這些HTTP請求就會重用現存TCP連接。

五. TCP 連接釋放

在正常情況下,服務器端的keep-alive過時了,就會主動發出請求釋放這條TCP連接。

 

Server發送一個連接釋放報文,FIN = 1 表示Server的數據已發送完畢,seq = v ,v等於前面已傳送過的數據的最后一個字節加1。

Client收到Server的連接釋放請求后,發送一個確認報文。ACK = 1 表示確認后ack有效,ack = u+1表示期望收到對方下一個報文段的第一個數據字節序號是u+1 ,seq = v , v等於前面Client已傳送過的數據的最后一個字節加1。

由於HTTP協議是基於請求-響應模型,所以這時Client再發送請求數據給Server已經無效了,因為Server到Client的TCP連接已關閉,不會再發送響應了。這里的Close-Wait大概是等待主機通知關閉這次TCP連接。

接下來Client就發送一個連接釋放給Server,FIN=1,ACK=1,ack = u + 1 與之前發送給Server的確認號一樣。這里的seq = v 也與之前的一樣。(個人認為Close-Wait期間Client不會再發送數據給Server,所有數據序號並沒有發生改變,正確與否有待考證)

 Server收到連接釋放報文后,便發送一個確認報文。然后進入Time-Wait,而不是立即關閉連接,原因是不保證這個確認報文沒有丟失,而Client收不到確認報文則執行超時重傳FIN+ACK,這時Server還未關閉,就可以重傳ACK。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM