Android面試題-網(wǎng)絡(luò)相關(guān)

TCP 的三次握手和四次揮手

第一次握手:客戶端發(fā)送 syn 包(syn=j)到服務(wù)器,并進(jìn)入 SYN_SEND 狀態(tài),等待服務(wù)器確認(rèn);
第二次握手:服務(wù)器收到 syn 包,必須確認(rèn)客戶的 SYN(ack=j+1),同時(shí)自己也發(fā)送一個(gè) SYN包(syn=k),即 SYN+ACK 包,此時(shí)服務(wù)器進(jìn)入 SYN_RECV 狀態(tài);
第三次握手:客戶端收到服務(wù)器的 SYN+ACK 包,向服務(wù)器發(fā)送確認(rèn)包 ACK(ack=k+1),此包發(fā)送完畢,客戶端和服務(wù)器進(jìn)入 ESTABLISHED 狀態(tài),完成三次握手。
握手過(guò)程中傳送的包里不包含數(shù)據(jù),三次握手完畢后,客戶端與服務(wù)器才正式開(kāi)始傳送數(shù)據(jù)。理想狀態(tài)下,TCP 連接一旦建立,在通信雙方中的任何一方主動(dòng)關(guān)閉連接之前,TCP 連接都將被一直保持下去。斷開(kāi)連接時(shí)服務(wù)器和客戶端均可以主動(dòng)發(fā)起斷開(kāi) TCP 連接的請(qǐng)求

斷開(kāi)過(guò)程需要經(jīng)過(guò)“四次握手”
第一次揮手:客戶端發(fā)送報(bào)文告訴服務(wù)器沒(méi)有數(shù)據(jù)要發(fā)送了
第二次揮手:服務(wù)端收到,再發(fā)送給客戶端告訴它我收到了
第三次揮手:服務(wù)端向客戶端發(fā)送報(bào)文,請(qǐng)求關(guān)閉連接
第四次揮手:客戶端收到關(guān)閉連接的請(qǐng)求,向服務(wù)端發(fā)送報(bào)文,服務(wù)端關(guān)閉連接

TCP(Transmission Control Protocol) 與 UDP(User Datagram Protocol) 的區(qū)別

  1. TCP 面向連接;UDP 是無(wú)連接的,即發(fā)送數(shù)據(jù)之前不需要建立連接
  2. TCP 提供可靠的服務(wù)。也就是說(shuō)通過(guò) TCP 連接傳送的數(shù)據(jù),無(wú)差錯(cuò)、不丟失、不重復(fù);UDP 盡最大努力交付,即不保證可靠交付
  3. TCP 面向字節(jié)流,實(shí)際上是 TCP 把數(shù)據(jù)看成一連串無(wú)結(jié)構(gòu)的字節(jié)流;UDP 是面向報(bào)文的。UDP 沒(méi)有擁塞控制,因此網(wǎng)絡(luò)出現(xiàn)擁塞不會(huì)使源主機(jī)的發(fā)送速率降低(對(duì)實(shí)時(shí)應(yīng)用很有用,如 IP 電話、實(shí)時(shí)視頻會(huì)議等)
  4. 每一條 TCP 連接只能是點(diǎn)到點(diǎn)的;UDP 支持一對(duì)一、一對(duì)多、多對(duì)一和多對(duì)多的交互通信
  5. TCP 首部開(kāi)銷(xiāo) 20 字節(jié);UDP 的首部開(kāi)銷(xiāo)小,只有 8 個(gè)字節(jié)
  6. TCP 的邏輯通信信道是全雙工的可靠信道,UDP 則是全雙工的不可靠信道

TCP 與 UDP 的應(yīng)用

TCP:HTTP、FTP、SMTP、TENET、POP3、Finger、NNTP、IMAP4
UDP:BOOTP、DHCP、NTP、TFTP、SNMP

HTTP 協(xié)議

HTTP 協(xié)議是一個(gè)基于請(qǐng)求與響應(yīng)模式的面向連接、無(wú)狀態(tài),應(yīng)用層的一種協(xié)議,支持 C/S模式,簡(jiǎn)單快速、靈活。
簡(jiǎn)單快速:協(xié)議簡(jiǎn)單,通信速度快
靈活:允許傳輸任意類(lèi)型的數(shù)據(jù)對(duì)象,由 Content-Type 標(biāo)記
無(wú)連接:每次處理一個(gè)請(qǐng)求,處理完成后既斷開(kāi)
無(wú)狀態(tài):對(duì)事務(wù)處理沒(méi)有記憶能力
HTTP 有兩種報(bào)文:請(qǐng)求報(bào)文和響應(yīng)報(bào)文
請(qǐng)求報(bào)文由請(qǐng)求行、請(qǐng)求報(bào)頭和請(qǐng)求數(shù)據(jù)組成。請(qǐng)求行:抓包第一行,包括請(qǐng)求方法、URL 和 HTTP 版本;請(qǐng)求報(bào)頭:指的就是題目中“里面的協(xié)議頭部”;請(qǐng)求數(shù)據(jù):指 POST 方式提交的表單數(shù)據(jù)
響應(yīng)報(bào)文由狀態(tài)行、響應(yīng)報(bào)頭和響應(yīng)正文組成。狀態(tài)行:狀態(tài)碼;響應(yīng)報(bào)頭:同請(qǐng)求報(bào)頭;響應(yīng)正文:服務(wù)器返回的資源數(shù)據(jù)
接下來(lái)是 HTTP 頭部,既請(qǐng)求報(bào)頭和響應(yīng)報(bào)頭,統(tǒng)稱消息報(bào)頭,消息報(bào)頭可以分為通用報(bào)頭、請(qǐng)求報(bào)頭、響應(yīng)報(bào)頭、實(shí)體報(bào)頭等。通用報(bào)頭和實(shí)體報(bào)頭既可以出現(xiàn)在請(qǐng)求報(bào)頭中,也可以出現(xiàn)在響應(yīng)報(bào)頭中,
通用報(bào)頭包含的字段如:Date、Connection、Cache-Control;
實(shí)體報(bào)頭中有:Content-Type、Content-Length、Content-Language、Content-Encoding;
請(qǐng)求報(bào)頭中包含的字段有:Host、User-Agent、Accept-Encoding、Accept-Language、Connection;
響應(yīng)報(bào)頭包含的字段:Location、Server

