1. 程式人生 > 其它 >趣談網路協議

趣談網路協議

趣談網路協議

學習曲線:

  1. 2021年11月30日16:42:07,學習了(0-4),一個小時整,共計五節課,沒興趣了。

  2. 2021年12月1日11:00:15,開始,2021年12月1日12:03:38結束,學習了5章節,共計學習一個小時整

  3. 2021年12月1日17:51:48,結束,學習了8個章節,共計學習;三個小時整

  4. 2021年12月3日15:20:46,開始,學習了4個章節,共計學習:一個小時整

  5. 2021年12月10日11:22:22,開始,學習結束


想成為技術牛人?先搞定網路協議!

為什麼網路協議這麼重要呢?為什麼“計算機組成與系統結構”“資料結構與演算法”“作業系統”“計算機網路”“編譯原理”,會成為大學計算機的核心課程呢?至少看起來,這些內容沒有“多少天搞定MFC、Structs”這樣的內容更容易幫你找到工作。

隨著見過的世面越來越多,我漸漸發現,無論是對於大規模系統的架構,還是對於程式設計師的個人職業生涯,網路和網路協議都是繞不過去的坎兒。 叢集規模一大,我們首先想到的就是網路互通的問題;應用吞吐量壓不上去,我們首先想到的也是網路互通的問題。 不客氣地講,很多情況下,只要搞定了網路,一個大型系統也就搞定了一半。所以,要成為技術牛人,搞定大系統,一定要過網路這一關,而網路協議在網路中佔有舉足輕重的地位。

相信大部分人都思考過“技術變化太快,容易過時”的問題。畢竟,技術浪潮一浪接一浪,新技術層出不窮。從搜尋引擎、大資料、雲端計算,到人工智慧、區塊鏈,簡直就是“你方唱罷我登場”。這裡面究竟有沒有最本質的東西,使得你掌握了它,就能在新技術的滾滾浪潮中,保持快速學習的能力?

通過對大量開源技術的程式碼進行分析,我發現很多技術看起來轟轟烈烈,扒下外衣,本質的東西其實就是基礎知識和核心概念。想要不被滾滾而來的新技術淘汰,就要掌握這些可以長久使用的知識,而網路協議就是值得你學習,而且是到40歲之後依然有價值的知識。

一看覺得懂,一問就打鼓,一用就糊塗

  • 網路協議知識點太多,學完記不住。

  • 看上去懂了,但是經不住問。

  • 知識學會了,實際應用依舊不會

千里之行,始於足下。不管何時,我相信,紮實的功底和過硬的技術,都會是你職業發展的助力器。

希望不僅可以幫你理清繁雜的網路協議概念,幫你構建一個精準的網路協議知識框架,幫你在熱門領域應用這些底層知識,更重要的是給你一種學習知識的方法和態度:看似最枯燥、最基礎的東西往往具有最長久的生命力。

為什麼要學習網路協議?

《聖經》中有一個通天塔的故事,大致是說,上帝為了阻止人類聯合起來,就讓人類說不同的語言。人類沒法兒溝通,達不成“協議”,通天塔的計劃就失敗了。但是千年以後,有一種叫“程式猿”的物種,敲著一種這個群體通用的語言,連線著全世界所有的人,打造這網際網路世界的通天塔。如今的世界,正是因為網際網路,才連線在一起。

協議三要素

當然,這種協議還是更接近人類語言,機器不能直接讀懂,需要進行翻譯,翻譯的工作教給編譯器,也就是程式設計師常說的compile。這個過程比較複雜,其中的編譯原理非常複雜,我在這裡不進行詳述。

  • 語法,就是這一段內容要符合一定的規則和格式。例如,括號要成對,結束要使用分號等。

  • 語義,就是這一段內容要代表某種意義。例如數字減去數字是有意義的,數字減去文字一般來說就沒有意義。

  • 順序,就是先幹啥,後幹啥。例如,可以先加上某個數值,然後再減去某個數值。

