網路的本質其實沒有你想的那麼難


Posted by ai86109 on 2020-07-07

前言

先講結論,其實說穿了網路的本質就是為了要溝通,如果只是幾個人要溝通那倒還好,但如果是幾千人、幾萬人,這時候就會需要一些規範了。

這些規範存在,或者你可以說出現的目的,就是為了可以讓溝通更順暢更有效率。你可以把握這個大原則,先把 Huli 的這篇:從傳紙條輕鬆學習基本網路概念看完,再來看這些專有名詞,可能會比較不那麼抗拒,而且更好懂。


故事之後

我們透過小明慘痛的經驗,知道了傳紙條守則:

  1. 寫明來源
  2. 寫明目的地
  3. 經過三次的前置作業,確保雙方都能收發

而其實對應到的網路概念就是:

  1. 寫明來源,在網路世界中其實就是大家常聽到的 IP 位置
  2. 寫明目的地,同上
  3. 經過三次的前置作業,確保雙方都能收發。這個在網路裡是一個叫做「TCP 三次握手」的東西,TCP(Transmission Control Protocol)是一個通訊協定(Protocol),能夠保證雙方收發正常。

而文中也將傳紙條這件事分層來看,每一層都專注於傳紙條的其中一個面向。

有了大致的概念後,接著就是把以上提到的幾個專有名詞拿出來講。


先從分層講起

國際標準組織提出了一個網路標準框架,叫做 OSI 模型,總共分為七層,而我們常常提到的 HTTP 便是第七層的應用層。

雖然 OSI 七層十分嚴謹,但也因為太過嚴謹以致於程式撰寫不易而影響發展,因此便有人依據 OSI 七層,將他簡化為 TCP/IP 四層,而漸漸形成我們現在的各種網路協定。

這四層包括應用層(HTTP, FTP 等), 傳輸層(TCP, UDP), 網路層(IP), 鏈結層(硬體相關)。

依照文章的敘述
HTTP / FTP 是紙條上的內容
TCP / UDP 是傳紙條時三次確認 / 不確認,一直傳紙條
IP 寄紙條時寫的收件人寄件人
實體層就是郵差幫忙送信。


IP(Internet Protocol)

IP 其實就是網路的一種協定,也就是剛剛說到分層中的網路層。

有我們熟悉的 IPv4, IPv6 兩個版本,IPv4 的網址表示方式,就是我們一般熟悉的四組 0~255 組成,所以代表他的組數最多就只有 2 的 32 次方個。為了要解決 IP address 不夠用的問題,所以產生了 IPv6 這個版本,最多可以支援 2 的 128 次方個位址。

而我們一般所說的 IP 其實講的是 IP address(後面還是簡稱為 IP),也就是這台機器在網路上的住址。理想狀態下,每台機器都會有一組 IP,我只要知道你的 IP 就可以連到你的電腦,但實際上並不會每台電腦都需要,所以才衍生出各種 IP。

通常公司都會使用固定IP,這樣用戶要連線時才不會找不到。

除了固定 IP 之外,還有浮動 IP,顧名思義每次使用時 IP 會跟上一次不一樣,這樣形式也會讓駭客不容易攻擊。

另外還有虛擬 IP。舉個例子來說,你在家裡使用網路分享器時,使用他的 device 都會產生一組 IP,這些 device 可以透過這些 IP 位置互相溝通。但當要連到外部時,會將 request 透過分享器送出去,外部 server 所接收到的會是這台分享器的固定或浮動 IP,而回傳時也會送回這個 IP,再由分享器送回發 request 的電腦(通常 192.168 開頭的都是虛擬 IP)。


HTTP

HTTP(HyperText Transfer Protocol),看到 protocol 就知道是一種協定,他是網際網路傳輸的基礎。

關於 HTTP 和 HTTPS 之間的差別,可以參考這篇 或是 HTTPS 是如何保证安全的?


TCP 三次握手(Three-way handshake)

接著要看剛提到傳輸層的 TCP, UDP。

TCP 是可靠的連結,也就是小明小美他們傳紙條要經過三次確認才能開始傳,TCP 可以確保彼此是有收到的,大部分應用層的服務(如 HTTP)都建立在 TCP 之上,因為他比較可靠。

這三次確認稱之為 TCP 三次握手。

關於三次握手可以參考:为什么 TCP 建立连接需要三次握手Socket是什么

而 UDP 可以想成傳紙條的 NBA 即時戰況,會一直傳送但不會確認是否收到
強調速度,應用像是視訊通話。


現實世界的傳紙條

講了這麼多感覺可以把它們串起來了,有想過當我們打開網頁時,是怎麼看到網頁內容的嗎?

是透過類似傳紙條的流程

瀏覽器 → 製造 request → 傳給 server
server → 處理 → 傳 response 回來

這些資訊可以透過 devTool > network > header & response 看到

我們前有說到 IP 位置,但為什麼我們平常要連到一個網站,打的是網址而非 IP呢?

這一切跟 DNS 有關。

我們剛說打開網頁時,瀏覽器會發送request 給 server,但要去 server 必須要有 server 的 IP 位置才有辦法,所以應該要有方法將我們在網址列輸入的網址,轉成機器看的懂的 IP 位置,靠的就是 DNS(Domain Name System)。

假設我們在網址列輸入 github.com,client 會先把網址送去給 DNS server

Client → github.com 是哪裡? → DNS server
DNS server → 13.250.177.223 → client

而我們得知 IP 後才會進行發送 request 給 server 的動作。

  • 在 devtool 裡,可以看 header 的 Request URL&Remote Address
  • 在 terminal 輸入 nslookup + domain name 也會回傳給你 IP 位置