HTTP1.0、HTTP1.1 、 HTTP2.0 的區(qū)別

HTTP1.0 和 HTTP1.1 的區(qū)別:

  1. 長(zhǎng)連接(Persistent Connection):HTTP1.1 支持長(zhǎng)連接和請(qǐng)求的流水線處理,在一個(gè) TCP 連接上可以傳送多個(gè) HTTP 請(qǐng)求和響應(yīng),減少了建立和關(guān)閉連接的消耗和延遲,在 HTTP1.1 中默認(rèn)開(kāi)啟長(zhǎng)連接 keep-alive,一定程度上彌補(bǔ)了 HTTP1.0 每次請(qǐng)求都要?jiǎng)?chuàng)建連接的缺點(diǎn)。HTTP1.0 需要使用 keep-alive 參數(shù)來(lái)告知服務(wù)器端要建立一個(gè)長(zhǎng)連接。
  2. 節(jié)約帶寬:HTTP1.0 中存在一些浪費(fèi)帶寬的現(xiàn)象,例如客戶端只是需要某個(gè)對(duì)象的一部分,而服務(wù)器卻將整個(gè)對(duì)象送過(guò)來(lái)了,并且不支持?jǐn)帱c(diǎn)續(xù)傳功能。HTTP1.1 支持只發(fā)送 header信息(不帶任何 body 信息),如果服務(wù)器認(rèn)為客戶端有權(quán)限請(qǐng)求服務(wù)器,則返回 100,客戶端接收到 100 才開(kāi)始把請(qǐng)求 body 發(fā)送到服務(wù)器;如果返回 401,客戶端就可以不用發(fā)送請(qǐng)求 body 了節(jié)約了帶寬。
  3. HOST 域:在 HTTP1.0 中認(rèn)為每臺(tái)服務(wù)器都綁定一個(gè)唯一的 IP 地址,因此,請(qǐng)求消息中的URL 并沒(méi)有傳遞主機(jī)名(hostname),HTTP1.0 沒(méi)有 host 域。隨著虛擬主機(jī)技術(shù)的發(fā)展,在一臺(tái)物理服務(wù)器上可以存在多個(gè)虛擬主機(jī)(Multi-homed Web Servers),并且它們共享一個(gè)IP 地址。HTTP1.1 的請(qǐng)求消息和響應(yīng)消息都支持 host 域,且請(qǐng)求消息中如果沒(méi)有 host 域會(huì)報(bào)告一個(gè)錯(cuò)誤(400 Bad Request)。
  4. 緩存處理:在 HTTP1.0 中主要使用 header 里的 If-Modified-Since,Expires 來(lái)做為緩存判斷的標(biāo)準(zhǔn),HTTP1.1 則引入了更多的緩存控制策略例如 Entity tag,If-Unmodified-Since, If-Match, If-None-Match 等更多可供選擇的緩存頭來(lái)控制緩存策略。
  5. 錯(cuò)誤通知的管理:在 HTTP1.1 中新增了 24 個(gè)錯(cuò)誤狀態(tài)響應(yīng)碼,如 409(Conflict)表示請(qǐng)求的資源與資源的當(dāng)前狀態(tài)發(fā)生沖突;410(Gone)表示服務(wù)器上的某個(gè)資源被永久性的刪除。

HTTP1.1 和 HTTP2.0 的區(qū)別

  1. 多路復(fù)用:HTTP2.0 使用了多路復(fù)用的技術(shù),做到同一個(gè)連接并發(fā)處理多個(gè)請(qǐng)求,而且并發(fā)請(qǐng)求的數(shù)量比 HTTP1.1 大了好幾個(gè)數(shù)量級(jí)。HTTP1.1 也可以多建立幾個(gè) TCP 連接,來(lái)支持處理更多并發(fā)的請(qǐng)求,但是創(chuàng)建 TCP 連接本身也是有開(kāi)銷(xiāo)的。
  2. 頭部數(shù)據(jù)壓縮:在 HTTP1.1 中,HTTP 請(qǐng)求和響應(yīng)都是由狀態(tài)行、請(qǐng)求/響應(yīng)頭部、消息主體三部分組成。一般而言,消息主體都會(huì)經(jīng)過(guò) gzip 壓縮,或者本身傳輸?shù)木褪菈嚎s過(guò)后的二進(jìn)制文件,但狀態(tài)行和頭部卻沒(méi)有經(jīng)過(guò)任何壓縮,直接以純文本傳輸。隨著 Web 功能越來(lái)越復(fù)雜,每個(gè)頁(yè)面產(chǎn)生的請(qǐng)求數(shù)也越來(lái)越多,導(dǎo)致消耗在頭部的流量越來(lái)越多,尤其是每次都要傳輸 UserAgent、Cookie 這類(lèi)不會(huì)頻繁變動(dòng)的內(nèi)容,完全是一種浪費(fèi)。HTTP1.1 不支持 header 數(shù)據(jù)的壓縮,HTTP2.0 使用 HPACK 算法對(duì) header 的數(shù)據(jù)進(jìn)行壓縮,這樣數(shù)據(jù)體積小了,在網(wǎng)絡(luò)上傳輸就會(huì)更快。
  3. 服務(wù)器推送:服務(wù)端推送是一種在客戶端請(qǐng)求之前發(fā)送數(shù)據(jù)的機(jī)制。網(wǎng)頁(yè)使用了許多資源:HTML、樣式表、腳本、圖片等等。在 HTTP1.1 中這些資源每一個(gè)都必須明確地請(qǐng)求。這是一個(gè)很慢的過(guò)程。瀏覽器從獲取 HTML 開(kāi)始,然后在它解析和評(píng)估頁(yè)面的時(shí)候,增量地獲取更多的資源。因?yàn)榉?wù)器必須等待瀏覽器做每一個(gè)請(qǐng)求,網(wǎng)絡(luò)經(jīng)常是空閑的和未充分使用的。為了改善延遲,HTTP2.0 引入了 server push,它允許服務(wù)端推送資源給瀏覽器,在瀏覽器明確地請(qǐng)求之前,免得客戶端再次創(chuàng)建連接發(fā)送請(qǐng)求到服務(wù)器端獲取。這樣客戶端可以直接從本地加載這些資源,不用再通過(guò)網(wǎng)絡(luò)。

