流程圖
DNS解析
- 本地域名服務器查找有沒有www.kaola.com所對應的ip
- 本地服務器未查找到,則去根域名服務器查找
- 根域名服務器未找到相應ip,會返回一級域名服務器地址
- 查找一級域名服務器
- 一級域名服務器未找到相應ip,返回二級域名服務器地址
- 查找二級域名服務器
- 二級域名服務器查看本地name.conf,是否有www主機的記錄
- 查到www主機的記錄,返回www主機的ip到二級域名服務器
- 返回ip到本地域名服務器
- 返回ip到瀏覽器
http請求
HTTP請求 客戶端根據域名獲得相應ip之後開始發送http請求,HTTP請求分爲三個部分:
TCP三次握手、http請求響應信息、關閉TCP鏈接html
TCP三次握手
http請求信息
http請求報文 TTP請求報文由請求行(request line)、請求頭部(header)、請求主體三個部分組成。以下圖所示: nginx
- 請求行包含:請求方法、URL、協議版本 請求方法包含8種:GET、POST、PUT、DELETE、PATCH、HEAD、OPTIONS、TRACE。 URL即請求地址,由 <協議>://<主機>:<端口>/<路徑>?<參數> 組成 協議版本即http版本號
- 請求頭部包含請求的附加信息,由 名/值 對組成
請求頭部通知服務器有關於客戶端請求的信息。它包含許多有關的客戶端環境和請求正文的有用信息。其中好比:Host,表示主機名,虛擬主機;Connection,HTTP/1.1 增長的,使用 keepalive,即持久鏈接,一個鏈接能夠發多個請求;User-Agent,請求發出者,兼容性以及定製化需求
- 請求主體包含回車符、換行符和請求數據,並非全部請求都具備請求數據
MVC
http請求報文發送後,通過nginx服務器轉發、服務端servlet處理請求以後,響應信息會以響應報文的形式返回給客戶端。
後續開一章 比較偏後端的mvc整個請求git
http響應信息
響應報文由響應行(request line)、響應頭部(header)、響應主體三個部分組成。以下圖所示: github
- 響應行包含:協議版本,狀態碼,狀態碼描述
狀態碼規則以下:
1xx:指示信息--表示請求已接收,繼續處理。
2xx:成功--表示請求已被成功接收、理解、接受。
3xx:重定向--要完成請求必須進行更進一步的操做。
4xx:客戶端錯誤--請求有語法錯誤或請求沒法實現。
5xx:服務器端錯誤--服務器未能實現合法的請求。
- 響應頭部包含響應報文的附加信息,由 名/值 對組成
- 響應主體包含回車符、換行符和響應返回數據,並非全部響應報文都有響應數據
關閉TCP鏈接
瀏覽器處理返回的信息(html、json等)
瀏覽器處理json
TCP拓展
拿到域名對應的IP地址以後,User-Agent(通常是指瀏覽器)會以一個隨機端口(1024 < 端口 < 65535)向服務器的WEB程序(經常使用的有httpd,nginx等)80端口發起TCP的鏈接請求。這個鏈接請求(原始的http請求通過TCP/IP4層模型的層層封包)到達服務器端後(這中間經過各類路由設備,局域網內除外),進入到網卡,而後是進入到內核的TCP/IP協議棧(用於識別該鏈接請求,解封包,一層一層的剝開),還有可能要通過Netfilter防火牆(屬於內核的模塊)的過濾,最終到達WEB程序後端
TCP報文格式
TCP/IP協議的詳細信息參看《TCP/IP協議詳解》三卷本。
下面是TCP報文格式圖:瀏覽器
上圖中有幾個字段須要重點介紹下:
(1)序號:Seq序號,佔32位,用來標識從TCP源端向目的端發送的字節流,發起方發送數據時對此進行標記。
(2)確認序號:ack序號,佔32位,只有ACK標誌位爲1時,確認序號字段纔有效,Ack=Seq+1。
(3)標誌位:共6個,即URG、ACK、PSH、RST、SYN、FIN等,具體含義以下:
- URG:緊急指針(urgent pointer)有效。
- ACK:確認序號有效。
- PSH:接收方應該儘快將這個報文交給應用層。
- RST:重置鏈接。
- SYN:發起一個新鏈接。
- FIN:釋放一個鏈接。
seq:首次是隨機產生 後面是等於返回的ack
ack:指望收到對方下一個報文段的第一個數據字節序號服務器
TCP三次握手
假如服務器B和客戶機A通信. 當A要和B通訊時
- A首先向B發一個SYN (Synchronize) 標記的包,告訴B請求創建鏈接. 注意: 一個 SYN包就是僅SYN標記設爲1的TCP包. 只有當B受到A發來的SYN包,纔可創建鏈接,除此以外別無他法。
- 接着,B收到後會發一個對SYN包的確認包(SYN/ACK)回去,表示對第一個SYN包的確認,並繼續握手操做. 注意: SYN/ACK包是僅SYN 和 ACK 標記爲1的包.
- A收到SYN/ACK 包,A發一個確認包(ACK),通知B鏈接已創建。至此,三次握手完成,一個TCP鏈接完成 注意: ACK包就是僅ACK 標記設爲1的TCP包.
序號 |
方向 |
seq |
ack |
SYN |
ACK |
1 |
A->B |
10000 |
0 |
1 |
0 |
2 |
B->A |
20000 |
10000+1=10001 |
1 |
1 |
3 |
A->B |
10001 |
20000+1=20001 |
0 |
1 |
第一次握手:A向B發起鏈接請求,以一個隨機數初始化A的seq,這裏假設爲10000,此時ACK=0
第二次握手:B收到A的鏈接請求後,也以一個隨機數初始化B的seq,這裏假設爲20000,意思是:你的請求我已收到,我這方的數據流就從這個數開始。B的ack是A的seq加1,即10000+1=10001
第三次握手:A收到B的回覆後,它的seq是它的上個請求的seq加1,即10000+1=10001,意思也是:你的回覆我收到了,我這方的數據流就從這個數開始。A此時的ACK是B的seq加1,即20000+1=20001mvc
數據傳輸過程當中seq和ack的值:
序號 |
方向 |
seq |
ack |
size |
23 |
A->B |
40000 |
70000 |
1514 |
24 |
B->A |
70000 |
40000+1514-54=41460 |
54 |
25 |
A->B |
41460 |
70000+54-54=70000 |
1514 |
26 |
B->A |
70000 |
41460+1514-54=42920 |
54 |
這個54能夠先不考慮 當作不存在便可 有興趣本身查查3d
TCP四次揮手
假如服務器B和客戶機A通信. 當A要和B通訊時
- 客戶端A沒有要發送給服務端B的數據了,想要關閉連接,則發送一個FIN=1,ACK=1的包,告訴B能夠關閉鏈接了,我沒有什麼數據要給你了。
- 而後B會發送ACK=1的包給A,告訴A我知道你沒有什麼想給個人了,可是我還有數據要給你,你先等下,我先不想FINISH呢。
- 等B把數據都發送給A以後,B會再次發送一個包,此次FIN=1,表示我這邊也想關閉了,咱倆一塊兒關把 。
在2和3之間,可能還會有不少B->A的傳遞,ack均爲80001
- 而後A迴應一個ACK,表示我知道了,一塊兒關吧。B收到這個ACK後,就會CLOSE 可是實際上A不會直接CLOSE,還會進入一個等待時間狀態TIME_WAIT
四次揮手過程當中seq和ack的值:
TCP鏈接的結束是四次揮手的過程,ACK一直等於1
序號 |
方向 |
seq |
ack |
FIN |
ACK |
1 |
A->B |
80000 |
90000 |
1 |
1 |
2 |
B->A |
90000 |
80000+1=80001 |
0 |
1 |
3 |
B->A |
95000 |
80001 |
1 |
1 |
4 |
A->B |
80001 |
95000+1=95001 |
0 |
1 |
參考
github.com/kaola-fed/b…