<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          HTTP協(xié)議以及基于UDP實(shí)現(xiàn)可靠的協(xié)議QUIC

          共 3590字,需瀏覽 8分鐘

           ·

          2021-09-02 09:59


          • 前言

          • HTTP協(xié)議

            • 請(qǐng)求準(zhǔn)備:

            • 請(qǐng)求構(gòu)建:

            • 請(qǐng)求的發(fā)送:

            • HTTP返回的構(gòu)建:

          • 如何實(shí)現(xiàn)一個(gè)靠譜的協(xié)議?

          • QUIC協(xié)議

            • 自定義連接機(jī)制:

            • 自定義重傳機(jī)制:

            • 無(wú)阻塞的多路復(fù)用:

            • 自定義流量控制:

          • 往期推薦:


          前言

          有三個(gè)月沒(méi)更筆記文了,似乎忘了這是一個(gè)技術(shù)類公眾號(hào)。

          在這段時(shí)間內(nèi)花了兩個(gè)月重學(xué)了一遍數(shù)據(jù)結(jié)構(gòu),然后在leetcode上刷了一百多道題。

          還看了一本《現(xiàn)代操作系統(tǒng)》,看的有點(diǎn)懵,又花錢買了一個(gè)大牛專欄看

          后續(xù)將這些筆記都整理一下,發(fā)到這個(gè)公眾號(hào)。

          還花了一周空閑時(shí)間用python寫(xiě)了一個(gè)小程序,每天定時(shí)獲取熱點(diǎn)信息、自動(dòng)編排、上傳、發(fā)布文章。熱點(diǎn)在文章中支持點(diǎn)擊跳轉(zhuǎn)。

          之前寫(xiě)的網(wǎng)絡(luò)協(xié)議其實(shí)只寫(xiě)了一小部分,后面還包括了HTTP協(xié)議、HTTPS協(xié)議、DNS、CDN、網(wǎng)絡(luò)模式以及容器網(wǎng)絡(luò)等。

          那么今天就來(lái)記錄一下HTTP協(xié)議相關(guān)內(nèi)容。

          HTTP協(xié)議

          瀏覽器上輸入url,比如http://www.xxx.com,這個(gè)叫做統(tǒng)一資源定位符

          其中www.xxx.com是一個(gè)域名,表示互聯(lián)網(wǎng)的一個(gè)位置。

          請(qǐng)求準(zhǔn)備:

          瀏覽器會(huì)將域名發(fā)送給DNS服務(wù)器,解析成IP地址。

          HTTP是基于TCP協(xié)議的,先要建立TCP連接。

          目前使用的HTTP協(xié)議大部分都是1.1,在1.1的協(xié)議里面,默認(rèn)開(kāi)啟了Keep-Alive的,這樣建立的TCP連接,可以在多次請(qǐng)求中復(fù)用。

          請(qǐng)求構(gòu)建:

          HTTP報(bào)文分為三大部分,分別是請(qǐng)求行,首部和請(qǐng)求的正文實(shí)體

          請(qǐng)求行

          URL就是http://www.xxx.com

          版本就是HTTP1.1

          方法有GET、POST、PUT、DELETE

          首部字段

          首部是Key-Value格式,通過(guò)冒號(hào)分隔,保存一些header信息

          例如:Accept-Charset,表示客戶端可接受的字符集。

          Content-Type指的是正文的格式,例如是JSON

          Cache-control 用來(lái)控制緩存

          請(qǐng)求的發(fā)送:

          HTTP 協(xié)議是基于 TCP 協(xié)議的,所以它使用面向連接的方式發(fā)送請(qǐng)求。

          到了 TCP 層,它會(huì)轉(zhuǎn)換成一個(gè)個(gè)報(bào)文段發(fā)送給服務(wù)器。

          在發(fā)送給每個(gè)報(bào)文段的時(shí)候,都需要對(duì)方有一個(gè)回應(yīng) ACK,來(lái)保證報(bào)文可靠地到達(dá)了對(duì)方。

          如果沒(méi)有回應(yīng),那么 TCP 這一層會(huì)進(jìn)行重傳,直到可以到達(dá)。

          TCP 層發(fā)送每一個(gè)報(bào)文的時(shí)候,都需要加上自己的地址(即源地址)和它想要去的地方(即目標(biāo)地址),將這兩個(gè)信息放到 IP 頭里面,交給 IP 層進(jìn)行傳輸。

          IP 層需要查看目標(biāo)地址和自己是否是在同一個(gè)局域網(wǎng)。如果是,就發(fā)送 ARP 協(xié)議來(lái)請(qǐng)求這個(gè)目標(biāo)地址對(duì)應(yīng)的 MAC 地址,然后將源 MAC 和目標(biāo) MAC 放入 MAC 頭,發(fā)送出去即可;

          如果不在同一個(gè)局域網(wǎng),就需要發(fā)送到網(wǎng)關(guān),還要需要發(fā)送 ARP 協(xié)議,來(lái)獲取網(wǎng)關(guān)的 MAC 地址,然后將源 MAC 和網(wǎng)關(guān) MAC 放入 MAC 頭,發(fā)送出去。

          網(wǎng)關(guān)收到包發(fā)現(xiàn) MAC 符合,取出目標(biāo) IP 地址,根據(jù)路由協(xié)議找到下一跳的路由器,獲取下一跳路由器的 MAC 地址,將包發(fā)給下一跳路由器。

          這樣路由器一跳一跳終于到達(dá)目標(biāo)的局域網(wǎng)。

          這個(gè)時(shí)候,最后一跳的路由器能夠發(fā)現(xiàn),目標(biāo)地址就在自己的某一個(gè)出口的局域網(wǎng)上。于是,在這個(gè)局域網(wǎng)上發(fā)送 ARP,獲得這個(gè)目標(biāo)地址的 MAC 地址,將包發(fā)出去。

          目標(biāo)的機(jī)器發(fā)現(xiàn) MAC 地址符合,就將包收起來(lái);發(fā)現(xiàn) IP 地址符合,根據(jù) IP 頭中協(xié)議項(xiàng),知道上一層是 TCP 協(xié)議,于是解析 TCP 的頭,里面有序列號(hào),需要看一看這個(gè)序列包是不是我要的,如果是就放入緩存中然后返回一個(gè) ACK,如果不是就丟棄。

          TCP 頭里面還有端口號(hào),HTTP 的服務(wù)器正在監(jiān)聽(tīng)這個(gè)端口號(hào)。于是,目標(biāo)機(jī)器自然知道是 HTTP 服務(wù)器這個(gè)進(jìn)程想要這個(gè)包,于是將包發(fā)給 HTTP 服務(wù)器。HTTP 服務(wù)器的進(jìn)程看到,原來(lái)這個(gè)請(qǐng)求是要訪問(wèn)一個(gè)網(wǎng)頁(yè),于是就把這個(gè)網(wǎng)頁(yè)發(fā)給客戶端。

          HTTP返回的構(gòu)建:

          狀態(tài)碼有幾種,1xx、2xx、3xx、4xx、5xx

          首部中,Retry-After 表示,告訴客戶端應(yīng)該在多長(zhǎng)時(shí)間以后再次嘗試一下。

          Content-Type,表示返回的是 HTML,還是 JSON。

          構(gòu)造好了返回的 HTTP 報(bào)文,接下來(lái)就是把這個(gè)報(bào)文發(fā)送出去。還是交給 Socket 去發(fā)送,還是交給 TCP 層,讓 TCP 層將返回的 HTML,也分成一個(gè)個(gè)小的段,并且保證每個(gè)段都可靠到達(dá)。

          這些段加上 TCP 頭后會(huì)交給 IP 層,然后把剛才的發(fā)送過(guò)程反向走一遍。雖然兩次不一定走相同的路徑,但是邏輯過(guò)程是一樣的,一直到達(dá)客戶端。

          客戶端發(fā)現(xiàn) MAC 地址符合、IP 地址符合,于是就會(huì)交給 TCP 層。根據(jù)序列號(hào)看是不是自己要的報(bào)文段,如果是,則會(huì)根據(jù) TCP 頭中的端口號(hào),發(fā)給相應(yīng)的進(jìn)程。這個(gè)進(jìn)程就是瀏覽器,瀏覽器作為客戶端也在監(jiān)聽(tīng)某個(gè)端口。

          當(dāng)瀏覽器拿到了 HTTP 的報(bào)文。發(fā)現(xiàn)返回“200”,一切正常,于是就從正文中將 HTML 拿出來(lái)。HTML 是一個(gè)標(biāo)準(zhǔn)的網(wǎng)頁(yè)格式。瀏覽器只要根據(jù)這個(gè)格式,渲染網(wǎng)頁(yè)。

          這就是一個(gè)正常的 HTTP 請(qǐng)求和返回的完整過(guò)程。

          如何實(shí)現(xiàn)一個(gè)靠譜的協(xié)議?

          為了保證順序性,每一個(gè)包都有一個(gè)ID,在建立連接的時(shí)候,會(huì)商定起始的ID是什么,然后按照ID一個(gè)個(gè)發(fā)送,為了保證不丟包,對(duì)于發(fā)送的包都要進(jìn)行應(yīng)答,但這個(gè)應(yīng)答也不是一個(gè)一個(gè)來(lái),而是會(huì)應(yīng)答某個(gè)之前的ID,表示都收到了,這種模式稱為累計(jì)確認(rèn)或者累計(jì)應(yīng)答

          QUIC協(xié)議

          QUIC協(xié)議,是Google內(nèi)部的一個(gè)基于UDP的可靠傳輸協(xié)議。

          自定義連接機(jī)制:

          TCP由一個(gè)四元組確認(rèn)一個(gè)連接,發(fā)生變化就得重連。移動(dòng)互聯(lián)網(wǎng)下,網(wǎng)絡(luò)不穩(wěn)定會(huì)再次重連,導(dǎo)致時(shí)延。

          基于UDP,不再以四元組為標(biāo)識(shí),而是以一個(gè)64位的隨機(jī)數(shù)作為ID來(lái)標(biāo)識(shí),而且UDP是無(wú)連接的,所以當(dāng)IP或者端口變化的時(shí)候,只要ID不變,就不需要重新建立連接。

          自定義重傳機(jī)制:

          TCP超時(shí)重傳是通過(guò)自適應(yīng)重傳算法,通過(guò)采用往返時(shí)間RTT不斷調(diào)整。

          QUIC 也有個(gè)序列號(hào),是遞增的。任何一個(gè)序列號(hào)的包只發(fā)送一次,下次就要加一了。

          例如,發(fā)送一個(gè)包,序號(hào)是 100,發(fā)現(xiàn)沒(méi)有返回;再次發(fā)送的時(shí)候,序號(hào)就是 101 了;如果返回的 ACK 100,就是對(duì)第一個(gè)包的響應(yīng)。如果返回 ACK 101 就是對(duì)第二個(gè)包的響應(yīng),RTT 計(jì)算相對(duì)準(zhǔn)確。

          QUIC 定義了一個(gè) offset 概念。QUIC 既然是面向連接的,也就像 TCP 一樣,是一個(gè)數(shù)據(jù)流,發(fā)送的數(shù)據(jù)在這個(gè)數(shù)據(jù)流里面有個(gè)偏移量 offset,可以通過(guò) offset 查看數(shù)據(jù)發(fā)送到了哪里,這樣只要這個(gè) offset 的包沒(méi)有來(lái),就要重發(fā);如果來(lái)了,按照 offset 拼接,還是能夠拼成一個(gè)流。

          無(wú)阻塞的多路復(fù)用:

          同一條 QUIC 連接上可以創(chuàng)建多個(gè) stream,來(lái)發(fā)送多個(gè) HTTP 請(qǐng)求。但是,QUIC 是基于 UDP 的,一個(gè)連接上的多個(gè) stream 之間沒(méi)有依賴。這樣,假如 stream2 丟了一個(gè) UDP 包,后面跟著 stream3 的一個(gè) UDP 包,雖然 stream2 的那個(gè)包需要重傳,但是 stream3 的包無(wú)需等待,就可以發(fā)給用戶。

          自定義流量控制:

          TCP 的流量控制是通過(guò)滑動(dòng)窗口協(xié)議。QUIC 的流量控制也是通過(guò) window_update,來(lái)告訴對(duì)端它可以接受的字節(jié)數(shù)。但是 QUIC 的窗口是適應(yīng)自己的多路復(fù)用機(jī)制的,不但在一個(gè)連接上控制窗口,還在一個(gè)連接中的每個(gè) stream 控制窗口。

          在 TCP 協(xié)議中,接收端的窗口的起始點(diǎn)是下一個(gè)要接收并且 ACK 的包,即便后來(lái)的包都到了,放在緩存里面,窗口也不能右移,因?yàn)?TCP 的 ACK 機(jī)制是基于序列號(hào)的累計(jì)應(yīng)答,一旦 ACK 了一個(gè)序列號(hào),就說(shuō)明前面的都到了,所以只要前面的沒(méi)到,后面的到了也不能 ACK,就會(huì)導(dǎo)致后面的到了,也有可能超時(shí)重傳,浪費(fèi)帶寬。

          QUIC 的 ACK 是基于 offset 的,每個(gè) offset 的包來(lái)了,進(jìn)了緩存,就可以應(yīng)答,應(yīng)答后就不會(huì)重發(fā),中間的空檔會(huì)等待到來(lái)或者重發(fā)即可,而窗口的起始位置為當(dāng)前收到的最大 offset,從這個(gè) offset 到當(dāng)前的 stream 所能容納的最大緩存,是真正的窗口大小。顯然,這樣更加準(zhǔn)確。

          往期推薦:

          TCP為什么可靠?

          詳解tcp三次握手四次揮手

          DNS域名解析系統(tǒng)

          廣播與多播

          UDP是什么東西???

          路由協(xié)議

          網(wǎng)關(guān)和路由

          星巴克氣氛組電腦是如何獲取IP的

          瀏覽器發(fā)起HTTP請(qǐng)求后經(jīng)歷了什么?

          推薦一個(gè)生產(chǎn)環(huán)境問(wèn)題排查利器

          MySQL系列文章

          k8s全系列文章匯總


          瀏覽 153
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  黄色动漫在线免费观看 | 天天干天天想天天日天天日 天天 | 青青草原亚洲 | 亚洲精品国产AV | 操色逼免费 |