HTTPS 協(xié)議

HTTPS(全稱:Hyper Text Transfer Protocol over Secure Socket Layer),是以安全為目標(biāo)的 HTTP通道,簡(jiǎn)單講是 HTTP 的安全版。HTTP 是應(yīng)用層協(xié)議,位于 HTTP 協(xié)議之下是傳輸協(xié)議 TCP。TCP 負(fù)責(zé)傳輸,HTTP 則定義了數(shù)據(jù)如何進(jìn)行包裝,在 HTTP 跟 TCP 中間多加了一層加密層TLS/SSL,SSL 是個(gè)加密套件,負(fù)責(zé)對(duì) HTTP 的數(shù)據(jù)進(jìn)行加密。TLS 是 SSL 的升級(jí)版。現(xiàn)在提到HTTPS,加密套件基本指的是 TLS。

傳輸加密的流程:Http 是應(yīng)用層將數(shù)據(jù)直接給到 TCP 進(jìn)行傳輸,Https 是應(yīng)用層將數(shù)據(jù)給到TLS/SSL,將數(shù)據(jù)加密后,再給到 TCP 進(jìn)行傳輸。HTTPS 是如何加密數(shù)據(jù)的:一般來(lái)說(shuō),加密分為對(duì)稱加密、非對(duì)稱加密

  1. 對(duì)稱加密:對(duì)稱加密的意思就是,加密數(shù)據(jù)用的密鑰,跟解密數(shù)據(jù)用的密鑰是一樣的。對(duì)稱加密的優(yōu)點(diǎn)在于加密、解密效率通常比較高。缺點(diǎn)在于,數(shù)據(jù)發(fā)送方、數(shù)據(jù)接收方需要協(xié)商,共享同一把密鑰,并確保密鑰不泄露給其他人。傳輸過(guò)程中容易被截獲。
  2. 非對(duì)稱加密:非對(duì)稱加密的意思就是,加密數(shù)據(jù)用的密鑰(公鑰),跟解密數(shù)據(jù)用的密鑰(私鑰)是不一樣的。網(wǎng)上一個(gè)很形象的例子:小服還是挺聰明的,得意了一會(huì)之后,小服意識(shí)到了密鑰會(huì)被截取這個(gè)問(wèn)題。倔強(qiáng)的小服又想到了另外一種方法:用非對(duì)稱加密的方法來(lái)加密數(shù)據(jù)。該方法是這樣的:小服和小客都擁有兩把鑰匙,一把鑰匙的公開(kāi)的(全世界都知道也沒(méi)關(guān)系),稱之為公鑰;而另一把鑰匙是保密(也就是只有自己才知道),稱之為私鑰。并且用公鑰加密的數(shù)據(jù),只有對(duì)應(yīng)的私鑰才能解密;用私鑰加密的數(shù)據(jù),只有對(duì)應(yīng)的公鑰才能解密。所以在傳輸數(shù)據(jù)的過(guò)程中,小服在給小客傳輸數(shù)據(jù)的過(guò)程中,會(huì)用小客給他的公鑰進(jìn)行加密,然后小客收到后,再用自己的私鑰進(jìn)行解密。小客給小服發(fā)消息的時(shí)候,也一樣會(huì)用小服給他的公鑰進(jìn)行加密,然后小服再用自己的私鑰進(jìn)行解密。這樣,數(shù)據(jù)就能安全著到達(dá)雙方。是什么原因?qū)е路菍?duì)稱加密這種方法的不安全性呢?它和對(duì)稱加密方法的不安全性不同。非對(duì)稱加密之所以不安全,是因?yàn)樾】褪盏搅斯€之后,無(wú)法確定這把公鑰是否真的是小服。解決的辦法就是數(shù)字證書(shū):小服再給小客發(fā)公鑰的過(guò)程中,會(huì)把公鑰以及小服的個(gè)人信息通過(guò) Hash 算法生成消息摘要,為了防止摘要被人調(diào)換,小服還會(huì)用 CA 提供的私鑰對(duì)消息摘要進(jìn)行加密來(lái)形成數(shù)字簽名,當(dāng)小客拿到這份數(shù)字證書(shū)之后,就會(huì)用 CA提供的公鑰來(lái)對(duì)數(shù)字證書(shū)里面的數(shù)字簽名進(jìn)行解密得到消息摘要,然后對(duì)數(shù)字證書(shū)里面小服的公鑰和個(gè)人信息進(jìn)行 Hash 得到另一份消息摘要,然后把兩份消息摘要進(jìn)行對(duì)比,如果一樣,則證明這些東西確實(shí)是小服的,否則就不是。

談?wù)勀銓?duì) WebSocket 的理解

