Android網絡編程(三) 之 網絡請求握手過程

1 一次網絡請求的過程

我們平常在瀏覽器輸入一個網址回車後經過了大概不到一秒時間的網絡請求便可展示出相應的頁面,其實這樣一次完整的網絡請求過程要經過好幾個步驟:

第一步:DNS解析IP地址;

第二步:TCP三次握手建立連接;

第三步:如果是HTTPS的話,還要進行TLS握手驗證簽名證書;

第四步:客戶端發起HTTP請求

第五步:服務器響應HTTP請求

第六步:客戶端瀏覽器接收到內容進行解析html、css、js

第七步:瀏覽器對頁面進行渲染

 

2 DNS解析IP過程

DNS( Domain Name System)叫作“域名系統”,是一種組織成域層次結構的計算機和網絡服務命名系統,它用於TCP/IP網絡,它所提供的服務是用來將主機名和域名轉換爲IP地址的工作。其過程大概是這樣:

第一步:通過java.net.InetAddress類來調用相應的方法來查看自身緩存是否存在,因爲Android系統中有對DNS做了二層的緩存處理。

第二步:如果java.net.InetAddress並沒有緩存,則再通過查看虛擬機的DNS緩存來判斷是否存在,這是第二層的緩存。

第三步:如果經過緩存後都不能解析到IP地址,則會再向本地Hosts文件來讀取解析。

第四步:如果通過以上在本機上無法完成域名的解析,那麼系統只能請求本地區的域名解析服務系統進行解析,比如校園網,如果連接的運營商網絡,那麼本地域名解析服務器就是本地區的運營商來提供服務。

第五步:如果本地域名解析服務器還沒有完成解析的話,那麼本地域名解析服務器將向根域名服務器發起解析請求。根域名服務器返回的是所查域的通用頂級域(Generic top-level domain,gTLD)地址,如:.com、.cn、.org、.edu等。

第六步:本地域名解析服務器向gTLD服務器發起請求。

第七步:gTLD服務器接收本地域名服務器發起的請求,並根據需要解析的域名,找到該域名對應的Name Server域名服務器 ,通常情況下,這個Name Server服務器就是你註冊的域名服務器,那麼你註冊的域名的服務商的服務器將承擔起域名解析的任務。

第八步:Name Server服務器查找域名對應的IP地址,將IP地址連同生存時間值(Time To Live,TTL)返回給本地域名服務器。

第九步:本地域名服務器緩存解析後的結果,緩存時間由TTL時間來控制。

第十步:返回解析結果給用戶,用戶系統將緩存該IP地址,緩存時間由TTL來控制。至此解析過程結束。

 

3 TCP三次握手

所謂的三次握手(Three-Way Handshake)即對每次發送的數據量是怎樣跟蹤進行協商使數據段的發送和接收同步,根據所接收到的數據量而確定的數據確認數及數據發送、接收完畢後何時撤消聯繫,並建立虛連接。

第一次握手:客戶端發送連接請求報文段,將SYN(Synchronize Sequence Numbers,同步序列號)設置爲1,並設置一個seq=x ,(Sequence Number,序列號)(x 是由操作系統根據一定的規則生成的,可以認爲是一個隨機數)將這個報文(SYN=1 seq=x)發送到服務器。此時,客戶端進入同步已發送狀態SYN_SEND,等待服務端的確。

第二次握手:服務器收到客戶端的請求報文段SYN後,若同意建立連接,需要對這個SYN報文段進行ACK(Acknowledgment Numbe,確認字符)確認,設置ack=x+1,同時,自己還要發送SYN請求信息,將SYN設置爲1,seq=y。服務器端將上述所有信息放到一個報文段(ACK=1 ack=x+1,SYN=1 seq=y)中一併發送給客戶端,此時服務器進入同步已接收狀態SYN_RECV

第三次握手:客戶端收到服務器的SYN+ACK報文段,要對服務器發送確認的確認,即進行ACK的確認,將ack設置爲y+1,向服務器發送ACK報文段(ACK=1 ack=y+1),這時客戶端和服務器端都進入已連接狀態狀態ESTABLISHED,完成三次握手。