會了計算機語言,你就能夠教給一臺計算機完成你的工作了。恭喜你,入門了!

但是,要想打造網際網路世界的通天塔,只教給一臺機器做什麼是不夠的,你需要學會教給一大片機器做什麼。這就需要網路協議。只有通過網路協議,才能使一大片機器互相協作、共同完成一件事。

雙11 簡簡單單的下單過程涉及的協議?

DNS、HTTP、HTTPS所在的層我們稱為應用層。經過應用層封裝後,瀏覽器會將應用層的包交給下一層去完成,通過socket程式設計來實現。下一層是傳輸層。傳輸層有兩種協議,一種是無連線的協議UDP,一種是面向連線的協議TCP。對於支付來講,往往使用TCP協議。所謂的面向連線就是,TCP會保證這個包能夠到達目的地。如果不能到達,就會重新發送,直至到達。

TCP協議裡面會有兩個埠,一個是瀏覽器監聽的埠,一個是電商的伺服器監聽的埠。作業系統往往通過埠來判斷,它得到的包應該給哪個程序。

傳輸層封裝完畢後,瀏覽器會將包交給作業系統的網路層。網路層的協議是IP協議。在IP協議裡面會有源IP地址,即瀏覽器所在機器的IP地址和目標IP地址,也即電商網站所在伺服器的IP地址。

作業系統既然知道了目標IP地址,就開始想如何根據這個門牌號找到目標機器。作業系統往往會判斷,這個目標IP地址是本地人,還是外地人。如果是本地人,從門牌號就能看出來,但是顯然電商網站不在本地,而在遙遠的地方。

作業系統知道要離開本地去遠方。雖然不知道遠方在何處,但是可以這樣類比一下:如果去國外要去海關,去外地就要去閘道器。而作業系統啟動的時候,就會被DHCP協議配置IP地址,以及預設的閘道器的IP地址192.168.1.1。

作業系統如何將IP地址發給閘道器呢?在本地通訊基本靠吼,於是作業系統大吼一聲,誰是192.168.1.1啊?閘道器會回答它,我就是,我的本地地址在村東頭。這個本地地址就是MAC地址,而大吼的那一聲是ARP協議。

於是作業系統將IP包交給了下一層,也就是MAC層。網絡卡再將包發出去。由於這個包裡面是有MAC地址的,因而它能夠到達閘道器。

閘道器收到包之後,會根據自己的知識,判斷下一步應該怎麼走。閘道器往往是一個路由器,到某個IP地址應該怎麼走,這個叫作路由表。

路由器有點像玄奘西行路過的一個個國家的一個個城關。每個城關都連著兩個國家,每個國家相當於一個區域網,在每個國家內部,都可以使用本地的地址MAC進行通訊。

一旦跨越城關,就需要拿出IP頭來,裡面寫著貧僧來自東土大唐(就是源IP地址),欲往西天拜佛求經(指的是目標IP地址)。路過寶地,借宿一晚,明日啟程,請問接下來該怎麼走啊?

城關往往是知道這些“知識”的,因為城關和臨近的城關也會經常溝通。到哪裡應該怎麼走,這種溝通的協議稱為路由協議,常用的有OSPFBGP

城關與城關之間是一個國家,當網路包知道了下一步去哪個城關,還是要使用國家內部的MAC地址,通過下一個城關的MAC地址,找到下一個城關,然後再問下一步的路怎麼走,一直到走出最後一個城關。

最後一個城關知道這個網路包要去的地方。於是,對著這個國家吼一聲,誰是目標IP啊?目標伺服器就會回覆一個MAC地址。網路包過關後,通過這個MAC地址就能找到目標伺服器。

目標伺服器發現MAC地址對上了,取下MAC頭來,傳送給作業系統的網路層。發現IP也對上了,就取下IP頭。IP頭裡會寫上一層封裝的是TCP協議,然後將其交給傳輸層,即TCP層