首先,Websocket 是一個(gè)持久化的協(xié)議,相對(duì)于 HTTP 這種非持久的協(xié)議來(lái)說(shuō)。HTTP 的生命周期通過(guò) Request 來(lái)界定,也就是一個(gè) Request 一個(gè) Response,那么在 HTTP1.0 中,這次HTTP 請(qǐng)求就結(jié)束了。在 HTTP1.1 中進(jìn)行了改進(jìn),使得有一個(gè) keep-alive,也就是說(shuō),在一個(gè)HTTP 連接中,可以發(fā)送多個(gè) Request,接收多個(gè) Response。但是請(qǐng)記住 Request = Response,在 HTTP 中永遠(yuǎn)是這樣,也就是說(shuō)一個(gè) request 只能有一個(gè) response。而且這個(gè) response 也是被動(dòng)的,不能主動(dòng)發(fā)起。Websocket 是基于 HTTP 協(xié)議的,或者說(shuō)借用了 HTTP 的協(xié)議來(lái)完成一部分握手。但是 Websocket 只需要一次 HTTP 握手,所以說(shuō)整個(gè)通訊過(guò)程是建立在一次連接/狀態(tài)中,也就避免了 HTTP 的非狀態(tài)性,服務(wù)端會(huì)一直知道你的信息,直到你關(guān)閉請(qǐng)求

HTTP 的 Get 和 Post 的區(qū)別

HTTP 是應(yīng)用層的協(xié)議,底層基于 TCP/IP 協(xié)議,所以本質(zhì)上 Get 和 Post 請(qǐng)求都是 TCP 請(qǐng)求。所以二者的區(qū)別都是體現(xiàn)在應(yīng)用層上(HTTP 的規(guī)定和 C/S 的限制)

  1. 參數(shù)的傳輸方式:GET 參數(shù)通過(guò) URL 傳遞,POST 放在 Request body 中。
  2. Get 請(qǐng)求在 URL 中傳送的參數(shù)是有長(zhǎng)度限制的,而 POST 沒(méi)有。
  3. 對(duì)于 GET 方式的請(qǐng)求,瀏覽器會(huì)把 Http Header 和 data 一并發(fā)送出去,服務(wù)器響應(yīng) 200(返回?cái)?shù)據(jù));而對(duì)于 POST,瀏覽器先發(fā)送 Header,服務(wù)器響應(yīng) 100 continue,瀏覽器再發(fā)送 data,服務(wù)器響應(yīng) 200 ok(返回?cái)?shù)據(jù))。不過(guò)要注意,并不是所有瀏覽器都會(huì)在 POST 中發(fā)送兩次包,比如火狐
  4. 對(duì)參數(shù)的數(shù)據(jù)類(lèi)型,GET 只接受 ASCII 字符,而 POST 沒(méi)有限制。
  5. GET 比 POST 不安全,因?yàn)閰?shù)直接暴露在 URL 上,所以不能用來(lái)傳遞敏感信息。
  6. GET 請(qǐng)求只能進(jìn)行 URL 編碼,而 POST 支持多種編碼方式。
  7. GET 在瀏覽器回退時(shí)是無(wú)害的,而 POST 會(huì)再次提交請(qǐng)求。
  8. GET 產(chǎn)生的 URL 地址可以被 Bookmark,而 POST 不可以。
  9. GET 請(qǐng)求會(huì)被瀏覽器主動(dòng) cache,而 POST 不會(huì),除非手動(dòng)設(shè)置。

Socket 和 Http 的區(qū)別

HTTP 協(xié)議:簡(jiǎn)單的對(duì)象訪問(wèn)協(xié)議,對(duì)應(yīng)于應(yīng)用層。HTTP 協(xié)議是基于 TCP 連接的
TCP 協(xié)議:對(duì)應(yīng)于傳輸層
IP 協(xié)議:對(duì)應(yīng)與網(wǎng)絡(luò)層,TCP/IP 是傳輸層協(xié)議,主要解決數(shù)據(jù)如何在網(wǎng)絡(luò)中傳輸;而 Http是應(yīng)用層協(xié)議,主要解決如何包裝數(shù)據(jù)。
Socket 是對(duì) TCP/IP 協(xié)議的封裝,Socket 本身并不是協(xié)議,而是一個(gè)調(diào)用接口(API),通過(guò) Socket,我們才能使用 TCP/IP 協(xié)議。
Http 連接:Http 連接就是所謂的短連接,及客戶端向服務(wù)器發(fā)送一次請(qǐng)求,服務(wù)器端響應(yīng)后連接即會(huì)斷掉。Socket 連接:Socket 連接及是所謂的長(zhǎng)連接,理論上客戶端和服務(wù)端一旦建立連接,則不會(huì)主動(dòng)斷掉;但是由于各種環(huán)境因素可能會(huì)是連接斷開(kāi),比如說(shuō):服務(wù)器端或客戶端主機(jī) down 了,網(wǎng)絡(luò)故障或者兩者之間長(zhǎng)時(shí)間沒(méi)有數(shù)據(jù)傳輸,網(wǎng)絡(luò)防火墻可能會(huì)斷開(kāi)該連接已釋放網(wǎng)絡(luò)資源。所以當(dāng)一個(gè) Socket 連接中沒(méi)有數(shù)據(jù)的傳輸,那么為了維持連續(xù)的連接需要發(fā)送心跳消息,具體心跳消息格式是開(kāi)發(fā)者自己定義的。