例個粟子:

第一次握手:客戶端說:喂,你好,你能聽到嗎?

第二次握手:服務端說:你好,我能聽到,你能聽到我講話嗎?

第三次握手:客戶端說:我也能聽到你講話

經過對話確認相互聽到這後,他們就可以互相開始講話了…

爲什麼要採用三次握手,而兩次不行嗎?

現假設在建立連接過程中出現一種異常情況:客戶端發出的第一個連接請求報文段並沒有丟失,而是在某些網絡結點長時間滯留了,以致延誤到連接釋放以後的某個時間纔到達服務端。本來這是一個早該失效的報文段,但是服務端收到了此失效的連接請求了,它並不知道這是一個失效的請求,就誤以爲是客戶端又發出一次新的連接請求,於是就向客戶端發出確認報文段,同間建立連接。我們假設不採用三次握手,那麼這時連接關係就會被建立了。

由於現在客戶端並沒有發出建立連接的請求,因此是不會理睬服務端的確認的,也不會向服務端發送數據,但是服務端卻以爲已經建立了連接,並一直等待客戶端發數據,這樣服務端的就會造成資源浪費。

所以採用三次握手就可以有效防止上述現象的發生。當第三次握手時,客戶端不會向服務端的確認發出確認,服務端由於收不到確認的確認,就會明白客戶端其實並沒有要求建立連接。

 

4 四次揮手

跟三次握手相對的是四次揮手(Four-Way Wavehand),就是指斷開一個TCP連接時,揮手方可以是客戶端也可以是服務端,他們之間總共發送4個包以確認連接的斷開,其過程如下:

