---
# System prepended metadata

title: '[NET101] 網路基礎概論（搭配 JS 實作）'
tags: [Frontend]

---

# [NET101] 網路基礎概論（搭配 JS 實作）

###### tags:`Frontend`
[TOC]

A、B 傳紙條，要完成遵守三個守則：
1. 寫明來源
1. 寫明目的地
1. 三個步驟來確認雙方訊息可以正常發送和接收：
    「A 發送訊息給 B，B 接收到訊息，B 回傳訊息給 A，A 接收到訊息」
    * B 接收到訊息 => B 接收 OK
    * B 回傳訊息給 A，A 接收到訊息 => A 發送 OK，A 接收 OK
    * B 回傳訊息給 A => B 發送 OK

標準化內容格式
分為 header(特殊需求), body(普遍需求)
用狀態碼標準化結果
用動詞（POST, GET, DELETE...）標準化動作

## 協定 = 標準 = Protocol

當一件事情有了統一的標準，當很多人都遵守一個共同的標準，就可以把事情規模化

## HTTP 協定

HTTP 負責前端和後端之間的溝通，request 和 response 傳的內容都是 "純文字"，但從瀏覽器看的話，它會幫你把格式排版排好，所以具有可讀性。

### DNS, Domain Name System
負責把 ==網址 Domain <=> IP address== 做查詢，但不一定都要向 DNS server 做查詢，也可以先在本地端的 ==cache== 做查詢，沒查詢到才去 DNS server 做查詢

`127.0.0.1` 是指 local host

###  永遠不要忘記瀏覽器只是另一個程式

request 和 response 不一定要用 browser 才可以做傳送和接收，脫離瀏覽器以後，同樣的事情還是可以做到瀏覽器在做的事情，例如 node 可以用 request library 來做 request 和 response 的處理。

### Header 與 Body
每個 request 和 response 都有 header 和 body 存在，它們根據使用的 protocal 的種類，會有不同的格式，像是這一課使用的都是 http header

### HTTP Method
取得 request 和 response 的方法。

GET
POST 可以放更多資訊，例如 cookies, 帳號, 密碼
DELETE 
PUT 覆蓋原本的內容
PATCH 增加新內容

[HTTP request methods](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods)

### HTTP Status code
* 301 資料永久移到別的位址，例如：傳一個`301`以及`網址從 a.com 移到 b.com`的資料，瀏覽器下次會從 b.com 直接找 DNS.
* 302 資料暫時移到別的位址

#### cheat sheet
1** Hold on
2** Here you go
3** Go away
4** You fucked up
5** I fucked up

一些常見 status code:
* 200 OK
* 301 Moved Permanently (滾去其他地方)
* 400 Bad Request (en-US)
    伺服器因為收到無效語法，而無法理解請求。
* 404 Not Found

[HTTP response status codes
](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status)

### 簡單 nodejs 實作
使用 'http' 這個 nodejs 內建 library
實作：
```javascript=
var http = require('http')

http.createServer((req, res) => {
    if (req.url === '/123') {
        console.log('123456')
        res.end() //才不會一直 pending
        return
    }
    if (req.url === '/redirect') {
        res.writeHead(200, {
            'lidemy': 'good'
        })
        res.end()
        return
    }
    if (req.url === '/goaway') {
        res.writeHead(302, { //302是轉址
            'Location': 'https://www.pixiv.net/'
        })
        res.end()
        return
    }
    else {
        res.writeHead(404)
        res.end()
    }
})

server.listen(5000) //從 localhost:5000 監聽
```

## TCP/IP

OSI 七層模型(OPEN SYSTEMS INTERCONNECTION MODEL):