描述一次網(wǎng)絡(luò)請(qǐng)求的流程

  1. 域名解析:瀏覽器會(huì)先搜索自身 DNS 緩存且對(duì)應(yīng)的 IP 地址沒(méi)有過(guò)期;若未找到則搜索操作系統(tǒng)自身的 DNS 緩存;若還未找到則讀本地的 hotsts 文件;還未找到會(huì)在 TCP/IP 設(shè)置的本地 DNS 服務(wù)器上找,如果要查詢的域名在本地配置的區(qū)域資源中,則完成解析;否則根據(jù)本地 DNS 服務(wù)器會(huì)請(qǐng)求根 DNS 服務(wù)器;根 DNS 服務(wù)器是 13 臺(tái)根 DNS,會(huì)一級(jí)一級(jí)往下找。
  2. TCP 三次握手:客戶端先發(fā)送 SYN=1,ACK=0,序列號(hào) seq=x 報(bào)文;(SYN 在連接建立時(shí)用來(lái)同步序號(hào),SYN=1,ACK=0 代表這是一個(gè)連接請(qǐng)求報(bào)文,對(duì)方若同意建立連接,則應(yīng)在響應(yīng)報(bào)文中使 SYN=1,ACK=1)服務(wù)器返回 SYN=1,ACK=1,seq=y,ack=x+1;客戶端再一次確認(rèn),但不用 SYN 了,回復(fù)服務(wù)端,ACK=1,seq=x+1, ack=y+1
  3. 建立 TCP 連接后發(fā)起 HTTP 請(qǐng)求:客戶端按照指定的格式開(kāi)始向服務(wù)端發(fā)送 HTTP 請(qǐng)求,HTTP 請(qǐng)求格式由四部分組成,分別是請(qǐng)求行、請(qǐng)求頭、空行、消息體,服務(wù)端接收到請(qǐng)求后,解析 HTTP 請(qǐng)求,處理完邏輯,最后返回一個(gè)具有標(biāo)準(zhǔn)格式的 HTTP 響應(yīng)給客戶端。
  4. 服務(wù)器響應(yīng) HTTP:請(qǐng)求服務(wù)器接收處理完請(qǐng)求后返回一個(gè) HTTP 響應(yīng)消息給客戶端,HTTP響應(yīng)信息格式包括:狀態(tài)行、響應(yīng)頭、空行、消息體
  5. 瀏覽器解析 HTML 代碼,請(qǐng)求 HTML 代碼中的資源:瀏覽器拿到 HTML 文件后,就開(kāi)始解析其中的 HTML 代碼,遇到 js/css/image 等靜態(tài)資源時(shí),向服務(wù)器發(fā)起一個(gè) HTTP 請(qǐng)求,如果返回 304 狀態(tài)碼,瀏覽器會(huì)直接讀取本地的緩存文件。否則開(kāi)啟線程向服務(wù)器請(qǐng)求下載。
  6. 瀏覽器對(duì)頁(yè)面進(jìn)行渲染并呈現(xiàn)給用戶
  7. TCP 的四次揮手:當(dāng)客戶端沒(méi)有東西要發(fā)送時(shí)就要釋放連接(提出中斷連接可以是 Client也可以是 Server),客戶端會(huì)發(fā)送一個(gè) FIN=1 的沒(méi)有數(shù)據(jù)的報(bào)文,進(jìn)入 FIN_WAIT 狀態(tài),服務(wù)端收到后會(huì)給客戶端一個(gè)確認(rèn),此時(shí)客戶端不能發(fā)送數(shù)據(jù),但可接收信息。

網(wǎng)絡(luò)分層

OSI 七層模型(OSI 七層協(xié)議模型)主要是:應(yīng)用層(Application)、表示層(Presentation)、
會(huì)話層(Session)、傳輸層(Transport)、網(wǎng)絡(luò)層(Network)、數(shù)據(jù)鏈路層(Data Link)、物
理層(Physical)
TCP/IP 五層模型(TCP/IP 五層模型):應(yīng)用層(Application)、傳輸層(Transport)、網(wǎng)絡(luò)層
(Network)、 數(shù)據(jù)鏈路層(Data Link)、物理層(Physical)

網(wǎng)絡(luò)請(qǐng)求緩存處理?OkHttp 如何處理網(wǎng)絡(luò)緩存?

1.網(wǎng)絡(luò)緩存優(yōu)先考慮強(qiáng)制緩存,再考慮對(duì)比緩存
--首先判斷強(qiáng)制緩存中的數(shù)據(jù)的是否在有效期內(nèi)。如果在有效期則直接使用緩存,如果過(guò)了有效期則進(jìn)入對(duì)比緩存
--在對(duì)比緩存過(guò)程中,判斷 ETag 是否有變動(dòng),如果服務(wù)端返回沒(méi)有變動(dòng),說(shuō)明資源未改變,使用緩存。如果有變動(dòng),判斷 Last-Modified
--判斷 Last-Modified,如果服務(wù)端對(duì)比資源的上次修改時(shí)間沒(méi)有變化,則使用緩存,否則重新請(qǐng)求服務(wù)端的數(shù)據(jù),并作緩存工作
2.Okhttp 緩存
開(kāi)啟使用 Okhttp 的緩存其實(shí)很簡(jiǎn)單,只需要給 OkHttpClient 對(duì)象設(shè)置一個(gè) Cache 對(duì)象即可,創(chuàng)建一個(gè) Cache 時(shí)指定緩存保存的目錄和緩存最大的大小即可
//新建一個(gè) cache,指定目錄為外部目錄下的 okhttp_cache 目錄,大小為 100M
Cache cache = new Cache(new File(Environment.getExternalStorageDirectory() +
"/okhttp_cache/"), 100 * 1024 * 1024);
//將 cache 設(shè)置到 OkHttpClient 中,這樣緩存就開(kāi)始生效了
OkHttpClient client = new OkHttpClient.Builder().cache(cache).build();
相關(guān)的類(lèi)有:
1.CacheControl(HTTP 中的 Cache-Control 和 Pragma 緩存控制):指定緩存規(guī)則
2.Cache(緩存類(lèi))
3.DiskLruCache(文件化的 LRU 緩存類(lèi))
1.讀取緩存:
先獲限 OkHttpClient 的 Cache 緩存對(duì)象,就是上面創(chuàng)建 OkHttpClient 設(shè)置的 Cahce; 傳 Request請(qǐng)求到 Cache 的 get 方法查找緩存響應(yīng)數(shù)據(jù) Response;構(gòu)造一個(gè)緩存策略,再調(diào)用它的 get()去 決 策 使 用 網(wǎng) 絡(luò) 請(qǐng) 求 還 是 緩 存 響 應(yīng) 。 若 使 用 緩 存 , 它 的 cacheResponse 不 為 空 ,networkRequest 為空,用緩存構(gòu)造響應(yīng)直接返回。若使用請(qǐng)求,則 cacheResponse 為空,networkRequest 不為空,開(kāi)始網(wǎng)絡(luò)請(qǐng)求流程。
Cache 的 get 獲取緩存方法:計(jì)算 request 的 key 值(請(qǐng)求 url 進(jìn)行 md5 加密),根據(jù) key 值去 DisLruCache 查找是否存在緩存內(nèi)容,存在則創(chuàng)建 Entry 實(shí)體。ENTRY_METADATA 代表響應(yīng)頭信息,ENTRY_BODY 代表響應(yīng)體信息。如果緩存存在,在指定目錄下會(huì)有兩個(gè)文件****.0*****.1 分別存儲(chǔ)某個(gè)請(qǐng)求緩存響應(yīng)頭和響應(yīng)體信息。CacheStrategy 的 get 方法:1)若緩存響應(yīng)為空 2)請(qǐng)求是 https 但緩存響應(yīng)沒(méi)有握手信息 3)
請(qǐng)求和緩存響應(yīng)都是不可緩存的 4)請(qǐng)求是 noCache,并且又包含 if-Modified-Since 或If-None-Match 則不使用緩存;再計(jì)算請(qǐng)求有效時(shí)間是否符合響應(yīng)的過(guò)期時(shí)間,若響應(yīng)在有效范圍內(nèi),則緩存策略使用緩存,否則創(chuàng)建一個(gè)新的有條件的請(qǐng)求,返回有條件的緩存策略。
2.存儲(chǔ)緩存流程:從 HttpEngine 的 readResponse()發(fā)送請(qǐng)求開(kāi)始,判斷 hasBody(userResponse),如果緩存的話,maybeCache()緩存響應(yīng)頭信息,unzip(cacheWritingResponse(storeRequest, userResponse))緩存響應(yīng)體。