在這一層裡,對於收到的每個包,都會有一個回覆的包說明收到了。這個回覆的包絕非這次下單請求的結果,例如購物是否成功,扣了多少錢等,而僅僅是TCP層的一個說明,即收到之後的回覆。當然這個回覆,會沿著剛才來的方向走回去,報個平安。

因為一旦出了國門,西行路上千難萬險,如果在這個過程中,網路包走丟了,例如進了大沙漠,或者被強盜搶劫殺害怎麼辦呢?因而到了要報個平安。

如果過一段時間還是沒到,傳送端的TCP層會重新發送這個包,還是上面的過程,直到有一天收到平安到達的回覆。這個重試絕非你的瀏覽器重新將下單這個動作重新請求一次。對於瀏覽器來講,就傳送了一次下單請求,TCP層不斷自己悶頭重試。除非TCP這一層出了問題,例如連線斷了,才輪到瀏覽器的應用層重新發送下單請求。

當網路包平安到達TCP層之後,TCP頭中有目標埠號,通過這個埠號,可以找到電商網站的程序正在監聽這個埠號,假設一個Tomcat,將這個包發給電商網站。

電商網站的程序得到HTTP請求的內容,知道了要買東西,買多少。往往一個電商網站最初接待請求的這個Tomcat只是個接待員,負責統籌處理這個請求,而不是所有的事情都自己做。例如,這個接待員要告訴專門管理訂單的程序,登記要買某個商品,買多少,要告訴管理庫存的程序,庫存要減少多少,要告訴支付的程序,應該付多少錢,等等。

如何告訴相關的程序呢?往往通過RPC呼叫,即遠端過程呼叫的方式來實現。遠端過程呼叫就是當告訴管理訂單程序的時候,接待員不用關心中間的網路互連問題,會由RPC框架統一處理。RPC框架有很多種,有基於HTTP協議放在HTTP的報文裡面的,有直接封裝在TCP報文裡面的。

當接待員發現相應的部門都處理完畢,就回復一個HTTPS的包,告知下單成功。這個HTTPS的包,會像來的時候一樣,經過千難萬險到達你的個人電腦,最終進入瀏覽器,顯示支付成功。

當網路包到達一個城關的時候,可以通過路由表得到下一個城關的IP地址,直接通過IP地址找就可以了,為什麼還要通過本地的MAC地址呢?

網路分層的真實含義是什麼?

長時間從事計算機網路相關的工作,我發現,計算機網路有一個顯著的特點,就是這是一個不僅需要背誦,而且特別需要將原理爛熟於胸的學科。很多問題看起來懂了,但是就怕往細裡問,一問就發現你懂得沒有那麼透徹。

我們上一節列了之後要講的網路協議。這些協議本來沒什麼稀奇,每一本教科書都會講,並且都要求你背下來。因為考試會考,面試會問。可以這麼說,畢業了去找工作還答不出這類題目的,那你的筆試基本上也就掛了。

當你聽到什麼二層裝置、三層裝置、四層LB和七層LB中層的時候,是否有點一頭霧水,不知道這些所謂的層,對應的各種協議具體要做什麼“工作”?

從你的電腦,通過SSH登入到公有云主機裡面,都需要經歷哪些過程?或者說你開啟一個電商網站,都需要經歷哪些過程?說得越詳細越好。

網路為什麼要分層?

複雜的程式都要分層,這是程式設計的要求。

這裡我們先探討第一個問題,網路為什麼要分層?因為,是個複雜的程式都要分層。

理解計算機網路中的概念,一個很好的角度是,想象網路包就是一段Buffer,或者一塊記憶體,是有格式的。同時,想象自己是一個處理網路包的程式,而且這個程式可以跑在電腦上,可以跑在伺服器上,可以跑在交換機上,也可以跑在路由器上。你想象自己有很多的網口,從某個口拿進一個網路包來,用自己的程式處理一下,再從另一個網口傳送出去。

當然網路包的格式很複雜,這個程式也很複雜。複雜的程式都要分層,這是程式設計的要求。比如,複雜的電商還會分資料庫層、快取層、Compose層、Controller層和接入層,每一層專注做本層的事情。