總共7層，根據設備的address決定層
![圖](https://www.practicalnetworking.net/wp-content/uploads/2016/01/packtrav-osi-layers.png)

TCP/IP 基本上跟OSI模型一樣，只是分成4層，層與層之間是相互疊加的概念上的構造。

### IP address
IPv4(比較舊的 IP 格式)、IPv6(比較新的 IP 格式)

固定 IP，不會改變的 IP address，例如: server
浮動 IP，設備的 IP 每次都會改變
虛擬 IP，只存在於內網的 IP，內網與外網之間通過數據機的一個對外 IP 來溝通。

### Port 的作用
電腦裡的 port 有很多個，每個 port 都有各自負責的服務，因此可以根據 port 來區別不同服務。例如預設進行特定服務的 port 有:
HTTP:80
HTTPS:443
FTP:21

自己在作測試的時候通常會用 3000, 4000 port(沒什麼服務在使用的 port)

### TCP 與 UDP
TCP，傳送 package 之後會**確認 (三次握手)**對方有收到，才會傳下一個封包，封包的傳送較可靠
![三次握手](https://i.imgur.com/MU0Q3sa.png)


UDP，不會確認對方有沒有收到封包，反正一直送封包過去就對了

## 統整
![總結](https://i.imgur.com/IUsajNL.png)
(body, header 是在 HTTP 那一邊)


## API
application programming **interface = 介面**，透過 API 可以讓雙方交換資料，例如: HTTP API 就是透過 HTTP 這個協定來交換資料。 串接 API 指的就是把 request 丟進去，然後拿到 respond (不太確定意思)

### 串接 HTTP API 實戰

```javascript=
const request = require('request')
const process = require('process')
const id = process.argv[2] //以 arr 的形式印出輸入 terminal 的程式碼

request.post(
    {
        url:'https://reqres.in/api/users',
        form: {
            'name':'sasha',
            'job':'hunter'

        }
    },
    (error, response, body) => {
        console.log(body)
    }
)
```

## 資料格式
XML 和 JSON 都是純文字的一種資料格式。

### XML
extensible markup language，==跟 HTML 依樣==，用 ==tag== 來標記內容的標記語言。

### JSON
* 使用 JSON.parse(//string) 把純文字轉換成 物件
* 使用 JSON.stringify(//obj) 把物件轉換成 純文字

### 實作
```javascript=
const request = require('request')
const process = require('process')
const id = process.argv[2] //以 arr 的形式印出輸入 terminal 的程式碼


request.post(
    {
        url:'https://reqres.in/api/users',
        form: {
            'name':'sasha',
            'job':'hunter'
        }
    },
    (error, response, body) => {
        console.log(body) //body 是一個 string (純文字)
        const json = JSON.parse(body) //把純文字的 string 轉換成 json 格式的物件
        console.log(json)
        console.log(JSON.stringify(json)) //把物件轉換成純文字的 string
    }
)
```
## HTTP API 以外的資料交換方式：soap

底層是透過 XML 來傳遞資料

## RESTful 到底是什麼？
它不是一種格式，而是一種 ==API 命名風格==，==讓工程師可以簡單的一眼看出來== 網址<==>HTTP method 在腦中連接起來，例如：
![](https://i.imgur.com/nWYt8Q3.png)

畢竟同樣是"傳資料"這件事，用 PATCH, POST...都可以達成，如果大家都各自為政，使用自己喜歡的 HTTP method 來做同一件事情，這樣會有不好管理的問題
## 好用工具

### 必學指令：curl

會發 GET request 給某網址，然後拿回 response

`curl '/網址' `//發 GET request 給某網址，然後印出 response
`curl -I '/網址'` //只取出 header

### nslookup, ping, telnet
`nslookup` 查詢 網址的 IP
`telnet //ip 或網址 //port` 測試 port 有沒有開並連進去，沒有打 port 的話就會去預設的 23 port
> win10 的 telnet 要自己去開起才可以使用，[開啟方法](https://goodlucky.pixnet.net/blog/post/48400569-%5Bwin10%5D-telnet-%E4%B8%8D%E6%98%AF%E5%86%85%E9%83%A8%E6%88%96%E5%A4%96%E9%83%A8%E5%91%BD%E4%BB%A4%E6%80%8E%E4%B9%88%E8%BE%A6%E5%91%A2%3F)

## query string
不同於 POST 會在 request 的 body 傳送額外資訊， query string 則是在網址裡面直接附上額外資訊的方法，query string 在 url 的格式是`?key=value`
![](https://i.imgur.com/QhSALVl.png)

如果 query string 的內容有特殊符號，就會讓對方的 server 不知道到底在傳甚麼資料，例如`str: "a&b=1"`，轉換成  query string 會是 `str=a&b=1`。    所以一般在 query string 的時候，都會先做 encode 的動作來避免這個問題，encode 可以用 JS 內建的`encodeURIComponent()`來達到

```javascript=
encodeURIComponent('a&b=1')
// "a%26b%3D1"
```