談?wù)剬?duì) Volley 的理解

1、Volley 的特點(diǎn)
Volley 是谷歌大會(huì)上推出的網(wǎng)絡(luò)通信框架(2.3 之前使用 HttpClient,之后使用HttpUrlConnection),它既可以訪問(wèn)網(wǎng)絡(luò)獲取數(shù)據(jù),也可以加載圖片,并且在性能方面進(jìn)行了大幅度的調(diào)整,它的設(shè)計(jì)目的就是適合進(jìn)行數(shù)據(jù)量不大但通信頻繁的網(wǎng)絡(luò)操作,而對(duì)于大數(shù)據(jù)量的操作,比如文件下載,表現(xiàn)很糟糕,因?yàn)?Volley 處理 http 返回的默認(rèn)實(shí)現(xiàn)是BasicNetwork,它會(huì)把返回的流全部導(dǎo)入內(nèi)存中,下載大文件會(huì)發(fā)生內(nèi)存溢出
2、Volley 執(zhí)行的過(guò)程
默認(rèn)情況下,Volley 中開(kāi)啟四個(gè)網(wǎng)絡(luò)調(diào)度線程和一個(gè)緩存調(diào)度線程,首先請(qǐng)求會(huì)加入緩存隊(duì)列,緩存調(diào)度線程從緩存隊(duì)列中取出線程,如果找到該請(qǐng)求的緩存就直接讀取該緩存并解析,然后回調(diào)給主線程,如果沒(méi)有找到緩存的響應(yīng),則將這個(gè)請(qǐng)求加入網(wǎng)絡(luò)隊(duì)列,然后網(wǎng)絡(luò)調(diào)度線程會(huì)輪詢?nèi)〕鼍W(wǎng)絡(luò)隊(duì)列中的請(qǐng)求,發(fā)起 http 請(qǐng)求,解析響應(yīng)并將響應(yīng)存入緩存,回調(diào)給主線程
3、Volley 為什么不適合下載上傳大文件?為什么適合數(shù)據(jù)量小的頻率高的請(qǐng)求?1.Volley 基于請(qǐng)求隊(duì)列,Volley 的網(wǎng)絡(luò)請(qǐng)求線程池默認(rèn)大小為 4。意味著可以并發(fā)進(jìn)行 4個(gè)請(qǐng)求,大于 4 個(gè)會(huì)排在隊(duì)列中。并發(fā)量小所以適合數(shù)據(jù)量下頻率高的請(qǐng)求 2.因?yàn)?Volley 下載文件會(huì)將流存入內(nèi)存中(是一個(gè)小于 4k 的緩存池),大文件會(huì)導(dǎo)致內(nèi)存溢出,所以不能下載大文件,不能上傳大文件的原因和 1 中差不多,設(shè)想你上傳了四個(gè)大文件,同時(shí)占用了 Volley 的四個(gè)線程,導(dǎo)致其他網(wǎng)絡(luò)請(qǐng)求都阻塞在隊(duì)列中,造成反應(yīng)慢的現(xiàn)象

談?wù)剬?duì) OkHttp 的理解

