網絡,網絡...git
雖然只是一個簡單的名詞,可是她的背後卻掩藏着太多太多的故事以及知識。github
窮其編程的一輩子,或許也只能探索出那冰山一角,嗨...web
小時雖知,學海無涯,卻絕不知意。玩乃天性,卻空流時光。憾...編程
so,矯情之餘,咱們來探索一下網絡到底是怎麼傳輸的。瀏覽器
探索網絡的範圍,都在上圖有所展現(另存爲看大圖)。緩存
打開一個網站,都是從瀏覽器中輸入網址開始,咱們的探索也是從這裏開始。安全
https: 是協議,告訴瀏覽器咱們要訪問的目標,而https: 表明的就是訪問Web服務器,固然也有其餘的協議。好比ftp:訪問的就是FTP服務器等。服務器
sexyphoenix.github.io 是Web服務器域名,能夠告訴咱們在哪裏能夠找到Web服務器。網絡
about/ 是Web服務器裏面的文件路徑名,這裏的about是目錄名,全路徑多是about/index.md,而index.md應該被github掩藏了。負載均衡
瀏覽器首先要作的就是對URL進行解析,知道咱們要訪問的是sexyphoenix.github.io這個Web服務器上文件路徑爲about目錄下的默認文件。
知道了要訪問的目標,接下來瀏覽器就要生成HTTP的請求信息,介紹到這,就要聊一聊HTTP協議了。
HTTP協議規定了客戶端和服務器通訊的內容和步驟,簡單來講,就是兩個部分「對什麼」作「怎樣的操做」。
「對什麼」上面已經解析過了,「怎樣的操做」就是HTTP主要的方法:POST、GET、DELETE、PUT等。HTTP格式看下圖。
生成HTTP信息以後,接下來,咱們就要發送信息給Web服務器了。但此時咱們忽然發現咱們只有Web服務器的域名,並不知道服務器究竟在哪裏。
那麼咱們應該如何像現實中送快遞同樣,快速的定位到哪一幢哪一室,講到這裏,想必你們都有所意會了,IP。
IP地址
IP地址實際就是4個字節,32比特的數字,每8個比特爲1組,具體看下圖十進制表示。
咱們發送的信息,就是經過子網的集成器找到最近的路由器,再經過路由器(基於IP設計)找到最優抵達Web服務器的路由器,這樣不斷的查找網絡中的路由器節點,最終抵達Web服務器。
注意,咱們的Web服務器的IP是最終的目的地,它是貫穿路由器---N---路由器---Web服務器整個環節的,是判斷整個網絡走向的依據,存在控制信息中。
路由器都有本身的IP,路由器到路由器就是根據Web服務器的IP(走向),經過自己的IP來移動。
到這裏,咱們也就瞭解清楚了經過IP,發送的信息最終能夠抵達Web服務器。
那麼,咱們如今的問題就是如何經過Web服務器的域名找到它的IP? 講到這裏,想必你們又都有所意會了,DNS。
域名解析
簡單的來講,DNS服務器維持了一系列關係表,也就是域名和IP對於的關係表。瀏覽器向最近的DNS服務器詢問「sexyphoenix.github.io」的IP地址是多少,DNS服務器會回答Web服務器IP爲xxx。這一步也叫域名解析
講到這裏,咱們就要深究一下,瀏覽器到底是怎樣向DNS服務器發送查詢的?
首先,咱們要清楚一點,瀏覽器等應用程序自己是不能發送信息的,而是委託給操做系統來發送的。
而操做系統有一個超級出名的庫,Socket庫,它是調用網絡功能的程序組件集合。
Socket庫裏面有一個函數。
IP信息 = gethostbyname("sexyphoenix.github.io") # 看,應用程序查詢IP很簡單,調用一個函數便可
發送數據有兩種協議,UDP和TCP,域名查詢用的是UDP。數據短速度快。
介紹了域名解析,下面來了解一下DNS服務器的工做。
DNS服務器
在上面已經提到過了,DNS服務器維護了一個關係表,上圖的類型A表示域名對應IP地址,MX表示域名對應的郵箱服務器,不一樣的類型,返回的信息有所不一樣。
DNS服務器的工做就是根據域名和類型,查找相關的記錄,並嚮應用程序返回響應信息。
DNS服務器查找
全球共有13臺根域名服務器,根域名用「.」表示,其次纔是下面的一級域名「com.」、「net.」等,咱們平時訪問的域名「sexyphoenix.github.io.」後面有一個點,平時被省略。
咱們用一張圖來看下查找順序,更清楚些。
先找最近的DNS服務器(通常是本機設置的),沒有再從根域找,而後不斷的向下找,直到找到咱們Web服務器IP所在的DNS服務器。
經過DNS服務器查詢,咱們已經獲得的Web服務器的IP,接下來就要開始發送數據了。而這部分也是比較難寫的一部分,由於咱們要深刻協議棧的內部,去了解它的結構。
咱們都知道數據的傳輸,都是由上層委託給下層工做的。應用程序將發送的信息的行爲委派給了操做系統,而操做系統內部就是經過協議棧來工做的。
來看下操做系統協議棧圖。
上部分是TCP協議和UDP協議,都是負責數據的收發部分,區別在於TCP是面向鏈接的,是一種可靠的協議,而UDP只負責發送,不保證準確到達。
下部分是IP協議,負責發送網絡包,其中還包括ICMP協議(檢查發送過程是否存在錯誤)和ARP協議(查詢MAC地址)。
數據收發
在查詢IP地址的時候,咱們用到了Socket庫,這裏一樣也須要用到它。
不過咱們這裏須要調用多個組件,才能實現數據的收發,從功能上能夠分爲四個部分。
建立套接字 (new Socket)
鏈接服務器的套接字 (connection)
收發數據 (write、read)
刪除套接字 (close)
在講以前,咱們先了解下套接字。
套接字在數據收發中是至關重要的,它是一塊內存空間,裏面存放着很重要的的控制信息。
這些控制信息存放着通訊對象的IP地址、端口、鏈接狀態、響應時間、數據收發狀況等等,只有這些存在,才能知道數據發送到哪裏,又發送了多少,有沒有錯誤等等。
建立套接字仍是很是簡單的,直接調用Socket庫中的socket組件便可,建立完成以後會返回一個標識符,標識符的主要做用就是爲了區別不一樣的套接字。
鏈接服務器用到的是connect組件,參數有標識符、服務器的IP、端口等,至關於和服務器之間鏈接了一條數據管道,後期數據在其中流通。
同時在這裏也會發生著名的「三次握手」。
在剛發生鏈接階段,管道里面是沒有數據的,可是會有控制信息,這些控制信息包括TCP頭部,以太網頭部、IP頭部。
控制信息
根據層級來,咱們會先生成TCP頭部,TCP頭部格式有不少字段,其中重要的就是雙方的端口,序號,ACK號,控制位,窗口等。稍微瞭解一下這些字段的做用。
端口
端口和IP是一同存在的,在互聯網早期的時候,公司聯網都是直接用公網IP的,但隨着互聯網的發展,公網IP愈來愈少,因而就出現了公網和內網的區別。
內網IP範圍
10.0.0.0 ~ 10.255.255.255
172.16.0.0 ~ 172.31.255.255
192.168.0.0 ~ 192.168.255.255
每一個公司的內部都使用這些內網IP,再經過惟一的一個公網IP訪問互聯網,這樣就能夠節省大量的公網IP。
那麼公司的這些設置內網IP的電腦是如何經過惟一的公網IP訪問互聯網呢? 互聯網返回的信息又是怎麼經過惟一的公網IP,定位到公司的某一臺電腦上的?
地址轉換(NAT),這個技術就解決了上面的問題,它的原理就是在轉發網絡包時對IP頭部地址和端口進行改寫。
而端口在其中的做用相當重要,它可讓路由器(公網IP)知道是那一臺內網的電腦與互聯網通訊,具體看下圖。
公司IP爲192.168.23.183的電腦,經過49158端口向互聯網發送鏈接,當到達公司的公網路由器的時候,路由器的IP模塊會對控制信息進行改寫,最後變成IP爲121.225.19.59,端口爲1001和通訊對象通訊。
同時將這條記錄保存在路由器上,當通訊對象返回信息時,會經過表格中的信息找到對應的內網電腦IP。
序號
發送方告訴接收方該網絡包在全部發送的數據的第幾個字節,序號的初始值是在鏈接階段隨機生成的(防止攻擊者猜到),在下面的收發數據階段,就是以這個序號爲基數。
ACK號
接收方告訴發送發已經收到全部數據的第幾個字節,至關於序號+發送的數據長度。
控制位
每個比特表明不一樣的控制信息,看下圖。
圖中解釋了比較重要的控制位。
窗口
接收方告訴發送方的窗口大小,若是接收方接受的速度比較慢,一塊兒傳送的數據量就會變小至關於控制了咱們傳送數據的快慢。
介紹了TCP頭部的關鍵字段,接下來咱們開始進入鏈接。
首先,咱們會將客戶端的控制位的SYN(1)、生成隨機序號M、窗口大小等,再經過其餘層,到達服務器端(第一次握手)。
服務器收到SYN爲1的信息,知道客戶端要和我鏈接,生成ACK號(M+1)、服務器隨機序號N(通訊是雙向的,這時的服務器也至關於發送方)、控制位SYN(1)、窗口等發送(第二次握手)。
客戶端收到服務器端的信息,獲得ACK號,知道鏈接正常,發送ACK號(N+1,服務器端的序號)、控制位SYN(1),告訴服務器已創建鏈接(第三次握手)。
管道鏈接創建成功後,就進入了數據收發階段。
咱們發送的信息通常都是比較大的,不可能一次性發送完畢,因此在TCP模塊,就會將應用數據切分紅數據塊,切分的每一個數據塊(MSS,最大數據長度)加上TCP頭部,IP頭部不能超過MTU大小(MTU,最大傳輸單元)。
接下來,交給IP模塊,生成IP頭部和MAC頭部信息,再經過網卡驅動,網卡設備將數字信息轉變成電信號,傳輸到接收方。接收方收到信息,會返回ACK號,重複以上步驟,直到接收方收到全部數據。
接收方收到所有數據後,一樣會向發送方發送數據,下面的步驟都和上面差很少了,這裏再也不贅述。
和接收方通訊完成以後,套接字不會再使用,這時就能夠刪除套接字了。
套接字刪除能夠由任何一方發起,這裏假設服務器端發起,下面就來說講著名的「四次揮手」。
接收方收到所有數據後,等待一會就會刪除套接字。
服務器生成斷開信息,即將TCP的頭部控制位的FIN設置爲1,發送給客戶端。
客戶端返回ACK號,表示發送的信息無誤。
客戶端全部數據處理完成後,向服務器發送FIN爲1的斷開信息。
服務器返回ACK號,表示發送的信息無誤,等待一會,客戶端和服務器端都刪除套接字。
講到這裏,數據收發的絕大數內容就講完了,接下來咱們聊一聊IP模塊。
IP模塊
前面提到過,在IP模塊會生成IP頭部和以太網頭部。那麼這兩個頭部究竟有什麼做用?
爲了便於理解,咱們這裏就講的簡單一些。
發送的數據到達子網的集線器或者交換機,經過MAC表,找到下一個轉發設備的MAC地址,以「以太網協議」傳輸到下一個轉發設備。
轉發設備根據目標地址的IP和「IP協議」判斷下一個轉發設備的IP,再經過MAC地址,傳輸到下一個轉發設備。
就這樣,通過多個轉發設備的接力後,網絡包最終到達接收方的網絡設備。
總結:IP協議根據目標地址判斷下一個IP轉發設備的位置,再經過以太網協議將網絡包輸出到下一個轉發設備。
其實在到達Web服務器以前,咱們也應該講講數字信號是如何轉化爲電子信號的? 數據又是如何經過運營商到達Web服務器的?
只是這部分實在過於複雜,也多數跟硬件以及運維方向有關,這裏就不講了。
首先,咱們來說一講Web服務器的部署。
Web服務器的部署有三種方式
直接部署在公司的內網。
公司的內網和Web服務器分開部署。在接入網以後,部署統一防火牆,再分別進去內網和服務器。
web服務器部署在運營商的數據中心。
三種方式自上而下,性能和安全上會愈來愈好,只是管理上可能會麻煩些。
爲了安全和分擔負載,Web服務器前面會部署防火牆,可能還會有負載均衡器、緩存服務器、內容分發等等。
數據在通過層層過濾後,最終到達Web服務器,服務器的程序和上面建立鏈接的步驟稍有不一樣。
首先是建立套接字(socket)。
綁定套接字和端口號(bind)。
等待鏈接(listen)。
接受鏈接(accept)。
服務器的程序會一直等待客戶端的鏈接。
在接收到客戶端的請求後,Web服務器根據URI轉換爲實際的文件名,並做出響應。格式以下。
到這裏,咱們全部的內容就到這裏了。
最後,祝你們天天身體健康,開心編程,看的開心。嘿...