《网络是怎样连接的》笔记
目錄
- 前序
- 一、生成HTTP請求消息
- 二、向DNS服務器查詢Web服務器的IP地址
- 三、瀏覽器委托協議棧發送消息
- 四、IP與以太網的包收發操作
- 五、集線器、交換機、路由器
- 六、服務器端的局域網中有什么玄機
- 七、請求到達Web服務器,響應返回瀏覽器
整體結構
全書主要圍繞以下結構書寫
網絡包的旅程
一、生成HTTP請求消息
1.1、瀏覽器輸入URL
http://www.baidu.com1.2、首先根據HTTP的規則,解析URL
1.3、URL省略文件名的幾種情況
- a) http://www.baidu.com/dir/
在/dir/后面省略了訪問的文件名,服務器已經默認設置在省略文件名情況下要訪問的默認文件名,一般都會訪問/dir/index.html或者/dir/default.html
- b) http://www.baidu.com/dir
一般處理方案:如果web服務器上存在dir文件,則將dir當作文件名來處理;如果web服務器上存在名為dir的目錄,則將dir當作目錄來處理
- c) http://www.baidu.com/
這個URL表示:它訪問一個名叫/的目錄。由于省略了文件名,所以根據上一種情況,它訪問的文件也就是/index.html或者/default.html。
注釋:/目錄表示的是目錄層級中最頂級的『根目錄』
- d)、http://www.baidu.com
沒有路徑時,表示訪問根目錄下事先設置的默認文件夾,也就是/index.html或者/default.html
1.4、HTTP的基本思路
HTTP協議:它定義了客戶端與服務器之間交互信息的內容和步驟
HTTP請求消息包含『對什么』和『進行怎樣的操作』兩個部分。
其中相當于『對什么』的部分稱為URI。一般來說URI的內容是一個存放網頁的文件名或者是一個CGI程序的文件名,例如"/dir/file.html"、"/dir/program.cgi"等。
其中『進行怎樣的操作』的部分稱為方法。方法表示需要讓web服務器完成怎樣的工作,其中典型的例子包括讀取URI表示的數據、將客戶端輸入的數據傳遞給CGI程序等。
URI:Uniform Resource Identifier,統一資源標識符
CGI程序:對web服務器程序調用其他程序的規則所做的定義就是CGI,安裝這個規則來工作的程序就是CGI程序。
HTTP的主要方法
| GET | 獲取URI指定的信息,如果URI指定的文件,則返回文件的內容;如果URI指定的是CGI程序,則返回該程序的輸出數據 |
| POST | 從客戶端向服務器發送數據。一般用于發送表單中填寫的數據等情況下 |
1.5、生成HTTP請求消息
1.6、發送請求后收到響應消息
響應狀態碼
1.7、請求網頁中包含圖片
1條請求消息中只能寫一個URI,如果需要獲取多個文件,必須對每個文件單獨發送1條請求
二、向DNS服務器查詢Web服務器的IP地址
瀏覽器能夠解析網址并生成HTTP消息,但它本身不具備將消息發送到網絡的功能,因此這一功能需要委托操作系統來實現。在委托操作系統發送消息時,必須提供通訊對象的IP地址,而不是域名,因此在HTTP消息之后,我們需要根據域名查詢IP地址
2.1、TCP/IP網絡
互聯網和公司內部的局域網都是基于TCP/IP的思路來設計的,TCP/IP的結構就是由一些小的子網,通過路由器連接起來組成一個大的網絡,這里的子網可以理解為用集線器連接起來的幾臺計算機,我們將它看成一個單位,稱為子網,將子網通過路由器連接起來,就形成一個網絡。
2.2、IP地址
在網絡中,所有的設備都會被分配一個地址,這個地址就相當于顯示中某一條路上的"XX號XX室",其中"號"對應的號碼是分配給整個子網的,而"室"對應的號碼是分配給子網中的計算機的,這就是網絡中的地址。"號"稱為網絡號,"室"稱為主機號,整個地址稱為IP地址。
IP地址 = 網絡號 + 主機號
預熱:數據傳遞過程
通過IP地址我們可以判斷出訪問對象服務器的位置,從而將消息發送到服務器。消息傳送的具體過程在后面的章節有詳細講解,不過現在我們先簡單了解一下。發送者發出的消息首先經過子網中的集線器,轉發到距離發送者最近的路由器上(上圖①)。接下來,路由器會根據消息的目的地判斷下一個路由器的位置,然后將消息發送到下一個路由器,即消息再次經過子網內的集線器被轉發到下一個路由器(上圖②)。前面的過程不斷重復,最終消息就被傳送到了目的地。
2.3、IP地址結構
實際的IP地址是一串32比特(bit)的數字,按照8bit=1byte(字節)為一組分成4組,分別用十進制表示。這就是我們常見的IP地址格式,但僅憑這一串數字我們無法區分哪部分是網絡號,哪部分是主機號。在IP地址的規則中,網絡號和主機號連起來總共是32比特,但這兩部分的具體結構是不固定的。在組建網絡時,用戶可以自行決定它們之間的分配關系,因此,我們還需要另外的附加信息來表示IP地址的內部結構。
IP地址的主機號:
全0:表示整個子網
全1:表示向子網上所有設備發送包,即『廣播』
2.4、瀏覽器如何向DNS服務器發出查詢的呢?
DNS解析器
向 DNS服務器發出查詢,也就是向DNS服務器發送查詢消息,并接收服務器返回的響應消息。換句話說,對于 DNS服務器,我們的計算機上一定有相應的 DNS客戶端,而相當于 DNS客戶端的部分稱為 DNS解析器,或者簡稱解析器。通過 DNS查詢 IP地址的操作稱為域名解析,因此負責執行解析( resolution)這一操作的就叫解析器( resolver)了。解析器實際上是一段程序,它包含在操作系統的 Socket庫中。
庫
首先,庫到底是什么東西呢?庫就是一堆通用程序組件的集合,其他的應用程序都需要使用其中的組件。庫有很多好處。首先,使用現成的組件搭建應用程序可以節省編程工作量;其次,多個程序使用相同的組件可以實現程序的標準化。除此之外還有很多其他的好處,因此使用庫來進行軟件開發的思路已經非常普及,庫的種類和數量也非常之多。
Socket庫
Socket庫也是一種庫,是用于調用網絡功能的程序組件集合。其中包含的程序組件可以讓其他的應用程序調用操作系統的網絡功能 ,而解析器就是這個庫中的其中一種程序組件。
2.5、如何通過解析器向DNS服務器發出查詢
根據域名查詢 IP地址時,瀏覽器會使用 Socket庫中的解析器。
調用解析器后,解析器會向 DNS服務器發送查詢消息,然后DNS服務器會返回響應消息。響應消息中包含查詢到的IP地址,解析器會取出 IP地址,并將其寫入瀏覽器指定的內存地址中。只要運行圖 1.11中的這一行程序,就可以完成前面所有這些工作,我們也就完成了IP地址的查詢。接下來,瀏覽器在向 Web服務器發送消息時,只要從該內存地址取出 IP地址,并將它與HTTP請求消息一起交給操作系統就可以了。
2.6、如何獲取DNS服務器IP地址?(Domain Name System,域名系統)
向 DNS服務器發送消息時,我們當然也需要知道 DNS服務器的 IP地址。只不過這個 IP地址是作為 TCP/ IP的一個設置項目事先設置好的,不需要再去查詢了。不同的操作系統中 TCP/ IP的設置方法也有差異,Windows中的設置如下圖所示,解析器會根據這里設置的 DNS服務器 IP地址來發送消息。
2.7、DNS服務器是如何工作的
DNS服務器會從域名與 IP地址的對照表中查找相應的記錄,并返回 IP地址。
域名
例如:www.baidu.com
服務器、郵件服務器(郵件地址中 @后面的部分)的名稱
Class
在最早設計 DNS方案時, DNS在互聯網以外的其他網絡中的應用也被考慮到了,而 Class就是用來識別網絡的信息。不過,如今除了互聯網并沒有其他的網絡了,因此 Class的值永遠是代表互聯網的 IN
記錄類型
例如:A = IP地址
MX = 郵件服務器
CNAME = 域名相關的別名
表示域名對應何種類型的記錄。例如,當類型為 A時,表示域名對應的是 IP地址;當類型為 MX時,表示域名對應的是郵件服務器。對于不同的記錄類型,服務器向客戶端返回的信息也會不同
2.8、如何在數萬DNS服務器中找到目標DNS服務器
域名層次結構
DNS中的域名都是用句點來分隔的,比如 www.lab.glasscom.com,這里的句點代表了不同層次之間的界限,就相當于公司里面的組織結構不用部、科之類的名稱來劃分,只是用句點來分隔而已 。
在域名中,越靠右的位置表示其層級越高,比如 www. lab. glasscom. com這個域名如果按照公司里的組織結構來說,大概就是“ com事業集團 glasscom部 lab科的 www”這樣。其中,相當于一個層級的部分稱為域。因此, com域的下一層是 glasscom域,再下一層是 lab域,再下面才是 www這個名字。
根域
com、jp、cn這些域(稱為頂級域)就是最頂層了,它們各自負責保存下級DNS服務器的信息,但實際上并非如此。在互聯網中,com和 jp的上面還有一級域,稱為根域。根域不像 com、 jp那樣有自己的名字,因此在一般書寫域名時經常被省略,如果要明確表示根域,應該像 www. lab. glasscom. com.這樣在域名的最后再加上一個句點,而這個最后的句點就代表根域。不過,一般都不寫最后那個句點,因此根域的存在往往被忽略,但根域畢竟是真實存在的,根域的 DNS服務器中保管著 com、 jp等的 DNS服務器的信息。由于上級 DNS服務器保管著所有下級 DNS服務器的信息,所以我們可以從根域開始一路往下順藤摸瓜找到任意一個域的 DNS服務器。
通過根域找到目標DNS服務器
還需要完成另一項工作,那就是將根域的 DNS服務器信息保存在互聯網中所有的 DNS服務器中。這樣一來,任何 DNS服務器就都可以找到并訪問根域 DNS服務器了。因此,客戶端只要能夠找到任意一臺 DNS服務器,就可以通過它找到根域 DNS服務器,然后再一路順藤摸瓜找到位于下層的某臺目標 DNS服務器。分配給根域 DNS服務器的 IP地址在全世界僅有 13個,而且這些地址幾乎不發生變化,因此將這些地址保存在所有的 DNS服務器中也并不是一件難事。實際上,根域 DNS服務器的相關信息已經包含在 DNS服務器程序的配置文件中了,因此只要安裝了 DNS服務器程序,這些信息也就被自動配置好了。
三、瀏覽器委托協議棧發送消息
整體流程一覽圖
創建套接字
<描述符> = socket(<使用IPv4>,<使用TCP>,…)
瀏覽器調用Socket庫中socket程序組件,和調用解析器一樣,調用socket之后,控制流程會轉移到socket內部并執行創建套接字的操作,完成之后控制流程又會被移交回應用程序。
應用程序調用 socket申請創建套接字,協議棧根據應用程序的申請執行創建套接字的操作。在這個過程中,協議棧首先會分配用于存放一個套接字所需的內存空間,然后寫入初始狀態。此內存空間用于記錄套接字的控制信息。
套接字 創建成功后,協議棧會返回一個描述符,應用程序會將收到的描述符存放在內存中。
描述符
應用程序是通過“描述符”這一類 似號碼牌的東西來識別套接字的。
描述符是用來識別不同的套接字的,大家可以作如下理解。我們現在只關注了瀏覽器訪問 Web服務器的過程,但實際上計算機中會同時進行多個數據的通信操作,比如可以打開兩個瀏覽器窗口,同時訪問兩臺 Web服務器。這時,有兩個數據收發操作在同時進行,也就需要創建兩個不同的套接字。這個例子說明,同一臺計算機上可能同時存在多個套接字,在這樣的情況下,我們就需要一種方法來識別出某個特定的套接字,這種方法就是描述符。我們可以將描述符理解成給某個套接字分配的編號。也許光說編號還不夠形象,大家可以想象一下在酒店寄存行李時的場景,酒店服務人員會給你一個號碼牌,向服務人員出示號碼牌,就可以取回自己寄存的行李,描述符的原理和這個差不多。當創建套接字后,我們就可以使用這個套接字來執行收發數據的操作了。這時,只要我們出示描述符,協議棧就能夠判斷出我們希望用哪一個套接字來連接或者收發數據了。
由于套接字中記錄了通信雙方的信息以及通信處于怎樣的狀態,所以只要通過描述符確定了相應的套接字,協議棧就能夠獲取所有的相關信息,這樣一來,應用程序就不需要每次都告訴協議棧應該和誰進行通信了。
套接字
socket本質是編程接口(API),對TCP/IP的封裝,TCP/IP也要提供可供程序員做網絡開發所用的接口,這就是Socket編程接口。
套接字是網絡通信過程中端點的抽象表示,包含進行網絡通信必需的五種信息:連接使用的協議,本地主機的IP地址,本地進程的協議端口,遠地主機的IP地址,遠地進程的協議端口。
socket = IP address + TCP/UDP + port。
協議棧
操作系統中的網絡控制軟件也就是協議棧,網絡硬件是網卡。
套接字與協議棧之間的關系
套接字中記錄了用于控制通信操作的各種控制信息,協議棧則需要根據這些信息判斷下一步的行動,這就是套接字的作用。
協議棧是根據套接字中記錄的控制信息來工作的。
網絡協議
| 應用層(Application) | HTTP、FTP、TFTP、SMTP、NFS | |
| 表示層(Presentation) | 應用層 | |
| 會話層(Session) | SMTP、DNS | |
| 傳輸層(Transport) | 傳輸層 | TCP、UDP |
| 網絡層(Network) | 網絡層 | IP、ARP、ICMP |
| 數據鏈路層(Data Link) | 數據鏈路層 | |
| 物理層(Physical) | 物理層 |
3.2、連接服務器
#include <sys/socket.h> int connect(int sockfd, const struct sockaddr* servaddr, socklen_t addrlen); // 返回:成功為0,出錯-1應用程序通過調用 Socket庫中的名為 connect的程序組件來完成這一操作。
第一個參數:即描述符,connect會將應用程序指定的描述符告知協議棧,然后協議棧根據這個描述符來判斷到底使用哪一個套接字去和服務器端的套接字進行連接,并執行連接的操作
第二個參數,即服務器 IP地址,就是通過 DNS服務器查詢得到的我們要訪問的服務器的 IP地址。
第三個參數,即端口號,IP地址是為了區分網絡中的各個計算機而分配的數值。因此,只要知道了 IP地址,我們就可以識別出網絡上的某臺計算機。但是,連接操作的對象是某個具體的套接字,因此必須要識別到具體的套接字才行,而僅憑IP地址是無法做到這一點的。
如果說描述符是用來在一臺計算機內部識別套接字的機制,那么端口號就是用來讓通信的另一方能夠識別出套接字的機制。
服務器上所使用的端口號是根據應用的種類事先規定好的,僅此而已。
Web是 80號端口,電子郵件是 25號端口 65
問題:我們知道了服務器的端口號,但是服務器不知道客戶端的端口號?
既然確定連接對象的套接字需要使用端口號,那么服務器也得知道客戶端的套接字號碼才行吧,這個問題是怎么解決的呢?
事情是這樣的,首先,客戶端在創建套接字時,協議棧會為這個套接字隨便分配一個端口號。接下來,當協議棧執行連接操作時,會將這個隨便分配的端口號通知給服務器。
連接服務器本質
連接實際上是通信雙方交換控制信息
控制信息
通信操作中使用的控制信息分為兩類。
(1)頭部中記錄的信息
(2)套接字(協議棧中的內存空間)中記錄的信息
控制信息一:頭部中記錄的信息
他們是客戶端和服務器相互聯絡時交換的控制信息。這些字段是固定的,在連接、收發、斷開等各個階段中,每次客戶端和服務器之間進行通信時,都需要提供這些控制信息。具體來說,這些信息會被添加在客戶端與服務器之間傳遞的網絡包的開頭。在連接階段,由于數據收發還沒有開始,網絡包中沒有實際的數據,只有控制信息。這些控制信息位于網絡包的開頭,因此被稱為頭部。此外,以太網和IP協議也有自己的控制信息,這些信息也叫 頭部,為了避免各種不同的頭部發生混淆,我們一般會記作 TCP頭部、以太網頭部、 IP頭部。
控制信息二:套接字(協議棧中的內存空間)中記錄的信息
那就是保存在套接字中,用來控制協議棧操作的信息。應用程序傳遞來的信息以及從通信對象接收到的信息都會保存在這里,還有收發數據操作的執行狀態等信息也會保存在這里,協議棧會根據這些信息來執行每一步的操作。
3.2.1、連接操作的實際過程
這個過程是從應用程序調用 Socket庫的connect開始的(看上圖『整體流程一覽圖』中②)。 >
connect(<描述符>,<服務器IP地址和端口號>, …)
連接操作的第一步是在 TCP模塊處創建表示連接控制信息的頭部。
通過 TCP頭部中的發送方和接收方端口號可以找到要連接的套接字。
TCP建立連接要進行“三次握手”
- 客戶端向服務器發送一個SYN J
- 服務器向客戶端響應一個SYN K,并對SYN J進行確認ACK J+1
- 客戶端再向服務器發一個確認ACK K+1
從圖中可以看出,當客戶端調用connect時,觸發了連接請求,向服務器發送了SYN J包,這時connect進入阻塞狀態;服務器監聽到連接請求,即收到SYN J包,調用accept函數接收請求向客戶端發送SYN K ,ACK J+1,這時accept進入阻塞狀態;客戶端收到服務器的SYN K ,ACK J+1之后,這時connect返回,并對SYN K進行確認;服務器收到ACK K+1時,accept返回,至此三次握手完畢,連接建立。
建立連接之后,協議棧的連接操作就結束了,也就是說 connect已經執行完畢,控制流程被交回到應用程序。
3.3、收發數據
3.3.1、將HTTP請求消息交給協議棧
接下來就進入數據收發階段了。數據收發操作是從應用程序調用 write將要發送的數據交給協議棧開始的(看上圖『整體流程一覽圖』中③),協議棧收到數據后執行發送操作。
MTU/MSS
MTU: Maximum Transmission Unit,最大傳輸單元。一個網絡包的最大長度,以太網中一般為 1500字節。
MSS: Maximum Segment Size,最大分段大小。除去頭部之后,一個網絡包所能容納的 TCP數據的最大長度。TCP和 IP的頭部加起來一般是 40字節,因此 MTU減去這個長度就是 MSS。例如,在以太網中, MTU為 1500,因此 MSS就是 1460。 TCP/ IP可以使用一些可選參數( protocol option),如加密等,這時頭部的長度會增加,那么 MSS就會隨著頭部長度增加而相應縮短。
3.3.2、對較大數據進行拆分
應用程序的數據一般都比較大,因此 TCP會按照網絡包的大小對數據進行拆分。
3.3.3、TCP通過ACK號確保網絡包是否收到
通過“序號”和“ ACK號”可以確認接收方是否收到了網絡包。
3.3.4、接受HTTP響應消息
首先,瀏覽器在委托協議棧發送請求消息之后,會調用read程序(看上圖『整體流程一覽圖』中④)來獲取響應消息。然后,控制流程會通過read轉移到協議棧,然后協議棧會執行接下來
的操作。和發送數據一樣,接收數據也需要將數據暫存到接收緩沖區中,這里的操作過程如下。首先,協議棧嘗試從接收緩沖區中取出數據并傳遞給應用程序,但這個時候請求消息剛剛發送出去,響應消息可能還沒返回。響應消息的返回還需要等待一段時間,因此這時接收緩沖區中并沒有數據,那么接收數據的操作也就無法繼續。這時,協議棧會將應用程序的委托,也就是從接收緩沖區中取出數據并傳遞給應用程序的工作暫時掛起,等服務器返回的響應消息到達之后再繼續執行接收操作。
協議棧會檢查收到的數據塊和 TCP頭部的內容,判斷是否有數據丟失,如果沒有問題則返回 ACK號。然后,協議棧將數據塊暫存到接收緩沖區中,并將數據塊按順序連接起來還原出原始的數據,最后將數據交給應用程序。具體來說,協議棧會將接收到的數據復制到應用程序指定的內存地址中,然后將控制流程交回應用程序。將數據交給應用程序之后,協議棧還需要找到合適的時機向發送方發送窗口更新。
3.4、斷開連接,并刪除套接字
3.4.1、從服務器端斷開連接
這里我們以服務器一方發起斷開過程為例來進行講解。
首先,服務器一方的應用程序會調用Socket庫的close程序。然后,服務器的協議棧會生成包含斷開信息的 TCP頭部,具體來說就是將控制位中的 FIN比特設為 1。接下來,協議棧會委托 IP模塊向客戶端發送數據。同時,服務器的套接字中也會記錄下斷開操作的相關信息。
3.4.2、從客戶端斷開連接
- 應用進程首先調用close主動關閉連接,這時TCP發送一個FIN M;
- 另一端接收到FIN M之后,執行被動關閉,對這個FIN進行確認。它的接收也作為文件結束符傳遞給應用進程,因為FIN的接收意味著應用進程在相應的連接上再也接收不到額外數據;
- 一段時間之后,接收到文件結束符的應用進程調用close關閉它的socket。這導致它的TCP也發送一個FIN N;
- 接收到這個FIN的源發送端TCP對它進行確認。
3.4.3、刪除套接字
和服務器的通信結束之后,用來通信的套接字也就不會再使用了,這時我們就可以刪除這個套接字了。不過,套接字并不會立即被刪除,而是會等待一段時間之后再被刪除。等待這段時間是為了防止誤操作。
誤操作舉例:如果最后客戶端返回的 ACK號丟失了,結果會如何呢?這時,服務器沒有接收到 ACK號,可能會重發一次 FIN。如果這時客戶端的套接字已經刪除了,會發生什么事呢?套接字被刪除,那么套接字中保存的控制信息也就跟著消失了,套接字對應的端口號就會被釋放出來。這時,如果別的應用程序要創建套接字,新套接字碰巧又被分配了同一個端口號,而服務器重發的 FIN正好到達,會怎么樣呢?本來這個 FIN是要發給剛剛刪除的那個套接字的,但新套接字具有相同的端口號,于是這個 FIN就會錯誤地跑到新套接字里面,新套接字就開始執行斷開操作了。之所以不馬上刪除套接字,就是為了防止這樣的誤操作。
TCP整個流程一覽
四、IP與以太網的包收發操作
4.1、包的基本知識
TCP模塊在執行連接、收發、斷開等各階段操作時,都需要委托 IP模塊將數據封裝成包發送給通信對象。我們在 TCP的講解中也經常提到 IP,下面就來討論一下 IP模塊是如何將包發送給對方的。
正式開始這個話題之前,我們先來介紹一下關于網絡包的一些基本知識。首先,包是由頭部和數據兩部分構成的(下圖(a))。頭部包含目的地址等控制信息,大家可以把它理解為快遞包裹的面單;頭部后面就是委托方要發送給對方的數據,也就相當于快遞包裹里的貨物。一個包發往目的地的過程如圖 2. 15所示。
4.2、IP模塊的作用
4.2.1、發送包的時候,IP模塊工作
收到委托后, IP模塊會將包的內容當作一整塊數據,在前面加上包含控制信息的頭部。
IP模塊負責添加如下兩個頭部:
(1)IP頭部: IP用的頭部,包含 IP地址。IP頭部中包含 IP協議規定的、根據 IP地址將包發往目的地所需的控制信息;
(2)MAC頭部:以太網用的頭部,包含 MAC地址。MAC頭部包含通過以太網的局域網將包傳輸至最近的路由器所需的控制信息。
總之,加上這兩個頭部之后,一個包就封裝好了,這些就是 IP模塊負責的工作。
4.2.2、接收包的時候,IP模塊工作
返回的包也會通過轉發設備發送回來,然后我們需要接收這個包。接收的過程和發送的過程是相反的,信息先以電信號的形式從網線傳輸進來,然后由網卡將其轉換為數字信息并傳遞給 IP模塊(下圖中的“ ③接收”)。接下來, IP模塊會將 MAC頭部和 IP頭部后面的內容,也就是 TCP頭部加上數據塊,傳遞給 TCP模塊。接下來的操作就是我們之前講過的 TCP模塊負責的部分了。
4.3、生成包含接收方IP地址的IP頭部
IP頭部的“接收方 IP地址”填寫通信對象的 IP地址。
發送方 IP地址需要判斷發送所使用的網卡,并填寫該網卡的 IP地址。
問題來了:一臺計算機多個網卡,如何設置發送方IP地址?
很多服務器上都會安裝多塊網卡,這時一臺計算機就有多個 IP地址,在填寫發送方 IP地址時就需要判斷到底應該填寫哪個地址。這個判斷相當于在多塊網卡中判斷應該使用哪一塊網卡來發送這個包,也就相當于判斷應該把包發往哪個路由器,因此只要確定了目標路由器,也就確定了應該使用哪塊網卡,也就確定了發送方的 IP地址。
那么,我們應該如何判斷應該把包交給哪塊網卡呢?其實和路由器使用 IP表(也叫路由表)判斷下一個路由器位置的操作是一樣的。因為協議棧的 IP模塊與路由器中負責包收發的部分都是根據 IP協議規則來進行包收發操作的,所以它們也都用相同的方法來判斷把包發送給誰。
(路由器收發下一章節具體說)
查看Windows本機的路由表Route Table
4.4、生成以太網用的MAC頭部
發送方 MAC地址
發送方 MAC地址,這里填寫網卡本身的 MAC地址。 MAC地址是在網卡生產時寫入 ROM里的,只要將這個值讀取出來寫入 MAC頭部就可以了。對于多塊網卡的情況,請大家回想一下設置發送方 IP地址的方法 。設置發送方 IP地址時,我們已經判斷出了從哪塊網卡發送這個包,那么現在只要將這塊網卡對應的 MAC地址填進去就好了。
接收方MAC地址
只要告訴以太網對方的 MAC的地址,以太網就會幫我們把包發送過去,那么很顯然這里應該填寫對方的 MAC地址。然而,在這個時間點上,我們還沒有把包發送出去,所以先得搞清楚應該把包發給誰,這個只要查一下路由表就知道了。在路由表中找到相匹配的條目,然后把包發給 Gateway列中的 IP地址就可以了。既然已經知道了包應該發給誰,那么只要將對方的 MAC地址填上去就好了,但到這里為止根本沒有出現對方的 MAC地址,也就是說我們現在根本不知道對方的 MAC地址是什么。因此,我們還需要執行根據 IP地址查詢 MAC地址的操作。詳情看 4.4.1、通過 ARP查詢目標路由器的 MAC地址
IP模塊根據路由表 Gateway欄的內容判斷應該把包發送給誰。
4.4.1、通過 ARP查詢目標路由器的 MAC地址
這里我們需要使用 ARP協議(網絡層協議),它其實非常簡單。在以太網中,有一種叫作廣播的方法,可以把包發給連接在同一以太網中的所有設備。 ARP就是利用廣播對所有設備提問:“ × ×這個 IP地址是誰的?請把你的 MAC地址告訴我。”然后就會有人回答:“這個 IP地址是我的,我的 MAC地址是 × × × ×。” (下圖)
ARP: Address Resolution Protocol,地址解析協議。
通過ARP緩存提升效率,避免每次發送
Windows查看ARP緩存
MAC地址
MAC: Media Access Control的縮寫。 MAC頭部、 MAC地址中的 MAC也是這個意思。也就是說,通過 MAC模塊控制包收發操作時所使用的頭部和地址就叫作 MAC頭部和 MAC地址。
4.5、網卡-將IP包轉換成電或光信號發送出去
IP生成的網絡包只是存放在內存中的一串數字信息,沒有辦法直接發送給對方。因此,我們需要將數字信息轉換為電或光信號,才能在網線上傳輸,也就是說,這才是真正的數據發送過程。負責執行這一操作的是網卡,但網卡也無法單獨工作,要控制網卡還需要網卡驅動程序。驅動程序不只有網卡才有,鍵盤、鼠標、顯卡、聲卡等各種硬件設備都有。當然,不同廠商和型號的網卡在結構上有所不同,因此網卡驅動程序也是廠商開發的專用程序。
網卡的 ROM中保存著全世界唯一的 MAC地址,這是在生產網卡時寫入的。
網卡是如何將包轉換成電信號并發送到網線中的
網卡驅動從 IP模塊獲取包之后,會將其復制到網卡內的緩沖區中,然后向 MAC模塊發送發送包的命令。接下來就輪到 MAC模塊進行工作了。首先, MAC模塊會將包從緩沖區中取出,并在開頭加上報頭和起始幀分界符,在末尾加上用于檢測錯誤的幀校驗序列
給網絡包再加 3個控制數據
網卡MAC模塊將包從緩沖區中取出,并在開頭加上 報頭 和 起始幀分界符,在末尾加上用于檢測錯誤的 幀校驗序列。
4.5.1、報頭
報頭作用
報頭是一串像 10101010…這樣 1和 0交替出現的比特序列,長度為 56比特,它的作用是確定包的讀取時機。當這些 1010的比特序列被轉換成電信號后,會形成如圖這樣的波形。接收方在收到信號時,遇到這樣的波形就可以判斷讀取數據的時機。
如何通過電信號來讀取數據
用電信號來表達數字信息時,我們需要讓 0和 1兩種比特分別對應特定的電壓和電流,例如下圖( a)這樣的電信號就可以表達數字信息。通過電信號來讀取數據的過程就是將這種對應關系顛倒過來。也就是說,通過測量信號中的電壓和電流變化,還原出 0和 1兩種比特的值。然而,實際的信號并不像下圖所示的那樣有分隔每個比特的輔助線,因此在測量電壓和電流時必須先判斷出每個比特的界限在哪里。但是,像下圖( a)右邊這種 1和 0連續出現的信號,由于電壓和電流沒有變化,我們就沒辦法判斷出其中每個比特到底應該從哪里去切分。
通過時鐘測量讀取信號的時機
如何判斷出其中每個比特到底應該從哪里去切分?
要解決這個問題,最簡單的方法就是在數據信號之外再發送一組用來區分比特間隔的時鐘信號。如圖( b)所示,當時鐘信號從下往上變化時讀取電壓和電流的值,然后和 0或 1進行對應就可以了。但是這種方法存在問題。當距離較遠,網線較長時,兩條線路的長度會發生差異,數據信號和時鐘信號的傳輸會產生時間差,時鐘就會發生偏移。
數據信號和時鐘信號的傳輸會產生時間差,時鐘就會發生偏移。
另外一種方法是當時鐘信號從上往下變化時進行讀取。要解決這個問題,可以采用將數據信號和時鐘信號疊加在一起的方法。這樣的信號如圖( c)所示,發送方將這樣的信號發給接收方。由于時鐘信號是像圖( b)這樣按固定頻率進行變化的,只要能夠找到這個變化的周期,就可以從接收到的信號( c)中提取出時鐘信號( b),進而通過接收信號( c)和時鐘信號( b)計算出數據信號( a),這和發送方將數據信號和時鐘信號進行疊加的過程正好相反。然后,只要根據時鐘信號( b)的變化周期,我們就可以從數據信號( a)中讀取相應的電壓和電流值,并將其還原為 0或 1的比特了。
4.5.2、起始幀分界符
起始幀分界符,它的末尾比特排列有少許變化。接收方以這一變化作為標記,從這里開始提取網絡包數據。也就是說,起始幀分界符是一個用來表示包起始位置的標記。
4.5.3、幀校驗序列
末尾的 FCS(幀校驗序列)用來檢查包傳輸過程中因噪聲導致的波形紊亂、數據錯誤,它是一串 32比特的序列,是通過一個公式對包中從頭到尾的所有內容進行計算而得出來的。具體的計算公式在此省略,它和磁盤等設備中使用的 CRC錯誤校驗碼是同一種東西,當原始數據中某一個比特發生變化時,計算出來的結果就會發生變化。在包傳輸過程中,如果受到噪聲的干擾而導致其中的數據發生了變化,那么接收方計算出的 FCS和發送方計算出的 FCS就會不同,這樣我們就可以判斷出數據有沒有錯誤。
4.5.4、向集線器發送網絡包
網卡的 MAC模塊生成通用信號,然后由 PHY( MAU)模塊轉換成可在網線中傳輸的格式,并通過網線發送出去。
4.6、接收返回包
網卡接收網絡包
接收操作的第一步就是不管三七二十一把這些信號全都收進來再說。信號的開頭是報頭,通過報頭的波形同步時鐘,然后遇到起始幀分界符時開始將后面的信號轉換成數字信息。這個操作和發送時是相反的,即 PHY( MAU)模塊先開始工作,然后再輪到 MAC模塊。首先, PHY( MAU)模塊會將信號轉換成通用格式并發送給 MAC模塊, MAC模塊再從頭開始將信號轉換為數字信息,并存放到緩沖區中。當到達信號的末尾時,還需要檢查 FCS。具體來說,就是將從包開頭到結尾的所有比特套用到公式中計算出 FCS,然后和包末尾的 FCS進行對比,正常情況下兩者應該是一致的,如果中途受到噪聲干擾而導致波形發生紊亂,則兩者的值會產生差異,這時這個包就會被當作錯誤包而被丟棄。如果 FCS校驗沒有問題,接下來就要看一下 MAC頭部中接收方 MAC地址與網卡在初始化時分配給自己的 MAC地址是否一致,以判斷這個包是不是發給自己的。我們沒必要去接收發給別人的包,因此如果不是自己的包就直接丟棄,如果接收方 MAC地址和自己 MAC地址一致,則將包放入緩沖區中 。到這里, MAC模塊的工作就完成了,接下來網卡會通知計算機收到了一個包。
網卡中斷計算機,網卡驅動從網卡緩存中讀取數據
通知計算機的操作會使用一個叫作中斷的機制。在網卡執行接收包的操作的過程中,計算機并不是一直監控著網卡的活動,而是去繼續執行其他的任務。因此,如果網卡不通知計算機,計算機是不知道包已經收到了這件事的。網卡驅動也是在計算機中運行的一個程序,因此它也不知道包到達的狀態。在這種情況下,我們需要一種機制能夠打斷計算機正在執行的任務,讓計算機注意到網卡中發生的事情,這種機制就是中斷。具體來說,中斷的工作過程是這樣的。首先,網卡向擴展總線中的中斷信號線發送信號,該信號線通過計算機中的中斷控制器連接到 CPU。當產生中斷信號時, CPU會暫時掛起正在處理的任務,切換到操作系統中的中斷處理程序 。然后,中斷處理程序會調用網卡驅動,控制網卡執行相應的接收操作。
網卡驅動被中斷處理程序調用后,會從網卡的緩沖區中取出收到的包,并通過 MAC頭部中的以太類型字段判斷協議的類型。現在我們在大多數情況下都是使用 TCP/ IP協議,但除了 TCP/ IP之外還有很多其他類型的協議,例如 NetWare中使用的 IPX/ SPX,以及 Mac電腦中使用的 AppleTalk等協議。這些協議都被分配了不同的以太類型,如 0080(十六進制)代表 IP協議,網卡驅動就會把這樣的包交給 TCP/ IP協議棧;如果是 809B則表示 AppleTalk協議,就把包交給 AppleTalk協議棧,以此類推。
4.7、將服務器的響應包從 IP傳遞給 TCP
下面我們假設 Web服務器返回了一個網絡包,那么協議棧會進行哪些處理呢 100?服務器返回的包的以太類型應該是 0800,因此網卡驅動會將其交給 TCP/ IP協議棧來進行處理。接下來就輪到 IP模塊先開始工作了,第一步是檢查 IP頭部,確認格式是否正確。如果格式沒有問題,下一步就是查看接收方 IP地址。如果接收網絡包的設備是一臺 Windows客戶端計算機,那么服務器返回的包的接收方 IP地址應該與客戶端網卡的地址一致,檢查確認之后我們就可以接收這個包了。
IP模塊檢查IP頭部,如果接收方 IP地址不是自己的地址,通過ICMP反饋回去
如果接收方 IP地址不是自己的地址,那一定是發生了什么錯誤。客戶端計算機不負責對包進行轉發,因此不應該收到不是發給自己的包 101。當發生這樣的錯誤時, IP模塊會通過 ICMP消息將錯誤告知發送方(圖 2. 1)。 ICMP規定了各種類型的消息,如表所示。當我們遇到這個錯誤時, IP模塊會通過表中的 Destination unreachable消息通知對方。從這張表的內容中我們可以看到在包的接收和轉發過程中能夠遇到的各種錯誤,因此希望大家看一看這張表。
IP模塊檢查IP頭部,如果接收方 IP地址是自己的地址,進行分片重組
如果接收方 IP地址正確,則這個包會被接收下來,這時還需要完成另一項工作。 IP協議有一個叫作分片的功能。簡單來說,網線和局域網中只能傳輸小包,因此需要將大的包切分成多個小包。如果接收到的包是經過分片的,那么 IP模塊會將它們還原成原始的包。分片的包會在 IP頭部的標志字段中進行標記,當收到分片的包時, IP模塊會將其暫存在內部的內存空間中,然后等待 IP頭部中具有相同 ID的包全部到達,這是因為同一個包的所有分片都具有相同的 ID。此外, IP頭部還有一個分片偏移量( fragment offset)字段,它表示當前分片在整個包中所處的位置。根據這些信息,在所有分片全部收到之后,就可以將它們還原成原始的包,這個操作叫作分片重組。
TCP模塊接收包
接下來包會被交給 TCP模塊。 TCP模塊會根據 IP頭部中的接收方和發送方 IP地址,以及 TCP頭部中的接收方和發送方端口號來查找對應的套接字。找到對應的套接字之后,就可以根據套接字中記錄的通信狀態,執行相應的操作了。例如,如果包的內容是應用程序數據,則返回確認接收的包,并將數據放入緩沖區,等待應用程序
五、集線器、交換機、路由器
(1)路由器根據目標地址判斷下一個路由器的位置
(2)集線器在子網中將網絡包傳輸到下一個路由
實際上,集線器是按照以太網規則傳輸包的設備,而路由器是按照 IP規則傳輸包的設備,因此我們也可以作如下理解。
(1)IP協議根據目標地址判斷下一個 IP轉發設備的位置
(2)子網中的以太網協議將包傳輸到下一個轉發設備
場景設定:網絡包在進入互聯網之前經歷的傳輸過程。這里我們假設客戶端計算機連接的局域網結構是像下圖這樣的。也就是說,網絡包從客戶端計算機發出之后,要經過集線器、交換機和路由器最終進入互聯網。實際上,我們家里用的路由器已經集成了集線器和交換機的功能,像圖上這樣使用獨立設備的情況很少見。
5.1、信號在網線中傳播
網卡 -> 網線 -> 集線器
從信號流出網卡進入網線開始。網卡中的 PHY( MAU) 2模塊負責將包轉換成電信號,信號通過 RJ-45接口進入雙絞線,這部分的放大圖如下圖的右側部分所示。以太網信號的本質是正負變化的電壓,大家可以認為網卡的 PHY( MAU)模塊就是一個從正負兩個信號端子輸出信號的電路。
網卡與集線器用雙絞線連接的形態
問題來了:信號衰減
信號在網線的傳輸過程中,能量會逐漸損失。網線越長,信號衰減就越嚴重。集線器收到的信號有時會出現衰減。如下圖。
“雙絞”是為了抑制噪聲
局域網網線使用的是雙絞線,其中“雙絞”的意思就是以兩根信號線為一組纏繞在一起,這種擰麻花一樣的設計是為了抑制噪聲的影響。
噪聲是如何產生的
首先,我們來看看噪聲是如何產生的。產生噪聲的原因是網線周圍的電磁波,當電磁波接觸到金屬等導體時,在其中就會產生電流。因此,如果網線周圍存在電磁波,就會在網線中產生和原本的信號不同的電流。由于信號本身也是一種帶有電壓變化的電流,其本質和噪聲產生的電流是一樣的,所以信號和噪聲的電流就會混雜在一起,導致信號的波形發生失真,這就是噪聲的影響。
電磁波來源有兩種:外部和內部
影響網線的電磁波分為兩種:
一種是由電機、熒光燈、 CRT顯示器等設備泄漏出來的電磁波,這種電磁波來自網線之外的其他設備,
另一種電磁波是從網線中相鄰的信號線泄漏出來的。由于傳輸的信號本身就是一種電流,當電流流過時就會向周圍發出電磁波,這些電磁波對于其他信號線來說就成了噪聲。這種內部產生的噪聲稱為串擾( crosstalk)。
雙絞線對噪聲的抑制
a)通過兩根信號線的纏繞抵消外源性噪聲;
b)通過改變節距抑制內源性噪聲。
5.2、集線器將信號發往所有設備
集線器的作用?
集線器將信號發送給所有連接在它上面的線路。
信號到達集線器的 PHY( MAU)模塊后,會進入中繼電路。中繼電路的基本功能就是將輸入的信號廣播到集線器的所有端口上。當然,也有一些產品具有信號整形、錯誤抑制等功能,但基本上就是將輸入的信號原封不動地輸出到網線接口。接下來,信號從所有接口流出,到達連接在集線器上的所有設備。然后,這些設備在收到信號之后會通過 MAC頭部中的接收方 MAC地址判斷是不是發給自己的,如果是發給自己的就接受,否則就忽略。這樣,網絡包就能夠到達指定 MAC地址的接收方了。
由于集線器只是原封不動地將信號廣播出去,所以即便信號受到噪聲的干擾發生了失真,也會原樣發送到目的地。這時,接收信號的設備,也就是交換機、路由器、服務器等,會在將信號轉換成數字信息后通過 FCS8校驗發現錯誤,并將出錯的包丟棄。當然,丟棄包并不會影響數據的傳輸,因為丟棄的包不會觸發確認響應。因此協議棧的 TCP模塊會檢測到丟包,并對該包進行重傳。
5.3、交換機的包轉發操作
交換機(Switch)意為“開關”是一種用于電(光)信號轉發的網絡設備。它可以為接入交換機的任意兩個網絡節點提供獨享的電信號通路。最常見的交換機是以太網交換機。其他常見的還有電話語音交換機、光纖交換機等
5.4、路由器的包轉發操作
5.4.1、路由器內部結構
大家只要看明白路由器包括轉發模塊和端口模塊兩部分就可以了。其中轉發模塊負責判斷包的轉發目的地,端口模塊負責包的收發操作。換句話說,路由器轉發模塊和端口模塊的關系,就相當于協議棧的 IP模塊和網卡之間的關系。
路由器內部結構
路由器的各個端口都具有 MAC地址和 IP地址。
5.4.2、路由器的工作原理
路由器在轉發包時,首先會通過端口將發過來的包接收進來,這一步的工作過程取決于端口對應的通信技術。對于以太網端口來說,就是按照以太網規范進行工作,而無線局域網端口則按照無線局域網的規范工作,總之就是委托端口的硬件將包接收進來。接下來,轉發模塊會根據接收到的包的 IP頭部中記錄的接收方 IP地址,在路由表中進行查詢,以此判斷轉發目標。然后,轉發模塊將包轉移到轉發目標對應的端口,端口再按照硬件的規則將包發送出去,也就是轉發模塊委托端口模塊將包發送出去的意思。
5.4.3、路由器根據路由表對包進行轉發
交換機是通過 MAC頭部中的接收方 MAC地址來判斷轉發目標的,而路由器則是根據 IP頭部中的 IP地址來判斷的。
交換機在地址表中只匹配完全一致的記錄,而 路由器則會忽略主機號部分,只匹配網絡號部分。打個比方,路由器在轉發包的時候只看接收方地址屬于哪個區, × ×區發往這一邊, × ×區發往那一邊。
5.4.4、路由器的包接收操作
路由器的整個工作過程。首先,路由器會接收網絡包。路由器的端口有各種不同的類型,這里我們只介紹以太網端口是如何接收包的。以太網端口的結構和計算機的網卡基本相同,接收包并存放到緩沖區中的過程也和網卡幾乎沒有區別。首先,信號到達網線接口部分,其中的 PHY( MAU)模塊和 MAC模塊將信號轉換為數字信息,然后通過包末尾的 FCS進行錯誤校驗,如果沒問題則檢查 MAC頭部中的接收方 MAC地址,看看是不是發給自己的包,如果是就放到接收緩沖區中,否則就丟棄這個包。如果包的接收方 MAC地址不是自己,說明這個包是發給其他設備的,如果接收這個包就違反了以太網的規則。
路由器的端口都具有 MAC地址,只接收與自身地址匹配的包,遇到不匹配的包則直接丟棄。
5.4.5、查詢路由表確定輸出端口
MAC頭部作用
完成包接收操作之后,路由器就會丟棄包開頭的 MAC頭部。 MAC頭部的作用就是將包送達路由器,其中的接收方 MAC地址就是路由器端口的 MAC地址。因此,當包到達路由器之后, MAC頭部的任務就完成了,于是 MAC頭部就會被丟棄。
通過路由器轉發的網絡包,其接收方 MAC地址為路由器端口的 MAC地址。
路由器會根據 IP頭部中的內容進行包的轉發操作
- a)查詢路由表判斷轉發目標
關于具體的工作過程,我們還是來看一個實際的例子,如上圖的情況,假設地址為 10. 10. 1. 101的計算機要向地址為 192. 168. 1. 10的服務器發送一個包,這個包先到達圖中的路由器。判斷轉發目標的第一步,就是根據包的接收方 IP地址查詢路由表中的目標地址欄,以找到相匹配的記錄。就像前面講過的一樣,這個匹配并不是匹配全部 32個比特,而是根據子網掩碼列中的值判斷網絡號的比特數,并匹配相應數量的比特 33。例如,上圖的第 3行,子網掩碼列為 255. 255. 255. 0,就表示需要匹配從左起 24個比特。網絡包的接收方 IP地址和路由表中的目標地址左起 24個比特的內容都是 192. 168. 1,因此兩者是匹配的,該行記錄就是候選轉發目標之一。
- b)路由器修改包的有效期
- c)路由器通過分片功能拆分大網絡包
- d)路由器的發送操作
這一步操作取決于輸出端口的類型。如果是以太網端口,則按照以太網的規則將包轉換為電信號發送出去;如果是 ADSL則按照 ADSL的規則來轉換,以此類推。在家庭網絡中,路由器后面一般連接 ADSL等線路接入互聯網,因此路由器會根據接入網的規則來發送包。不過,要理解具體的操作過程,需要先理解相應的通信線路 ,比較復雜,因此我們留到下一章探索互聯網內部時再講解。這里,我們假設路由器位于公司等局域網的內部,即輸出端口也是以太網,看看這種情況是如何操作的。
以太網的包發送操作是根據以太網規則來進行的,即便設備種類不同,規則也是相同的。也就是說,其基本過程和協議棧中的 IP模塊發送包的過程是相同的,即在包前面加上 MAC頭部,
設置其中的一些字段,然后將完成的包轉換成電信號并發送出去。下面來簡單復習一下這個過程。首先,為了判斷 MAC頭部中的 MAC地址應該填寫什么值,我們需要根據路由表的網關列判斷對方的地址。如果網關是一個 IP地址,則這個 IP地址就是我們要轉發到的目標地址;如果網關為空,則 IP頭部中的接收方 IP地址就是要轉發到的目標地址。知道對方的 IP地址之后,接下來需要通過 ARP根據 IP地址查詢 MAC地址,并將查詢的結果作為接收方 MAC地址。路由器也有 ARP緩存,因此首先會在 ARP緩存中查詢,如果找不到則發送 ARP查詢請求。
路由器判斷下一個轉發目標的方法如下。
如果路由表的網關列內容為 IP地址,則該地址就是下一個轉發目標。
如果路由表的網關列內容為空,則 IP頭部中的接收方 IP地址就是下一個轉發目標。
路由器也會使用 ARP來查詢下一個轉發目標的 MAC地址。
網絡包完成后,接下來會將其轉換成電信號并通過端口發送出去。這一步的工作過程和計算機也是相同的。例如,當以太網工作在半雙工模式時,需要先確認線路中沒有其他信號后才能發送,如果檢測到碰撞,則需要等待一段時間后重發。如果以太網工作在全雙工模式,則不需要確認線路中的信號,可以直接發送。如果輸出端口為以太網,則發送出去的網絡包會通過交換機到達下一個路由器。由于接收方 MAC地址就是下一個路由器的地址,所以交換機會根據這一地址將包傳輸到下一個路由器。接下來,下一個路由器會將包轉發給再下一個路由器,經過層層轉發之后,網絡包就到達了最終的目的地。
5.5、路由器與交換機的關系
IP協議本身沒有傳輸包的功能,因此包的實際傳輸要委托以太網來進行。
路由器是基于 IP設計的,而交換機是基于以太網設計的,因此 IP與以太網的關系也就是路由器與交換機的關系。換句話說,路由器將包的傳輸工作委托給交換機來進行
IP(路由器)負責將包送達通信對象這一整體過程,而其中將包傳輸到下一個路由器的過程則是由以太網(交換機)來負責的。
六、服務器端的局域網中有什么玄機
6.1、防火墻
防火墻的基本思路
防火墻的基本思路,即只允許發往特定服務器中的特定應用程序的包通過,然后屏蔽其他的包。
主流的是包過濾方式的防火墻
包過濾方式的防火墻可根據接收方 IP地址、發送方 IP地址、接收方端口號、發送方端口號、控制位等信息來判斷是否允許某個包通過。
防火墻的不足
防火墻無法抵御的攻擊
防火墻可以根據包的起點和終點來判斷是否允許其通過,但僅憑起點和終點并不能篩選出所有有風險的包。
比如,假設 Web服務器在收到含有特定數據的包時會引起宕機。但是防火墻只關心包的起點和終點,因此即便包中含有特定數據,防火墻也無法發現,于是包就被放行了。然后,當包到達 Web服務器時,就會引發服務器宕機。通過這個例子大家可以看出,只有檢查包的內容才能識別這種風險,因此防火墻對這種情況無能為力。
對防火墻無法抵御攻擊的應對方法
a)方法一:這個問題的根源在于 Web服務器程序的 Bug,因此修復 Bug防止宕機就是其中一種方法。這類 Bug中,危險性較高的會作為安全漏洞公布出來,開發者會很快發布修復了 Bug的新版本,因此持續關注安全漏洞信息并更新軟件的版本是非常重要的。
b)另一種方法就是在防火墻之外部署用來檢查包的內容并阻止有害包的設備或軟件。
6.2、負載均衡
6.2.1、多臺服務器 – 分布式架構
使用多臺服務器來分擔負載的方法更有效。這種架構統稱為分布式架構。
DNS輪詢分配服務器IP地址
最簡單的一種是通過 DNS服務器來分配。當訪問服務器時,客戶端需要先向 DNS服務器查詢服務器的 IP地址,如果在 DNS服務器中填寫多個名稱相同的記錄,則每次查詢時 DNS服務器都會按順序返回不同的 IP地址。
DNS輪詢不足之處
例如:假如多臺 Web服務器中有一臺出現了故障,這時我們希望在返回 IP地址時能夠跳過故障的 Web服務器,然而普通的 DNS服務器并不能確認 Web服務器是否正常工作,因此即便 Web服務器宕機了,它依然可能會返回這臺服務器的 IP地址。
使用負載均衡器分配訪問
6.2.2、緩存服務器
臨時保存內容并代替 Web服務器返回內容的緩存服務器
緩存服務器三種部署
6.3、內容分發服務
根據緩存服務器分布第三種方式,進行布局。
七、請求到達Web服務器,響應返回瀏覽器
7.1、服務器概覽
7.2、服務器的接收操作
7.2.1、 網卡將接收到的信號轉換成數字信息
服務器將接收到的電信號還原數字信息
根據信號還原的數字信息
網卡的 MAC模塊將網絡包從信號還原為數字信息,校驗 FCS并存入緩沖區。
在這個過程中,服務器的 CPU并不是一直在監控網絡包的到達,而是在執行其他的任務,因此 CPU并不知道此時網絡包已經到達了。但接下來的接收操作需要 CPU來參與,因此網卡需要通過 中斷 將網絡包到達的事件通知給 CPU。接下來, CPU就會暫停當前的工作,并切換到網卡的任務。然后,網卡驅動會開始運行,從網卡緩沖區中將接收到的包讀取出來,根據 MAC頭部的以太類型字段判斷協議的種類,并調用負責處理該協議的軟件。這里,以太類型的值應該是表示 IP協議,因此會調用 TCP/ IP協議棧,并將包轉交給它。
網卡驅動會根據 MAC頭部判斷協議類型,并將包交給相應的協議棧。
7.2.2、IP模塊接收操作
( 1)IP模塊首先會檢查 IP頭部的格式是否符合規范,然后檢查接收方 IP地址,看包是不是發給自己的;
( 2)判斷網絡包是否經過分片;
( 3)需要檢查 IP頭部的協議號字段,并將包轉交給相應的模塊。例如,如果協議號為 06(十六進制),則將包轉交給 TCP模塊;如果是 11(十六進制),則轉交給 UDP模塊。
7.2.3、TCP模塊如何處理連接包
第一步:當 TCP頭部中的控制位 SYN為 1時,表示這是一個發起連接的包。這時, TCP模塊會執行接受連接的操作,不過在此之前,需要先檢查包的接收方端口號,并確認在該端口上有沒有與接收方端口號相同且正在處于等待連接狀態的套接字。如果指定端口號沒有等待連接的套接字,則向客戶端返回錯誤通知的包。向客戶端返回一個表示接收方端口不存在等待連接的套接字的 ICMP消息。
第二步:如果存在等待連接的套接字,則為這個套接字復制一個新的副本,并將發送方 IP地址、端口號、序號初始值、窗口大小等必要的參數寫入這個套接字中,同時分配用于發送緩沖區和接收緩沖區的內存空間。然后生成代表接收確認的 ACK號,用于從服務器向客戶端發送數據的序號初始值,表示接收緩沖區剩余容量的窗口大小,并用這些信息生成 TCP頭部,委托 IP模塊發送給客戶端。
第三步:這個包到達客戶端之后,客戶端會返回表示接收確認的 ACK號,當這個 ACK號返回服務器后,連接操作就完成了。這時,服務器端的程序應該進入調用 accept的暫停狀態,當將新套接字的描述符轉交給服務器程序之后,服務器程序就會恢復運行。
7.2.4、TCP模塊如何處理數據包
( 1)收到數據包時, TCP模塊會根據收到的包的發送方 IP地址、發送方端口號、接收方 IP地址、接收方端口號找到相對應的套接字;
( 2)將數據塊拼合起來并保存在接收緩沖區中;
( 3)向客戶端返回 ACK。
7.2.5、TCP模塊的斷開操作
在TCP協議的規則中,斷開操作可以由客戶端或服務器任何一方發起,具體的順序是由應用層協議決定的。Web中,這一順序隨HTTP協議版本不同而不同,在HTTP1.0中,是服務器先發起斷開操作。
(1)服務器會調用Socket庫的socket,TCP模塊會生成一個 FIN為 1的 TCP頭部,并委托 IP模塊發送給客戶端
(2)當客戶端收到這個包后,會返回一個ACK號,
(3)接下來客戶端會調用close,生成一個 FIN為 1的 TCP頭部發給服務器,
(4)服務器再返回一個 ACK號。
總結
以上是生活随笔為你收集整理的《网络是怎样连接的》笔记的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 网络是怎么连接的
- 下一篇: idea 代码格式化快捷键