1、OKHttp 的特點(diǎn)
1.相較于 Volley,它的最大并發(fā)量為 64
2.使用連接池技術(shù),支持 5 個(gè)并發(fā)的 socket 連接,默認(rèn) keepAlive 時(shí)間為 5 分鐘,解決TCP 握手和揮手的效率問(wèn)題,減少握手次數(shù)
3.支持 Gzip 壓縮,且操作對(duì)用戶透明,可以通過(guò) header 設(shè)置,在發(fā)起請(qǐng)求的時(shí)候自動(dòng)加入 header,Accept-Encoding: gzip,而我們的服務(wù)器返回的時(shí)候 header 中有Content-Encoding:gzip
4.利用響應(yīng)緩存來(lái)避免重復(fù)的網(wǎng)絡(luò)請(qǐng)求
5.很方便的添加攔截器,通常情況下,攔截器用來(lái)添加、移除、轉(zhuǎn)換請(qǐng)求和響應(yīng)的頭部信息,比如添加公參等
6.請(qǐng)求失敗,自動(dòng)重連,發(fā)生異常時(shí)重連,看源碼調(diào)用 recover 方法重連了一次
7.支持 SPDY 協(xié)議(SPDY 是 Google 開(kāi)發(fā)的基于 TCP 的應(yīng)用層協(xié)議,用以最小化網(wǎng)絡(luò)延遲,提升網(wǎng)絡(luò)速度,優(yōu)化用戶的網(wǎng)絡(luò)使用體驗(yàn)。SPDY 并不是一種用于替代 HTTP 的協(xié)議,而是對(duì)HTTP 協(xié)議的增強(qiáng)。新協(xié)議的功能包括數(shù)據(jù)流的多路復(fù)用、請(qǐng)求優(yōu)先級(jí)以及 HTTP 報(bào)頭壓縮。谷歌表示,引入 SPDY 協(xié)議后,在實(shí)驗(yàn)室測(cè)試中頁(yè)面加載速度比原先快 64%)
8.使用 Okio 來(lái)簡(jiǎn)化數(shù)據(jù)的訪問(wèn)與存儲(chǔ),提高性能
2、OkHttp 的缺點(diǎn)
1.消息回來(lái)需要切到主線程,主線程要自己去寫(xiě)。
2.調(diào)用比較復(fù)雜,需要自己進(jìn)行封裝。
3.緩存失效:網(wǎng)絡(luò)請(qǐng)求時(shí)一般都會(huì)獲取手機(jī)的一些硬件或網(wǎng)絡(luò)信息,比如使用的網(wǎng)絡(luò)環(huán)境。同時(shí)為了信息傳輸?shù)陌踩?,可能還會(huì)對(duì)請(qǐng)求進(jìn)行加密。在這些情況下 OkHttp 的緩存系統(tǒng)就會(huì)失效了,導(dǎo)致用戶在無(wú)網(wǎng)絡(luò)情況下不能訪問(wèn)緩存。
3、OkHttp 框架中都用到了哪些設(shè)計(jì)模式
1.Builder 設(shè)計(jì)模式,如構(gòu)建對(duì)象 OkHttpClient,還有單例模式
2.工廠方法模式,如源碼中的接口 Call
3.觀察者模式如 EventListener,監(jiān)聽(tīng)請(qǐng)求和響應(yīng)
4.策略模式
5.責(zé)任鏈模式,如攔截器

談?wù)剬?duì) Retrofit 的理解

Retrofit 底層是基于 OkHttp 實(shí)現(xiàn)的,與其他網(wǎng)絡(luò)框架不同的是,它更多使用運(yùn)行時(shí)注解的方式提供功能
1、原理
通過(guò) java 接口以及注解來(lái)描述網(wǎng)絡(luò)請(qǐng)求,并用動(dòng)態(tài)代理的方式生成網(wǎng)絡(luò)請(qǐng)求的 request,然后通過(guò) client 調(diào)用相應(yīng)的網(wǎng)絡(luò)框架(默認(rèn) okhttp)去發(fā)起網(wǎng)絡(luò)請(qǐng)求,并將返回的 response通過(guò) converterFactorty 轉(zhuǎn)換成相應(yīng)的數(shù)據(jù) model,最后通過(guò) calladapter 轉(zhuǎn)換成其他數(shù)據(jù)方式(如 Rxjava Observable)
2、Retrofit 流程
1.通過(guò)解析網(wǎng)絡(luò)請(qǐng)求接口的注解,配置網(wǎng)絡(luò)請(qǐng)求參數(shù)
2.通過(guò)動(dòng)態(tài)代理生成網(wǎng)絡(luò)請(qǐng)求對(duì)象
3.通過(guò)網(wǎng)絡(luò)請(qǐng)求適配器將網(wǎng)絡(luò)請(qǐng)求對(duì)象進(jìn)行平臺(tái)適配
4.通過(guò)網(wǎng)絡(luò)請(qǐng)求執(zhí)行器發(fā)送網(wǎng)絡(luò)請(qǐng)求
5.通過(guò)數(shù)據(jù)轉(zhuǎn)換器解析服務(wù)器返回的數(shù)據(jù)
6.通過(guò)回調(diào)執(zhí)行器切換線程(子線程 ->>主線程)
7.用戶在主線程處理返回結(jié)果
3、Retrofit 優(yōu)點(diǎn)
1.可以配置不同 HTTP Client 來(lái)實(shí)現(xiàn)網(wǎng)絡(luò)請(qǐng)求,如 Okhttp、HttpClient 等
2.請(qǐng)求的方法參數(shù)注解都可以定制
3.支持同步、異步和 RxJava
4.超級(jí)解耦
5.可以配置不同的反序列化工具來(lái)解析數(shù)據(jù),如 json、xml 等
6.框架使用了很多設(shè)計(jì)模式

HttpUrlConnection 和 OkHttp 的關(guān)系

Okhttp 中有 OkHttpUrlConnection 類(lèi),繼承自 HttpUrlConnection

AsyncTask+HttpClient 和 AsyncHttpClient 有什么區(qū)別

AsyncHttpClient 是異步的 HttpClient

HttpClient 和 HttpUrlConnection 的區(qū)別

首先 HttpClient 和 HttpUrlConnection 這兩種方式都支持 Https 協(xié)議,都是以流的形式進(jìn)行上傳或者下載數(shù)據(jù),也可以說(shuō)是以流的形式進(jìn)行數(shù)據(jù)的傳輸,還有 ipv6,以及連接池等功能。HttpClient 這個(gè)擁有非常多的 API,所以如果想要進(jìn)行擴(kuò)展的話,并且不破壞它的兼容性的話,很難進(jìn)行擴(kuò)展,也就是這個(gè)原因,Google 在 Android6.0 的時(shí)候,直接就棄用了這個(gè)HttpClient。而 HttpUrlConnection 相對(duì)來(lái)說(shuō)就是比較輕量級(jí)了,API 比較少,容易擴(kuò)展,并且能夠滿足 Android 大部分的數(shù)據(jù)傳輸。比較經(jīng)典的一個(gè)框架 Volley,在 2.3 版本以前都是使用 HttpClient,在 2.3 以后就使用了 HttpUrlConnection

Xutils、Volley、OkHttp、Retrofit 對(duì)比