程式是如何工作的?

當一個網路包從一個網口經過的時候,你看到了,首先先看看要不要請進來,處理一把。有的網口配置了混雜模式,凡是經過的,全部拿進來。

拿進來以後,就要交給一段程式來處理。於是,你呼叫process_layer2(buffer)。當然,這是一個假的函式。但是你明白其中的意思,知道肯定是有這麼個函式的。那這個函式是幹什麼的呢?從Buffer中,摘掉二層的頭,看一看,應該根據頭裡面的內容做什麼操作。

假設你發現這個包的MAC地址和你的相符,那說明就是發給你的,於是需要呼叫process_layer3(buffer)。這個時候,Buffer裡面往往就沒有二層的頭了,因為已經在上一個函式的處理過程中拿掉了,或者將開始的偏移量移動了一下。在這個函式裡面,摘掉三層的頭,看看到底是傳送給自己的,還是希望自己轉發出去的。

如何判斷呢?如果IP地址不是自己的,那就應該轉發出去;如果IP地址是自己的,那就是發給自己的。根據IP頭裡面的標示,拿掉三層的頭,進行下一層的處理,到底是呼叫process_tcp(buffer)呢,還是呼叫process_udp(buffer)呢?

假設這個地址是TCP的,則會呼叫process_tcp(buffer)。這時候,Buffer裡面沒有三層的頭,就需要檢視四層的頭,看這是一個發起,還是一個應答,又或者是一個正常的資料包,然後分別由不同的邏輯進行處理。如果是發起或者應答,接下來可能要傳送一個回覆包;如果是一個正常的資料包,就需要交給上層了。交給誰呢?是不是有process_http(buffer)函式呢?

沒有的,如果你是一個網路包處理程式,你不需要有process_http(buffer),而是應該交給應用去處理。交給哪個應用呢?在四層的頭裡面有埠號,不同的應用監聽不同的埠號。如果發現瀏覽器應用在監聽這個埠,那你發給瀏覽器就行了。至於瀏覽器怎麼處理,和你沒有關係。

瀏覽器自然是解析HTML,顯示出頁面來。電腦的主人看到頁面很開心,就點了滑鼠。點選滑鼠的動作被瀏覽器捕獲。瀏覽器知道,又要發起另一個HTTP請求了,於是使用埠號,將請求發給了你。

你應該呼叫send_tcp(buffer)。不用說,Buffer裡面就是HTTP請求的內容。這個函式裡面加一個TCP的頭,記錄下源埠號。瀏覽器會給你目的埠號,一般為80埠。

然後呼叫send_layer3(buffer)。Buffer裡面已經有了HTTP的頭和內容,以及TCP的頭。在這個函式裡面加一個IP的頭,記錄下源IP的地址和目標IP的地址。

然後呼叫send_layer2(buffer)。Buffer裡面已經有了HTTP的頭和內容、TCP的頭,以及IP的頭。這個函式裡面要加一下MAC的頭,記錄下源MAC地址,得到的就是本機器的MAC地址和目標的MAC地址。不過,這個還要看當前知道不知道,知道就直接加上;不知道的話,就要通過一定的協議處理過程,找到MAC地址。反正要填一個,不能空著。

萬事俱備,只要Buffer裡面的內容完整,就可以從網口發出去了,你作為一個程式的任務就算告一段落了。

揭祕層與層之間的關係

只要是在網路上跑的包,都是完整的。可以有下層沒上層,絕對不可能有上層沒下層。

所以,對TCP協議來說,三次握手也好,重試也好,只要想發出去包,就要有IP層和MAC層,不然是發不出去的。

經常有人會問這樣一個問題,我都知道那臺機器的IP地址了,直接發給他訊息唄,要MAC地址幹啥?這裡的關鍵就是,沒有MAC地址訊息是發不出去的。

所以如果一個HTTP協議的包跑在網路上,它一定是完整的。無論這個包經過哪些裝置,它都是完整的。