第一次揮手:主機A發送斷開報文段,將FIN(Finish Number)設置爲1,並設置一個seq=u(u是上一個最後傳輸的字節序號+1)將這個報文(FIN=1 seq=u發送後,主機A進入終止等待1狀態FIN_WAIT_1

第二次揮手:主機B收到主機A發來的FIN報文段,需要對這個該報文段進行ACK確認,設置ack=u+1,並且帶上序列號seq=v,主機B將上述所有信息放在一個報文段(ACK=1 ack=u+1 seq=v)中一併發回給主機A,此時主機B進入關閉等待狀態CLOSE_WAIT。當主機A收到主機B的確認請求後,此時主機A就會進入終止等待2狀態FIN_WAIT_2,等待主機B發送連接釋放報文,此時主機B還可以對主機A進行正常數據發送。

第三次揮手:如果主機B將最後的數據都發送完畢後,已經沒有要發送的數據,則會向主機A發送連接釋放報文,將FIN設置爲1,並選擇seq=w和ACK確認,設置ack=u+1,將該釋放報文(FIN=1 seq=w, ACK=1 ack=u+1)發出,此時主機B進入最後確認狀態LAST_ACK

第四次揮手: 主機A收到釋放報文後,就需要發出最後確認,將ack設置爲w+1,並且帶上序列號seq=u+1,向主機B發送報文段(ACK=1 ack=w+1 seq=u+1),此時主機A進入了時間等待狀態TIME_WAIT,此時TCP連接並沒立刻斷開,而是經過2*MSL(最長報文段壽命,通常爲2分鐘,爲了確保這段時間內不會重新創建相同地址和端口的新連接)的時間後才撤銷傳輸控制塊,進入關閉狀態CLOSED。在這時間內,當主機B收到主機A發出的最後確認後,就會立即進入關閉狀態CLOSED並撤銷傳輸控制塊至此,TCP的四次揮手就完成了。

例個粟子:

第一次揮手:A說:我說完了,我要閉嘴了,不想再說什麼了。

第二次揮手:B說:我收到了知道你已經說完了,但是我還有話說。

經過了B也把話嘮叨完後…

第三次揮手:B說:我也說完了,我也要閉嘴了,不說了。

第四次揮手:A說:我收到了知道你也已經說完了但是A不太放心,等待了一段時間後(2個最大報文生命週期),確實沒有聽到說話了,知道該離開了; B在收到A已經知道自己說完後就立即離開了。

爲什麼連接的時候是三次握手,關閉的時候卻是四次揮手?

TCP是全雙工模式,這就意味着,當主機A發出FIN報文段時,表示告訴主機B,我的數據已經全部發送完畢了,不再發送數據了。這時主機B返回ACK報文段時,表示他已經知道主機A沒有數據發送了,但是並不代碼主要B沒有數據要發送啊,所以此時主機B還是可以發送數據到主機A的,當主機B也發送了FIN 報文段時,這個時候就表示主機B也沒有數據要發送了,就會告訴主機A,我也沒有數據要發送了。之後彼此 就會中斷這次TCP連接。

 

5 TLS握手

SSL/TLS協議的基本思路

第一步:客戶端向服務器端索要公鑰;

第二步:服務端返回包含公鑰的可信任的證書;

第三步:客戶端驗證證書確定公鑰,利用公鑰使用非對稱加密的方式進行私密協商如何生成對話密鑰(非對稱加密效率低,但安全性高,所以說服務器公鑰只用於加密"對話密鑰"本身)

第四步:服務端收到協商後解密結果,往後雙方通信就使用對稱加密方式生成對話密鑰(對稱加密效率高,減少通信耗時)

四次握手的詳細過程

第一次握手:客戶端向服務器發出加密通信的請求(ClientHello),提供以下信息:

         支持最高的協議版本version,如:TLS1.2

         支持的加密套件cipher suites列表:身份驗證算法、密鑰交換算法、對稱加密算法和信息摘要

         支持的壓縮算法compression methods 列表,用於後續的信息壓縮傳輸

隨機數random_C,用於後面生成對話密鑰

擴展字段 extensions,支持協議與算法的相關參數以及其它輔助信息等

第二次握手:服務端收到客戶端請求後便迴應請求(server_hello + server_certificate + sever_hello_done)(如果服務端也要求客戶端提供證書,像網銀中的U盾類的,則會在此再包含一項請求):

         server_hello:服務端返回協商的信息結果,包括以下信息:

                   協議版本version

                   確認使用加密套件cipher suite

                   選擇的壓縮算法 compression method

                   隨機數 random_S,用於後面生成對話密鑰

                   擴展字段 extensions,支持協議與算法的相關參數以及其它輔助信息等

         server_certificates:含公鑰的服務器端配置的證書

         server_hello_done:通知客戶端信息發送結束

第三次握手:客戶端收到服務器迴應以後,會對返回的證書進行驗證。如果證書不是可信機構頒佈、或者證書中的域名與實際域名不一致、或者證書已經被吊銷、或者證書已經過期,就會向訪問者顯示一個警告,由其選擇是否還要繼續通信。如果證書沒有問題,客戶端繼續向服務器發送信息(client_key_exchange  +  change_cipher_spec  +  encrypted_handshake_message(Finished))(如果服務端要求客戶端也提從證書,像網銀中的U盾類的,則在此發送證書及其相關信息):

         client_key_exchange:計算產生隨機數字pre_master,並利用證書提取的公鑰使用非對稱加密的方式進行加密傳遞

(客戶端此時已經掌握計算對話密鑰的方法:enc_key=Fuc(random_C, random_S, pre_master))

         change_cipher_spec:表示後續的通信都將採用雙方協商的密鑰和加密算法進行加密通信

         encrypted_handshake_message:通知結束握手,結合前面發送通信所有內容的hash值與其它相關信息生成一段數據,用於供服務端進行校驗

第四次握手:服務端收到客戶端傳遞的加密過的pre_master後用私鑰進行解密,也通過enc_key=Fuc(random_C, random_S, pre_master)計算出對話密鑰,然後給客戶端回覆信息(change_cipher_spec  +  encrypted_handshake_message(Finished)):

         change_cipher_spec:表示後續的通信都將採用雙方協商的密鑰和加密算法進行加密通信

         encrypted_handshake_message:通知結束握手,結合前面發送通信所有內容的hash值與其它相關信息生成一段數據,用於客戶端進行校驗

 

至此,整個TLS握手階段全部結束。接下來,客戶端與服務器進入的通信,就是普通的HTTP協議,只不過用上了對話密鑰加密了內容。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章