Xutils:這個(gè)框架非常全面,可以進(jìn)行網(wǎng)絡(luò)請(qǐng)求,可以進(jìn)行圖片加載處理,可以數(shù)據(jù)儲(chǔ)存,還可以對(duì) view 進(jìn)行注解,使用這個(gè)框架非常方便,但是缺點(diǎn)也是非常明顯的,使用這個(gè)項(xiàng)目,會(huì)導(dǎo)致項(xiàng)目對(duì)這個(gè)框架依賴非常的嚴(yán)重,一旦這個(gè)框架出現(xiàn)問(wèn)題,那么對(duì)項(xiàng)目來(lái)說(shuō)影響非常大的。

Volley:Volley 是 Google 官方出的一套小而巧的異步請(qǐng)求庫(kù),該框架封裝的擴(kuò)展性很強(qiáng),支持 HttpClient、HttpUrlConnection,甚至支持 OkHttp,而且 Volley 里面也封裝了 ImageLoader,所以如果你愿意你甚至不需要使用圖片加載框架,不過(guò)這塊功能沒(méi)有一些專(zhuān)門(mén)的圖片加載框架強(qiáng)大,對(duì)于簡(jiǎn)單的需求可以使用,稍復(fù)雜點(diǎn)的需求還是需要用到專(zhuān)門(mén)的圖片加載框架。Volley 也有缺陷,比如不支持 post 大數(shù)據(jù),所以不適合上傳文件。不過(guò) Volley 設(shè)計(jì)的初衷本身也就是為頻繁的、數(shù)據(jù)量小的網(wǎng)絡(luò)請(qǐng)求而生。

OKhttp:Android 開(kāi)發(fā)中是可以直接使用現(xiàn)成的 api 進(jìn)行網(wǎng)絡(luò)請(qǐng)求的。就是使用 HttpClient、HttpUrlConnection 進(jìn)行操作。Okhttp 針對(duì) Java 和 Android 程序,封裝的一個(gè)高性能的 http請(qǐng)求庫(kù),支持同步、異步,而且 Okhttp 又封裝了線程池,封裝了數(shù)據(jù)轉(zhuǎn)換,封裝了參數(shù)的使用,錯(cuò)誤處理等。API 使用起來(lái)更加的方便。但是我們?cè)陧?xiàng)目中使用的時(shí)候仍然需要自己在做一層封裝,這樣才能使用的更加的順手。

Retrofit:Retrofit 是 Square 公司出品的默認(rèn)基于 OkHttp 封裝的一套 RESTful 網(wǎng)絡(luò)請(qǐng)求框架,RESTful 是目前流行的一套 api 設(shè)計(jì)的風(fēng)格,并不是標(biāo)準(zhǔn)。Retrofit 的封裝可以說(shuō)是很強(qiáng)大,里面涉及到一堆的設(shè)計(jì)模式,可以通過(guò)注解直接配置請(qǐng)求,可以使用不同的 http 客戶端,雖然默認(rèn)是用 http,可以使用不同 Json Converter 來(lái)序列化數(shù)據(jù),同時(shí)提供對(duì) RxJava 的支持,使用 Retrofit + OkHttp + RxJava + Dagger2 可以說(shuō)是目前比較潮的一套框架,但是需要有比較高的門(mén)檻。

Volley VS OkHttp
Volley 的優(yōu)勢(shì)在于封裝的更好,而使用 OkHttp 你需要有足夠的能力再進(jìn)行一次封裝。而OkHttp 的優(yōu)勢(shì)在于性能更高,因?yàn)?OkHttp 基于 NIO 和 Okio,所以性能上要比 Volley 更快。IO 和 NIO 這兩個(gè)都是 Java 中的概念,如果我從硬盤(pán)讀取數(shù)據(jù),第一種方式就是程序一直等,數(shù)據(jù)讀完后才能繼續(xù)操作這種是最簡(jiǎn)單的也叫阻塞式 IO,還有一種是你讀你的, 程序接著往下執(zhí)行,等數(shù)據(jù)處理完你再來(lái)通知我,然后再處理回調(diào)。而第二種就是 NIO 的方式,非阻塞式,所以 NIO 當(dāng)然要比 IO 的性能要好了,而 Okio 是 Square 公司基于 IO 和 NIO 基礎(chǔ)上做的一個(gè)更簡(jiǎn)單、高效處理數(shù)據(jù)流的一個(gè)庫(kù)。理論上如果 Volley 和 OkHttp 對(duì)比的話,更傾向于使用 Volley,因?yàn)?Volley 內(nèi)部同樣支持使用 OkHttp,這點(diǎn) OkHttp 的性能優(yōu)勢(shì)就沒(méi)了,而且 Volley 本身封裝的也更易用,擴(kuò)展性更好些。

OkHttp VS Retrofit
毫無(wú)疑問(wèn),Retrofit 默認(rèn)是基于 OkHttp 而做的封裝,這點(diǎn)來(lái)說(shuō)沒(méi)有可比性,肯定首選 Retrofit。

Volley VS Retrofit
這兩個(gè)庫(kù)都做了不錯(cuò)的封裝,但 Retrofit 解耦的更徹底,尤其 Retrofit2.0 出來(lái),Jake 對(duì)之前1.0 設(shè)計(jì)不合理的地方做了大量重構(gòu),職責(zé)更細(xì)分,而且 Retrofit 默認(rèn)使用 OkHttp,性能上也要比 Volley 占優(yōu)勢(shì),再有如果你的項(xiàng)目如果采用了 RxJava,那更該使用 Retrofit。所以這兩個(gè)庫(kù)相比,Retrofit 更有優(yōu)勢(shì),在能掌握兩個(gè)框架的前提下該優(yōu)先使用 Retrofit。但是 Retrofit門(mén)檻要比 Volley 稍高些,要理解他的原理,各種用法,想徹底搞明白還是需要花些功夫的,如果你對(duì)它一知半解,那還是建議在商業(yè)項(xiàng)目使用 Volley 吧。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容