所謂的二層裝置、三層裝置,都是這些裝置上跑的程式不同而已。一個HTTP協議的包經過一個二層裝置,二層裝置收進去的是整個網路包。這裡面HTTP、TCP、 IP、 MAC都有。什麼叫二層裝置呀,就是隻把MAC頭摘下來,看看到底是丟棄、轉發,還是自己留著。那什麼叫三層裝置呢?就是把MAC頭摘下來之後,再把IP頭摘下來,看看到底是丟棄、轉發,還是自己留著。

小結

總結一下今天的內容,理解網路協議的工作模式,有兩個小竅門:

  • 始終想象自己是一個處理網路包的程式:如何拿到網路包,如何根據規則進行處理,如何發出去;

  • 始終牢記一個原則:只要是在網路上跑的包,都是完整的。可以有下層沒上層,絕對不可能有上層沒下層。

ifconfig:最熟悉又陌生的命令列

  • IP是地址,有定位功能;MAC是身份證,無定位功能;

  • CIDR可以用來判斷是不是本地人;

  • IP分公有的IP和私有的IP

DHCP與PXE:IP是怎麼來的,又是怎麼沒的?

動態主機配置協議(DHCP)

原來配置IP有這麼多門道兒啊。你可能會問了,配置了IP之後一般不能變的,配置一個服務端的機器還可以,但是如果是客戶端的機器呢?我抱著一臺膝上型電腦在公司裡走來走去,或者白天來晚上走,每次使用都要配置IP地址,那可怎麼辦?還有人事、行政等非技術人員,如果公司所有的電腦都需要IT人員配置,肯定忙不過來啊。

因此,我們需要有一個自動配置的協議,也就是動態主機配置協議(Dynamic Host Configuration Protocol),簡稱DHCP

有了這個協議,網路管理員就輕鬆多了。他只需要配置一段共享的IP地址。每一臺新接入的機器都通過DHCP協議,來這個共享的IP地址裡申請,然後自動配置好就可以了。等人走了,或者用完了,還回去,這樣其他的機器也能用。

所以說,如果是資料中心裡面的伺服器,IP一旦配置好,基本不會變,這就相當於買房自己裝修。DHCP的方式就相當於租房。你不用裝修,都是幫你配置好的。你暫時用一下,用完退租就可以了。

UDP協議

UDP和TCP是傳輸層的網路協議

UDP的三大特點

UDP就像小孩子一樣,有以下這些特點:

第一,溝通簡單,不需要一肚子花花腸子(大量的資料結構、處理邏輯、包頭欄位)。前提是它相信網路世界是美好的,秉承性善論,相信網路通路預設就是很容易送達的,不容易被丟棄的。

第二,輕信他人。它不會建立連線,雖然有埠號,但是監聽在這個地方,誰都可以傳給他資料,他也可以傳給任何人資料,甚至可以同時傳給多個人資料。

第三,愣頭青,做事不懂權變。不知道什麼時候該堅持,什麼時候該退讓。它不會根據網路的情況進行發包的擁塞控制,無論網路丟包丟成啥樣了,它該怎麼發還怎麼發。

UDP的三大使用場景

第一,需要資源少,在網路情況比較好的內網,或者對於丟包不敏感的應用

第二,不需要一對一溝通,建立連線,而是可以廣播的應用

第三,需要處理速度快,時延低,可以容忍少數丟包,但是要求即便網路擁塞,也毫不退縮,一往無前的時候

基於UDP的“城會玩”的五個例子

“城會玩”一:網頁或者APP的訪問

原來訪問網頁和手機APP都是基於HTTP協議的。HTTP協議是基於TCP的,建立連線都需要多次互動,對於時延比較大的目前主流的移動網際網路來講,建立一次連線需要的時間會比較長,然而既然是移動中,TCP可能還會斷了重連,也是很耗時的。而且目前的HTTP協議,往往採取多個數據通道共享一個連線的情況,這樣本來為了加快傳輸速度,但是TCP的嚴格順序策略使得哪怕共享通道,前一個不來,後一個和前一個即便沒關係,也要等著,時延也會加大。

