照例是寫在前面的話,今天在這里想和自己說一些話,希望未來的自己能夠記住,就像我在簡書的簽名里寫下的,“希望自己能記得當下寫下那段文字的初心!”,學習其實是一件非常嚴肅的事情,它容不得半點馬虎和粗心,當你在當下去學習的時候,你應該去做的事全心全意,專注的去做當下的這件事,而不是又看電視,有看書,又在玩游戲,因為你看起來在學習,其實是在表演!昨天晚上看了一篇脈脈分享的文章讓我感覺到很慚愧,“打工”十年月薪7000,思維落后的努力都是瞎忙,其中有一個觀點是,如果你的勤奮只是流于表面,只是為了炫耀與朋友圈,只是為了做給領導看,那你就是假的勤奮,這種表演式的勤奮并不能持續多久。其中一句話是"只有真正的勤奮才能改變一個人的命運,那些假勤奮的人看起來很風光,其實達不到很高的高度!",和大家共勉吧!啰嗦完畢,下面正式開始。
這次寫的文章是《網絡是怎樣連接的》讀書筆記,這本書真的是滿滿的干貨,希望每一個程序員都應該學習的一本書,對這本書,真的是相見恨晚。我們這次記錄第一章的內容,以后我會堅持把這本書的所有讀書筆記都寫完。
這張腦圖是我自己整理的,還不是很完善,等把所有的章節讀完之后,會有一個整體的腦圖做出來,那一定很壯觀!我們就按照這個腦圖上的章節開始整理吧。本筆記中所有的圖都來至書中。
我們的探索之旅是從在瀏覽器中輸入一個網址開始的。那么我們就從第一步,網址開始吧!
第一步:解析網址
網址它的另一個名字叫URL
,全名叫:Uniform Resource Locator
,統一資源定位符。還有一個是URI
,全名叫Uniform Resource Identifier
,統一資源標識符。他們兩個是什么關系呢?想必很多人都不清楚吧。
URI
叫統一資源表示符,是用字符串標識某一互聯網資源,而URL
表示資源的地點(互聯網上所處的位置)。可見URL
是URI
的子集。
我們可以看一下URL
的各種格式:
這里我們簡單的介紹一下URL
的格式:
1.http
,ftp
,file
,mailto
,news
這部分文字都表示瀏覽器應 當使用的訪問方法:
比如當訪問Web 服務器時應該使用HTTPA 協議,而
訪問FTP服務器時則應該使用FTP協議。因此,我們可以把這部分理解為
訪問時使用的協議類型。盡管后面部分的寫法各不相同,但開頭部分的
內容決定了后面部分的寫法,因此并不會造成混亂。
2.user:password
,表示輸入的用戶名和密碼
3.www.glasscom.com
,表示的訪問的域名
4.:80
是表示的端口號
5./dir/file1.html
表示的訪問的文件地址。
而在瀏覽器解析的時候是這樣的:
HTTP的基本思路
在解析完網址以后,我們已經知道了想要訪問的文件在哪里,這個時候就需要瀏覽器通過使用HTTP
協議來訪問瀏覽器:
HTTP
協議定義了客戶端和服務器之間交互的消息內容和步驟,其基 本思路非常簡單。首先,客戶端會向服務器發送請求消息。 請求 消息中包含的內容是“對什么”和“進行怎樣的操作”兩個部分。
其中“對什么”就是URI
,(上面說的那個統一資源定位符)而“進行怎樣的操作”就是方法,
方法表示需要讓 Web
服務器完成怎樣的工作,其中典型的例子包括讀取URI表示的數據、 將客戶端輸入的數據發送給URI
表示的程序等。
那,這里就是大家所熟悉的各種GET,POST,PUT
等方法了,具體方法的含義,我會在另一個筆記中進行詳解。
第二步:生成HTTP請求信息
對URL
解析之后,我們知道了Web
服務器和域名,下面就應該生成請求信息了。
我們看一下請求消息的格式:
請求消息:
第一行:請求行,通過這一行可以大致了解請求的內容。
第二行:消息頭,每行包含一個頭字段,用于表示請求的附加信息。
第三行:消息體,包含客戶端向服務端發送的數據。
響應消息:
第一行:狀態行
第二行:消息頭
第三行:消息體,包含服務器向客戶端發送的數據。
這里我們列舉一下HTTP
中主要的頭字段:
TODO:這里暫時先放在這里,后期在整理到別的專門的一篇里。還有響應消息的狀態碼,這里也暫時欠缺吧
**注意:1 條請求消息中只能寫 1 個 URI。如果需要獲取多個文件,必須 對每個文件單獨發送 1 條請求。 **
這里是HTTP
消息示例:
第三步:向DNS服務器查詢IP地址
說起通過DNS
服務器查詢IP
地址,我們需要明白兩個概念,一個是IP
,一個是DNS
,
IP地址的基本知識
IP地址的基本思路
在網絡中,所有的設備都會被分配一個地址。這個地址就相當于現實 中某條路上的“×× 號 ×× 室”。 其中“號”對應的號碼是分配給整個子 網的,而“室”對應的號碼是分配給子網中的計算機的,這就是網絡中的 地址。“ 號”對應的號碼稱為網絡號,“ 室”對應的號碼稱為主機號,這個 地址的整體稱為IP
地址 。通過IE
地址我們可以判斷出訪問對象服務器的 位置,從而將消息發送到服務器。消息傳送的具體過程在后面的章節有詳 細講解,不過現在我們先簡單了解一下。發送者發出的消息首先經過子網
中的集線器 ,轉發到距離發送者最近的路由器上。 接下來, 路由器會根據消息的目的地判斷下一個路由器的位置,然后將消息發送 到下一個路由器,即消息再次經過子網內的集線器被轉發到下一個路由 器。 前面的過程不斷重復,最終消息就被傳送到了目的地.
實際的IP地址
實際的IP
地址是一串32比特的數字,按照8比特為一組分成4組,分別用十進制表示,然后再用圓點分開。
這就是我們平常經常見到的 IP 地址格式,但僅憑這一 串數字我們無法區分哪部分是網絡號,哪部分是主機號。
在 IP 地址的規則 中,網絡號和主機號連起來總共是 32 比特,但這兩部分的具體結構是不固
定的。在組建網絡時,用戶可以自行決定它們之間的分配關系,因此,我 們還需要另外的附加信息來表示 IP
地址的內部結構。
這一附加信息稱為子網掩碼。子網掩碼的格式如1.10圖所示,是一 串與 IP 地址長度相同的 32 比特數字,其左邊一半都是 1,右邊一半都是其中,子網掩碼為 1 的部分表示網絡號,子網掩碼為 0 的部分表示主機 號。將子網掩碼按照和 IP 地址一樣的方式以每 8 比特為單位用圓點分組后 寫在 IP 地址的右側,這就是圖 1.9(b)的方法。這種寫法太長,我們也可 以把 1 的部分的比特數用十進制表示并寫在 IP 地址的右側,如圖 1.9(c) 所示。這兩種方式只是寫法上的區別,含義是完全一樣的。
主機號部分的比特全部為0則表示整個子網
主機號部分的比特全部為1則表示向子網上所有的設備發送包,及“廣播”。
關于子網掩碼非常不好理解,可以看這里
為什么我們有了域名還會需要IP地址呢?
因為:TCP/IP網絡是通過IP地址來確定通信對象的,因此必須知道IP地址。
干嘛不用域名代替IP地址呢?
機器在處理IP的時候要比處理域名要快的多,一個IP地址的長度是32比特,也就是4個字節,而域名最短也要幾十個字節,甚至最長255自己。也就是使用IP地址,只需要處理4自己數字。而域名則需要處理幾十個到255個自己,這就增加了路由器的負擔,傳送數據時也會花費更多的時間。
域名是給人用的,這樣好記,比如百度,而IP地址是給機器用的,這樣快!
應該怎么查IP呢?通過Socket庫來查詢DNS服務器
這里有幾個概念:
什么是解析器?
計算機上負責調用一段程序來查詢DNS的客戶端叫DNS解析器,簡稱解析器。
什么是域名解析?
通過DNS查詢IP地址的操作稱為域名解析。
這一段程序在哪里呢?
在Socket庫里,Socket 庫是用于調用網絡功能的程序組件集合。
解析器的調用
通過Socket庫中的代碼,調用gethostbyname
,然后輸入域名參數,就可以查詢到IP地址了
解析器的內部原理
當我們調用Socket
庫中的gethostbyname
方法時,我們會生成一條消息,這條消息表示“請告訴我www.baidu.com的ip地址”,并把這條消息通過網卡發送到DNS服務器中進行查詢,查詢到以后DNS服務器返回響應的消息;從響應的消息中取出IP地址,并存放到內存地址中,接著返回應用程序。
這就是解析器的基本原理。
DNS服務器的基本工作
來自客戶端的查詢消息包含以下3種信息。
1:域名
服務器、郵件服務器(郵件地址中 @ 后面的部分)的名稱
2:Class
在設置DNS方案時,互聯網之外的網絡也考慮到了,而Class就是用來識別網絡的,不過現在只有互聯網,所以它的值永遠都是代表互聯網的IN
3:記錄類型
標識域名對應何種類型的記錄。
類型為A:表示域名對應的IP地址
類型為MX時,表示域名對應的是郵件服務器。
類型為PTR,表示根據IP地址反查域名。
類型為CNAME,表示查詢域名相關別名。
類型為NS,表示查詢DNS服務器IP地址。
類型為SOA。表示查詢域名屬性信息的。
下面是DNS服務器的基本工作;
DNS 服務器會從域名與 IP 地址的對照表中查找相應的記錄,并 返回 IP 地址。
域名的層次結構
由于信息實際上并不能全部保存在一臺DNS服務器上,而是分布在很多臺DNS服務器中,這些DNS服務器相互配合,才能查詢出想要的信息。
所以我們這里要看一下:
信息是如何在DNS服務器上注冊并保存的。
1.DNS服務器中的所有信息都是按照域名以分層次的結構來保存的。
2.DNS中的域名都是用句點來分割的,比如www.baidu.com
,這個句點就代表了三個層次的域名服務器。www
是一個,baidu
是一個,com
是一個,越靠左層次越高,每個域都是作為一個整體來處理的,也就是一個域就作為一個整體存放在DNS服務器中,上一級域保存著下一級域的信息,也就是www
這個根域保存著baidu
這個域的信息,當我們需要查詢的時候,只需要找到根域,然后就可以從根域中查找到我們所要找的域名。
3.實際上域名的根域并不是www
,而是在上一個層次的,這個域名保存著www
這個層次的域名信息。
查找響應的DNS服務器并獲取IP地址
我們知道了信息是如何保存的后,也就是知道了應該怎么查詢,因為上一級域名保存著下一級域名的信息,上一級的DNS服務器保存著下一級的DNS服務器信息,我們首先訪問最近的DNS服務器,這里其實就是我們計算機上自己已經記錄的那臺DNS服務器,然后我們訪問根域的DNS服務器,通過根域我們知道了www
的域名DNS的IP在哪里,然后我們訪問它,通過它的信息里保存的信息繼續往下查,一直到我們要查的域名為止,接著返回查到的IP地址。
通過上面這兩張圖我們就知道查詢DNS服務器的全貌,大家細細品味一下。
我們還可以更快,通過緩存加快DNS服務器的查詢速度
時候并不需要從最上級的根域開始查找,因為 DNS 服務器有一 個緩存 A 功能,可以記住之前查詢過的域名。如果要查詢的域名和相關信息已 經在緩存中,那么就可以直接返回響應,接下來的查詢可以從緩存的位置開 始向下進行。相比每次都從根域找起來說,緩存可以減少查詢所需的時間。
第四步:委托協議棧發送消息
既然我們已經知道了IP地址,那么我們就可以委托系統內部的協議棧向這個IP地址也就是Web
服務器發送消息了。
發送消息的過程大體如上圖所示的那樣:
實際上我們需要經過下面四個步驟:
1.創建套接字(創建套接字階段)
2.將管道連接到服務器端的套接字上(連接階段)
3.收發數據(通信階段)
4.斷開管道并刪除套接字(斷開階段)
這里我們大體講一下流程,在第二章節會詳細進行講解
從上面的圖中,我們可以分為以下幾個步驟:
1.通過解析器查詢DNS服務器獲取域名的IP地址
2.通過調用socket
組件創建套接字。而描述符就是套接字的句柄,以讓客戶端加以區分
3.通過調用Socket
庫中的connect
方法進行三次握手的連接
4.通過調用Socket
庫中的writer
發送數據
5.通過調用Socket
庫中的read
接受數據
6.通過調用Socket
庫中close
方法斷開連接。
關于協議棧發送消息,我們會在第二章部分具體詳解。
其實這篇文章是上周就寫完的,由于簡書的圖片不能用外部鏈接,所在這周才發布!