但其實 client 去問 DNS server 之前也不是沒做功課,他會先到電腦內的 host database 找找,看這個 domain 有沒有相對應的 IP 資料寫在裡面了,如果沒有才會進一步去找 DNS server。

像這邊就已經寫好了 127.0.0.1 localhost,當在瀏覽器輸入 localhost就會到這個 IP,也就是本機。

而像是 adobe 的盜版軟體也是用這種做法。
當軟體要檢查是否為正版時,他會 request → adobe server → response
所以如果你把 adobe server 改成一個不存在的 IP,就不會有 response 回來,檢查也就會失敗。


脫離瀏覽器吧

剛剛講的都是利用瀏覽器去拜訪網站,但這邊再次強調,瀏覽器只是個程式而已,脫離了瀏覽器我們一樣可以發送 request,並且接收 response。

可以利用 npm 上的 request:https://www.npmjs.com/package/request

按照流程安裝後便可以使用。得到 response 的內容後,開一個 html 檔案貼上,打開之後就可以得到一個差不多的網頁了。

如果想要在瀏覽器上看這些資訊,檢查 > network > 就可以在 headers 等 sheet 看到相關資訊。

這邊補充一下,request & response 都有 headers 和 body,body 是帶著主要資訊,headers 則是額外資訊(這邊的 headers&body 與 html 的無關)。


HTTP method

實際寫程式之前,有些背景知識需要先知道。

在第二集時,千千讓動詞標準化動作,講的就是 HTTP method。
所有的方法可以參考這裡:HTTP 請求方法

這邊只舉出幾個最常用的為例子。

GET
當我們送出一個網址後 → 傳送一個 GET request → server
server → 傳送回來response → 顯示出圖片、網頁等等

POST
當我們輸入登入資訊時 → 傳送一個 POST request(內含我們輸入資訊的body)→ server
server → 傳送回來response → 再看成功與否去做動作

PUT
會把傳入的東西取代掉原本的東西

PATCH
只會修改部分資料

DELETE
刪除指定資源

除此之外其他都比較少用到,用到時再查即可。


HTTP status code(狀態碼)

另一個很重要的是 HTTP 狀態碼:HTTP 狀態碼

必須大概知道 1~5 開頭代表什麼

  • 1xx 訊息
  • 2xx 成功
  • 3xx 成功導向
  • 4xx 用戶端錯誤
  • 5xx 伺服器錯誤

還有知道一些常見的即可

  • 200 OK
  • 204 No content 伺服器成功處理了請求,沒有返回任何內容(ex: 你DELETE 成功)
  • 301 永久移到新的位置(所以下一次就會直接把你導到新網址)
  • 302 暫時移到新的位置(下一次還是會去問這個網站我要去導去哪)
  • 404 Not Found
  • 500 Internal server error 可能搶票的時候會看到
  • 503 Service Unavailable

製作一個簡易 http server

綜合以上知識,就可以用 Node.js 製作一個超簡易的 http server。

建立一個檔案 touch server.js

Node.js 有個內建的 library 叫 HTTP,引用他並且 create 一個 server,最後給他一個 port(這邊給他 5000)。

var http = require('http')
var server = http.createServer(function(req, res){

})

server.listen(5000)
  • port其實就是傳紙條故事的服務代碼(例如:nba即時戰況,借籃球...)

接下來就可以開始寫一些東西在裡面了!

var server = http.createServer(function(req, res){
    console.log(req.url)
    res.write('hello')
    res.end()

})
  • 此時可以去terminal 執行 node server.js

並不會印出任何東西,也會一直執行除非按 ctrl+c 才會停。但這很正常,因為你沒有 request 他什麼,他自然不會回你;而 server 端也要一直保持執行,才能在 request 出現時及時回應。

確定 server 執行後,開網頁輸入 localhost:5000,此時可以在網頁上看到 hello,打開檢查可以看到回傳成功的 200,response 就是 hello。

Node.js 也會印出

/
/favicon.ico
  • /是表示根目錄的意思,/favicon.ico是每個網頁 sheet 上預設小 icon,瀏覽器都會預設去發一個 request,問說有沒有這個 icon 可以拿。

我們也可以去拜訪其他的子目錄

var http = require('http')
var server = http.createServer(function(req, res){
    if(req.url === '/'){
        res.write('wecolme!')
        res.end()
        return
    }
    if(req.url === '/hello'){
        res.write('hello')
        res.end()
        return
    }
    if(req.url === '/redirect'){
        res.writeHead(302, {
            'Location': 'https://www.google.com'
        })
        res.end()
        return
    }
    res.writeHead(404)
    res.end()
})

server.listen(5000)

以上就是實作一個最簡單的 server

補充:
剛剛在實作的時候,我們有 listen(5000),這個 5000 是什麼?
就是 port 連接埠,是故事裡說的服務代碼,有一些常見預設的 port 要知道:

  • HTTP 80
  • HTTPS 443
  • FTP 21

所以為什麼我們需要協定(protocol)?

看完前面講到這麼多協定,你可以能已經知道答案了。

協定其實就是標準,而有了標準才能規模化。

從第二集千千的例子我們可以知道,當你量一大的時候,如果沒有一些標準,是很難規模化的。

也不要忘記開頭說到的,網路的本質其實就是為了要溝通

參考資料:https://www.youtube.com/watch?v=8KuO4r5CHjM


#HTTP #DNS #IP #TCP #port #internet







Related Posts

Angular 9 SCSS Global Variable

Angular 9 SCSS Global Variable

3. 優美地定義 React 型別

3. 優美地定義 React 型別

[30] 文法 - 自動分號、TDZ、try..finally、switch

[30] 文法 - 自動分號、TDZ、try..finally、switch


Comments