QUIC(全稱Quick UDP Internet Connections快速UDP網際網路連線)是Google提出的一種基於UDP改進的通訊協議,其目的是降低網路通訊的延遲,提供更好的使用者互動體驗。

QUIC在應用層上,會自己實現快速連線建立、減少重傳時延,自適應擁塞控制,是應用層“城會玩”的代表。這一節主要是講UDP,QUIC我們放到應用層去講。

“城會玩”二:流媒體的協議

現在直播比較火,直播協議多使用RTMP,這個協議我們後面的章節也會講,而這個RTMP協議也是基於TCP的。TCP的嚴格順序傳輸要保證前一個收到了,下一個才能確認,如果前一個收不到,下一個就算包已經收到了,在快取裡面,也需要等著。對於直播來講,這顯然是不合適的,因為老的視訊幀丟了其實也就丟了,就算再傳過來使用者也不在意了,他們要看新的了,如果老是沒來就等著,卡頓了,新的也看不了,那就會丟失客戶,所以直播,實時性比較比較重要,寧可丟包,也不要卡頓的。

另外,對於丟包,其實對於視訊播放來講,有的包可以丟,有的包不能丟,因為視訊的連續幀裡面,有的幀重要,有的不重要,如果必須要丟包,隔幾個幀丟一個,其實看視訊的人不會感知,但是如果連續丟幀,就會感知了,因而在網路不好的情況下,應用希望選擇性的丟幀。

還有就是當網路不好的時候,TCP協議會主動降低傳送速度,這對本來當時就卡的看視訊來講是要命的,應該應用層馬上重傳,而不是主動讓步。因而,很多直播應用,都基於UDP實現了自己的視訊傳輸協議

“城會玩”三:實時遊戲

“城會玩”四:IoT物聯網

“城會玩”五:行動通訊領域

TCP協議

通過對TCP頭的解析,我們知道要掌握TCP協議,重點應該關注以下幾個問題:

  • 順序問題 ,穩重不亂;

  • 丟包問題,承諾靠譜;

  • 連線維護,有始有終;

  • 流量控制,把握分寸;

  • 擁塞控制,知進知退。

TCP的連線建立,我們常常稱為三次握手。

A:您好,我是A。

B:您好A,我是B。

A:您好B。

我們也常稱為“請求->應答->應答之應答”的三個回合。

  • 你需要記住TCP和UDP的Socket的程式設計中,客戶端和服務端都需要呼叫哪些函式;

  • 寫一個能夠支撐大量連線的高併發的服務端不容易,需要多程序、多執行緒,而epoll機制能解決C10K問題。

HTTP協議

開始應用層協議,上面是傳輸層的協議。

HTTP是基於TCP協議的,當然是要先建立TCP連線了,怎麼建立呢?還記得第11節講過的三次握手嗎? 目前使用的HTTP協議大部分都是1.1。在1.1的協議裡面,預設是開啟了Keep-Alive的,這樣建立的TCP連線,就可以在多次請求中複用。

HTTPS協議

流媒體協議(RTMP協議)

編碼是一個壓縮的過程

每一張圖片,我們稱為一。只要每秒鐘幀的資料足夠多,也即播放得足夠快。比如每秒30幀,以人的眼睛的敏感程度,是看不出這是一張張獨立的圖片的,這就是我們常說的幀率FPS)。

每一張圖片,都是由畫素組成的,假設為1024*768(這個畫素數不算多)。每個畫素由RGB組成,每個8位,共24位。

我們來算一下,每秒鐘的視訊有多大?

30幀 × 1024 × 768 × 24 = 566,231,040Bits = 70,778,880Bytes

如果一分鐘呢?4,246,732,800Bytes,已經是4個G了。

視訊和圖片的壓縮過程有什麼特點?

之所以能夠對視訊流中的圖片進行壓縮,因為視訊和圖片有這樣一些特點。

  1. 空間冗餘:影象的相鄰畫素之間有較強的相關性,一張圖片相鄰畫素往往是漸變的,不是突變的,沒必要每個畫素都完整地儲存,可以隔幾個儲存一個,中間的用演算法計算出來。

  2. 時間冗餘:視訊序列的相鄰影象之間內容相似。一個視訊中連續出現的圖片也不是突變的,可以根據已有的圖片進行預測和推斷。

  3. 視覺冗餘:人的視覺系統對某些細節不敏感,因此不會每一個細節都注意到,可以允許丟失一些資料。

  4. 編碼冗餘:不同畫素值出現的概率不同,概率高的用的位元組少,概率低的用的位元組多,類似霍夫曼編碼(Huffman Coding)的思路。

總之,用於編碼的演算法非常複雜,而且多種多樣,但是編碼過程其實都是類似的。

ITU-T(國際電信聯盟電信標準化部門,ITU Telecommunication Standardization Sector)與MPEG聯合制定了H.264/MPEG-4 AVC,這才是我們這一節要重點關注的

如何在直播裡看到帥哥美女?

當然,這個二進位制也可以通過某種網路協議進行封裝,放在網際網路上傳輸,這個時候就可以進行網路直播了。

網路協議將編碼好的視訊流,從主播端推送到伺服器,在伺服器上有個運行了同樣協議的服務端來接收這些網路包,從而得到裡面的視訊流,這個過程稱為接流

服務端接到視訊流之後,可以對視訊流進行一定的處理,例如轉碼,也即從一個編碼格式,轉成另一種格式。因為觀眾使用的客戶端千差萬別,要保證他們都能看到直播。

流處理完畢之後,就可以等待觀眾的客戶端來請求這些視訊流。觀眾的客戶端請求的過程稱為拉流

如果有非常多的觀眾,同時看一個視訊直播,那都從一個伺服器上拉流,壓力太大了,因而需要一個視訊的分發網路,將視訊預先載入到就近的邊緣節點,這樣大部分觀眾看的視訊,是從邊緣節點拉取的,就能降低伺服器的壓力。

當觀眾的客戶端將視訊流拉下來之後,就需要進行解碼,也即通過上述過程的逆過程,將一串串看不懂的二進位制,再轉變成一幀幀生動的圖片,在客戶端播放出來,這樣你就能看到美女帥哥啦。

整個直播過程,可以用這個的圖來描述。

編碼:如何將豐富多彩的圖片變成二進位制流?

雖然我們說視訊是一張張圖片的序列,但是如果每張圖片都完整,就太大了,因而會將視訊序列分成三種幀。

  • I幀,也稱關鍵幀。裡面是完整的圖片,只需要本幀資料,就可以完成解碼。

  • P幀,前向預測編碼幀。P幀表示的是這一幀跟之前的一個關鍵幀(或P幀)的差別,解碼時需要用之前快取的畫面,疊加上和本幀定義的差別,生成最終畫面。

  • B幀,雙向預測內插編碼幀。B幀記錄的是本幀與前後幀的差別。要解碼B幀,不僅要取得之前的快取畫面,還要解碼之後的畫面,通過前後畫面的資料與本幀資料的疊加,取得最終的畫面。

可以看出,I幀最完整,B幀壓縮率最高,而壓縮後幀的序列,應該是在IBBP的間隔出現的。這就是通過時序進行編碼

一個視訊,可以拆分成一系列的幀,每一幀拆分成一系列的片,每一片都放在一個NALU裡面,NALU之間都是通過特殊的起始識別符號分隔,在每一個I幀的第一片前面,要插入單獨儲存SPS和PPS的NALU,最終形成一個長長的NALU序列

推流:如何把資料流打包傳輸到對端?

那這個格式是不是就能夠直接在網上傳輸到對端,開始直播了呢?其實還不是,還需要將這個二進位制的流打包成網路包進行傳送,這裡我們使用RTMP協議。這就進入了第二個過程,推流

RTMP是基於TCP的,因而肯定需要雙方建立一個TCP的連線。在有TCP的連線的基礎上,還需要建立一個RTMP的連線,也即在程式裡面,你需要呼叫RTMP類庫的Connect函式,顯示建立一個連線。

RTMP為什麼需要建立一個單獨的連線呢?

因為它們需要商量一些事情,保證以後的傳輸能正常進行。主要就是兩個事情,一個是版本號,如果客戶端、伺服器的版本號不一致,則不能工作。另一個就是時間戳,視訊播放中,時間是很重要的,後面的資料流互通的時候,經常要帶上時間戳的差值,因而一開始雙方就要知道對方的時間戳。

未來溝通這些事情,需要傳送六條訊息:客戶端傳送C0、C1、 C2,伺服器傳送S0、 S1、 S2。

首先,客戶端傳送C0表示自己的版本號,不必等對方的回覆,然後傳送C1表示自己的時間戳。

伺服器只有在收到C0的時候,才能返回S0,表明自己的版本號,如果版本不匹配,可以斷開連線。

伺服器傳送完S0後,也不用等什麼,就直接傳送自己的時間戳S1。客戶端收到S1的時候,發一個知道了對方時間戳的ACK C2。同理伺服器收到C1的時候,發一個知道了對方時間戳的ACK S2。

於是,握手完成。

視訊名詞比較多,編碼兩大流派達成了一致,都是通過時間、空間的各種演算法來壓縮資料;

壓縮好的資料,為了傳輸組成一系列NALU,按照幀和片依次排列;

排列好的NALU,在網路傳輸的時候,要按照RTMP包的格式進行包裝,RTMP的包會拆分成Chunk進行傳輸;

推送到流媒體叢集的視訊流經過轉碼和分發,可以被客戶端通過RTMP協議拉取,然後組合為NALU,解碼成視訊格式進行播放。

FTP協議

如果你想下載一個電影,一般會通過什麼方式呢?

當然,最簡單的方式就是通過HTTP進行下載。但是相信你有過這樣的體驗,通過瀏覽器下載的時候,只要檔案稍微大點,下載的速度就奇慢無比。

還有種下載檔案的方式,就是通過FTP,也即檔案傳輸協議。FTP採用兩個TCP連線來傳輸一個檔案。

  • 控制連線:伺服器以被動的方式,開啟眾所周知用於FTP的埠21,客戶端則主動發起連線。該連線將命令從客戶端傳給伺服器,並傳回伺服器的應答。常用的命令有:list——獲取檔案目錄;reter——取一個檔案;store——存一個檔案。

  • 資料連線:每當一個檔案在客戶端與伺服器之間傳輸時,就建立一個數據連線。

P2P協議

  • 下載一個檔案可以使用HTTP或FTP,這兩種都是集中下載的方式,而P2P則換了一種思路,採取非中心化下載的方式;

  • P2P也是有兩種,一種是依賴於tracker的,也即元資料集中,檔案資料分散;另一種是基於分散式的雜湊演算法,元資料和檔案資料全部分散。

DNS協議

傳統的DNS有很多問題,例如解析慢、更新不及時。因為快取、轉發、NAT問題導致客戶端誤會自己所在的位置和運營商,從而影響流量的排程。

HttpDNS通過客戶端SDK和服務端,通過HTTP直接呼叫解析DNS的方式,繞過了傳統DNS的這些缺點,實現了智慧的排程。

  • CDN和電商系統的分散式倉儲系統一樣,分為中心節點、區域節點、邊緣節點,而資料快取在離使用者最近的位置。

  • CDN最擅長的是快取靜態資料,除此之外還可以快取流媒體資料,這時候要注意使用防盜鏈。它也支援動態資料的快取,一種是邊緣計算的生鮮超市模式,另一種是鏈路優化的冷鏈運輸模式。2021年12月3日17:48:41

(by 極客時間課程)