kyle shanks
    • Create new note
    • Create a note from template
      • Sharing URL Link copied
      • /edit
      • View mode
        • Edit mode
        • View mode
        • Book mode
        • Slide mode
        Edit mode View mode Book mode Slide mode
      • Customize slides
      • Note Permission
      • Read
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Write
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Engagement control Commenting, Suggest edit, Emoji Reply
    • Invite by email
      Invitee

      This note has no invitees

    • Publish Note

      Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

      Your note will be visible on your profile and discoverable by anyone.
      Your note is now live.
      This note is visible on your profile and discoverable online.
      Everyone on the web can find and read all notes of this public team.
      See published notes
      Unpublish note
      Please check the box to agree to the Community Guidelines.
      View profile
    • Commenting
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
      • Everyone
    • Suggest edit
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
    • Emoji Reply
    • Enable
    • Versions and GitHub Sync
    • Note settings
    • Note Insights New
    • Engagement control
    • Transfer ownership
    • Delete this note
    • Save as template
    • Insert from template
    • Import from
      • Dropbox
      • Google Drive
      • Gist
      • Clipboard
    • Export to
      • Dropbox
      • Google Drive
      • Gist
    • Download
      • Markdown
      • HTML
      • Raw HTML
Menu Note settings Note Insights Versions and GitHub Sync Sharing URL Create Help
Create Create new note Create a note from template
Menu
Options
Engagement control Transfer ownership Delete this note
Import from
Dropbox Google Drive Gist Clipboard
Export to
Dropbox Google Drive Gist
Download
Markdown HTML Raw HTML
Back
Sharing URL Link copied
/edit
View mode
  • Edit mode
  • View mode
  • Book mode
  • Slide mode
Edit mode View mode Book mode Slide mode
Customize slides
Note Permission
Read
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Write
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Engagement control Commenting, Suggest edit, Emoji Reply
  • Invite by email
    Invitee

    This note has no invitees

  • Publish Note

    Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

    Your note will be visible on your profile and discoverable by anyone.
    Your note is now live.
    This note is visible on your profile and discoverable online.
    Everyone on the web can find and read all notes of this public team.
    See published notes
    Unpublish note
    Please check the box to agree to the Community Guidelines.
    View profile
    Engagement control
    Commenting
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    • Everyone
    Suggest edit
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    Emoji Reply
    Enable
    Import from Dropbox Google Drive Gist Clipboard
       Owned this note    Owned this note      
    Published Linked with GitHub
    • Any changes
      Be notified of any changes
    • Mention me
      Be notified of mention me
    • Unsubscribe
    --- title: 'Http 協定 / Https / URL' disqus: kyleAlien --- Http 協定 / Https / URL === ## OverView of Content 如有引用參考請詳註出處,感謝 :smile: [TOC] ## 指定訪問文件 - URX ? * 由於我們是訪問伺服器上的某個資源,所以我們就要指定資源,而指定資源通常幾種說法 URI、URL、URN... 最常見的就是 URL * `U` 在不同時代代表了不同意思 * 早期代表了 **`Universal` 萬用** * 標準後代表了 **`Uniform` 統一** * `R` 代表了 `Resource` 資源 * **URL、URN 其實是 URI 的一個小分支**,也就是說 URL、URN 是 URI 的子集 :::info * URL & URI 差別 | 類型 (全名) | 功能 | 其他 | | -------- | -------- | -------- | | `URL`(`Uniform Resource Location`)| 資源路徑 | URL 是一種**指向路徑** | | `URN`(`Uniform Resource Name`) | **資源標識符** | 某項 **獨一無二** 的資源,通常用於永久標識資源,並與資源的位置或存取方式無關 | | `URI`(`Uniform Resource Identifier`)| 資源實際位子 | **能直接找到資源的就是 URI** | ::: > URL 可以代表協議,以及要訪問的資源位置、設定 > > ![](https://i.imgur.com/DGD7p8H.png) ### 協定 Scheme ```shell= https ``` * **==Http 代表此 URL 使用的協定==**,常見的還有 Https、SMTP、POP3、FTP、mailto... * **Http 是超文本傳輸** 而 http++s++ 表示了以 SSL (Secure Socket Layer) 機制傳輸,該加密會導致擷取的到資料無法被一般解析,而 **SSL 機製作用於應用層到傳輸層之間(++通常在 [表達層](https://hackmd.io/AIIw1ejaSWykNrWSsMH8Mw?both#%E8%A1%A8%E7%A4%BA%E5%B1%A4) 加密++)** :::warning 封包訊息可以使用 `wireshark` & `tcpdump` 攔截到,https 也可以攔截到但是會看不懂它的訊息 ::: * Https/Http 協議之後也可以接著使用者名稱、密碼,一般格式如下 > 如果使用 Http 的話,不建議用這種方式登入 ```shell= # 協議://<使用者名稱>:<密碼>@<主機>:<Port>/<Path> https://kylePan:abcd1234@www.hello.com:1000/world ``` ### 主機地址 Host ```shell= www.google.com ``` * 從`//` 至 `/` 之間的 **www.google.com 這代表了伺服器的位址,正確來說是 FQDN (完整網域名稱),而 ==FQDN 必須藉由 DNS(網域解析) 轉換為 IP== 地址才可通訊** > www 則是指伺服器端的服務是屬於 Web 伺服器(萬維網) :::warning 上面所說道的 **伺服器** 並非指電腦,**是指一組服務程式**,http/https 就是網頁服務、ftp/ftps 指的是檔案服務,**一台電腦可以有多個服務** ::: * Linux、Windows 都可以 **透過指令 ++nslookup++ 查詢到相對應的 IP**, 一個 IP 可以有多組 DNS > ![](https://i.imgur.com/4KD72Se.png) * **TCP/IP 協定除了需要 ip 地址外,還==需要端口 (port)==**,而上面不需要 port 的原因在於,**它使用常規端口所以不用特別加上 port,用法在 https//ip ==:port==** ```htmlmixed= 以下是相同的功能 // 使用 ipv4 訪問 google https://172.217.27.132 // 使用 ipv6 訪問 google,中括弧必須 https://[2404:6800:4008:800::2004] // 使用名稱訪問 https://www.google.com ``` :::warning * **直接使用 IP 訪問實會出現 ++不安全連線++**,這是因為 **==憑證==** 的問題,**這種狀況只會出現在 https 中,因為 https 才需要憑證** ::: ### 網頁 Path - 參數 Quary-String ```shell= search?client=ubuntu&channel=fs&q=ubuntu+drawio&ie=utf-8&oe=utf-8 ``` * **從`/` 至 `?` 之間的 search,是真正的請求主體**(Get 請求) * 把 URL 的第一個斜槓`/`稱為 **根目錄 (如同 Linux 的根目錄)** * 而 **`serach` 才是主要要服務的主體** * **`?` 之後統稱為 `欄位` or `參數`**,`client=ubuntu&channel=fs&q=ubuntu+drawio&ie=utf-8&oe=utf-8`,**組跟組之間使用 ==&== 區分開來** 每一組參數在等號左方稱為參數名,右方成為參數值 (key & value),若是沒有參數則不寫任何值 * **`#` 稱為錨,也就是網頁的讀取點**,像是 #name=454 (454 開始閱讀這個網頁) ```htmlmixed= // 原參數 client=ubuntu&channel=fs&q=ubuntu+drawio&ie=utf-8&oe=utf-8 // 解析參數出 5 組 1. client=ubuntu 2. channel=fs 3. q=ubuntu+drawio 4. ie=utf-8 5. oe=utf-8 ``` ### URL 編碼 - 百分比編碼 * **保留字元** 在 URI 的規範中,定義了「保留字元」(`Reserved character`),像是 `:`、`/`、`?`、`?`、`&`、`=`、`@`、`%`... 等等 * 參數欄位的特殊符號,當參數有些特別符號時 (很常看到這些特別符號),會去搜尋 [**ASCII**](https://zh.wikipedia.org/wiki/ASCII) 碼對應,使用 %<ASCII 16進制\> 轉換成 URL > URL 中可以使用 `+` 代表空白也就代表 `%20`,而真正使用 `+` 號時請使用 `%2B` | 符號 | 轉換 | | -------- | -------- | | 空白 | %20 | | + | %2B | | < | %3C | | = | %3D | | > | %3E | | ? | %3F | * **中文字元** 針對英文可以使用 ASCII 編碼,用一個位元的 UTF-8 即可;但如果使用中文(或是非英文),那使用 ASCII 編碼就會不夠表達,這時 UTF-8 就會是 2 ~ 3 位元的大小 :::danger * **編碼並非一定要使用 UTF-8 嘛?** 只要遊覽器、伺服器端講好規範就可以,如果兩者不按照規定解析,仍會解析錯誤 > 中文字「林」,UTF-8 是 `E6、9E、97` 在 URL 編碼之下就會變為 `%E6%9E%97` > > 而如果瀏覽器使用 BIG5 則是編碼為 `%AA%4C` ::: ### Java URI - 編碼工具 * Java 也提供 URI 編碼方案(`ISO_8859_1` 是國際標準化組織 (IOS) 為 西歐語言的字元碼制定的編碼,與 `ASCII` 相容) ```java= public static void main(String[] args) { String encodeUrl = URLEncoder.encode("https://hello.world?url=http://123", StandardCharsets.ISO_8859_1); System.out.println("encode url: " + encodeUrl); String decodeUrl = URLDecoder.decode(encodeUrl, StandardCharsets.ISO_8859_1); System.out.println("decodeUrl url: " + decodeUrl); } ``` > ![image](https://hackmd.io/_uploads/rkGXneW46.png) * Java 中有一個 URI 類 (`java.net.URL`),它可以自動轉換出需要的資訊 ```java= import java.net.URL; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; public class Main { public static void main(String[] args) throws IOException { URL url = new URL("https://hackmd.io/?nav=overview"); System.out.println("Protocol:" + url.getProtocol()); System.out.println("Host:" + url.getHost()); System.out.println("Port:" + url.getPort()); System.out.println("Path:" + url.getPath()); InputStream is = url.openStream(); InputStreamReader isr = new InputStreamReader(is); BufferedReader br = new BufferedReader(isr); String str = br.readLine(); while (str != null) { System.out.println(str); str = br.readLine(); } br.close(); isr.close(); is.close(); } } ``` 1. 如果沒有設定 port 的話,java 內部實現預設為 -1 2. **URL 可直接讀取網頁 IO 內容,也就是 html 的文本** > ![](https://i.imgur.com/r3SjdFU.png) ## Http 協議 Http 通訊協定是架構在 TCP/IP 應用層之上的協定;其特性是 ^1.^ **無狀態**、^2.^ **基於請求(`Request`) / 回應(`Response`)的模型** * Http 歷史簡介 | 年分 | 版本 | 功能、特色 | | -------- | -------- | -------- | | 1991年 | HTTP 0.9 | 只有一個 GET 命令、只能回覆 HTML 超文本 | | 1996年 | HTTP 1.0 | 除了 GET 還引入 POST、HEAD 命令,每次回覆都需要包括頭訊息 | | 1997年 | HTTP 1.1 | 更加完善,目前大部分還使用中 | | 2009年 | SPDY | Google 為了改善 Http 1.1 效率研發 | | 2015年 | HTTP 2 | SPDY 協議的主要特性也在其中 | ### Http 特性 1. 典型的 **C/S 架構** (client & server) > **基於請求(`Request`) / 回應(`Response`)的模型** 2. **速度快,只需要傳送方法 & 路徑就可以得到返回的數據** 常用的方法有 `GET`、`POST`、`HEAD`...每種方法規定了客戶端 & 服務端聯繫的類型 3. **靈活,Http 允許傳輸任何類型的數據**,**傳輸的類型使用 ++Content-Type++ 標記** 4. **無連接,限制每一次的連接只處理當次的請求**,加快處理速度 5. **無狀態**,對於事務處理不會有記憶 (不會記錄過往訊息,也就**不會給伺服器添加紀錄的負擔**) :::info * 也是 **由於 Http 的特性,MVC 才發展出 `Model2` 模式**、`Session management` 會話管理機制 ::: ### Http Request - Get / Post 請求結構 * **Http 請求結構就是一個文本**,文本每一個字都是 ASCII 碼(「字元」),字串長度不固定,依照需求增加,一般而言包括 4 個部分 ```shell= # Get # 請求行 GET /example HTTP/1.1 #請求頭 Host: www.example.com User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:100.0) Gecko/20100101 Firefox/100.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 Accept-Language: en-US,en;q=0.5 Accept-Encoding: gzip, deflate, br Connection: keep-alive Upgrade-Insecure-Requests: 1 ## ----------------------------------------------------------------------------------------- # Post # 請求行 POST /api/data HTTP/1.1 #請求頭 Host: www.example.com Content-Type: application/json Content-Length: 32 # 空行 # 請求內容 {"key1": "value1", "key2": "value2"} ``` > > ![](https://i.imgur.com/6Hwf7LS.png) 1. **請求行**:透過它來表達出通用操作模式、語意與行為定義;HTTP 也定義一套固定的操作方式,可以讓任何資源遵守,它稱之為「動詞, `verbs`」 ```htmlmixed= // 不需要<>,單純為了區隔 <Method> <Request-URI> <HTTP-Version> <CRLF> ``` | 動詞 Method | 功能 | | -------- | -------- | | **`GET`** | 請求獲取 `<Request-URI>` 的資源內容 | | **`POST`** | 請求獲取 `<Request-URI>` 的資源內容,**==並附加新的內容==,相當於資料庫中的 `insert` 行為** | | `HEAD` | 請求獲取 `<Request-URI>` 的資源的報頭 (header Message) | | `PUT` | 請求服務器,**++儲存++一個資源至服務器**,相當於資料庫中的 `update` 動作 | | `DELETE` | 請求服務器,**++刪除++一個服務器內的資源** | | `TRACE` | 請求服務器回傳收到的訊息,**常用於診斷是否由傳輸錯誤** | | `CONNECT` | Http 1.1 協議中預留給能夠將連接改為管道方式的代理服務器 | | `OPTIONS` | **查詢服務器的功能、性能** | 2. **請求頭 (`Overview`)** **它是 `Key : Value`,而且有++多行請求頭++**,並使用 `:` 區分開來;伺服器端可以依據需求取出做適當的回應… 如下 * `User-Agent` 中得知使用者使用的瀏覽器資訊 * `Accecpt-Language` 了解遊覽器可接受哪些語系的內容回應 3. **空行**(`\r\n`) 4. **請求數據、參數 (`Context`)** 在 GET 方法並不會使用到數據,因為 GET 只有要求數據,但 Get 可以攜帶參數在 URL 中,給伺服器判斷 ```shell= https://www.google.com/search?q=HelloWorld&sca_esv=582168257 ``` :::danger * 大量的數據不適合使用 Get 請求,因為 Get 有長度限制(每個遊覽器都不同) ::: **++POST 方法才會使用到++,POST 方法需要提交文本,提交給伺服器資料**… 這個資訊通常用「表單」的方式發送,這是伺服器端對於使用者的要求 ### Get、Post 選擇 - 冪等概念 * **Get、Post 選擇** * **Get 請求的特色** * Get 參數會跟隨在 URL 之上,不過由於瀏覽器 URL 長度限制,所以不適合處理大量、長度長的資料 * 如果希望保留網頁頁面,並且參數也會影響到頁面的展示,那就可以用 GET 請求,將參數保留在 URL 之上 * **Post 請求特色** * 由於 Post 不會將請求體顯示在 URL 之上,所以相對來講,較為安全 * 但 Post 行為可能不夠即時,因為它並非同步操作 > 回應可能是 201 `Created` 或是 202 `Accpeted` * **選擇請求** * **操作類型** 來決定: 如果 **不希望瀏覽器 Cache 網頁資訊,就可以用 Post** 因為遊覽器可能會依照 URL 來 Cache,而使用 Post 就可以每次都攜帶最新資料到後端處理,不會 Cache * **冪等(`idempotent`)操作** 來決定 是否冪等,就是判斷請求的操作 **是否改變伺服器的狀態**、**是否同一個操作重複多次**、**是否回傳相同結果** :::success 冪等源於數學,後來才延伸到電腦領域;它是指函數可以使用相同的參數重複執行,並每次得到相同的結果) ::: * **Get 適用於冪等操作**:因為 Get 不會改變伺服器狀態,對於 DB 來說相當於做 `select` 操作 > Get 的請求參數,它只用於告知伺服器,**必須根據請求參數回傳對應的內容**,並且每次回傳都是相同的 * **Post 則是「非」冪等操作**:對於 DB 來說相當於做 `insert` 操作(同資料可能操作多次) > **Post 發送的資料可能影響伺服器上的資料、狀態**,像是增刪改查.. 等等操作,而且同一份資料可能會得到不同結果 :::info * 相較之下,`put`、`delete` 操作則是等冪操作 因為我們發送 10 次 `PUT` 訊息會是相同的結果,但是如果我們發送 10 次 `POST` 訊息則可能得到不同的結果 ::: ### Http Response 結構 * Http 回應結構也同樣是一個文本,文本每一個字都是 ASCII 碼,字串長度不固定 ```shell= # 狀態行 HTTP/1.1 200 OK # 響應頭 Date: Sun, 13 Nov 2023 12:00:00 GMT Server: Apache/2.4.38 (Unix) Content-Type: text/html; charset=UTF-8 Content-Length: 1234 # 空行 # 響應數據 <!DOCTYPE html> <html> <head> <title>Example Page</title> </head> <body> <h1>Hello, World!</h1> <p>This is an example response.</p> </body> </html> ``` > ![](https://i.imgur.com/VLql0LU.png) 1. **狀態行** (該行狀態碼較重要) ```htmlmixed= // 不需要<>,單純為了區隔 <HTTP-Version> <State-Code> <Reason-Phrase> <CRLF> // Reason-Phrase 為狀態碼的文本描述 ``` 以下舉幾個常見的狀態碼 | State-Code | Reason-Phrase | 意義 | | -------- | -------- | -------- | | 200 | OK | 客戶端請求成功 | | 400 | Bad Request | 客戶端語法錯誤,服務器無法解讀 | | 401 | Unauthorized | 未經過授權,該狀態碼必須還 www-Authenticate 報頭域一起使用 | | 403 | Forbidden | 服務器收到請求,但拒絕提供該服務 | | 404 | Not Found | 服務器找不到請求的資源或是文件 | | 500 | Internal Server Error | 服務器內部錯誤而妨礙了請求的執行 | | 501 | Service Unavailable | 服務端維護中或是暫時超載,無法立刻響應該請求 | | 503 | Server Unavailable | 服務器當前不能處理客戶端請求,一段時間後可能會恢復正常 | 狀態碼的區間 | 區間 | 意義 | | -------- | -------- | | 100~199 | 提示訊息,收到請求,是用者可以繼續執行操作 | | 200~299 | **請求成功**,請求已被接受並處理 | | 300~399 | **重新定位**,請求者**必須**更進一步操作 | | 400~499 | **客戶端錯誤** | | 500~599 | **服務端錯誤** | 2. 響應頭 (Overview) **它是 Key : Value,而且有++多行請求頭++**,並使用 `:` 區分開來 3. 空行 4. 響應數據 (Context) ### Http Header 訊息:客戶端、伺服器端 * 以下要說明的是 HTTP 定義的內容協商(`content negotiation`)機制,稱之為 Http Header,這些 Header 選項可以超過一個以上 ```shell= header1[;q=1] [; header2...] ``` > `q=1` 是品質因數,因數越高代表越能接受的格式 * 我們將 Http Header(報頭)分為幾個大分類,分別是客戶端的請求報頭、服務器端的響應報頭、通用報頭… 等等 1. General-header **通用報頭** > 可出現在請求(客戶端)、響應(服務器)報頭 | Key | 功能 | | -------- | -------- | | `Data` | 消息產生的時間 & 日期 | | `Conntion` | 允許發送指定連結的選項,可指定是連續的、傳送完畢就關閉...等等 | | **`Cache-Control`** | **緩存策略,++該指令是單向的++ (客戶端緩存機制、服務端緩存機制可不同)** | | `cookies` | 儲存訊息 | | `Transfer-Encoding` | **告知服務器端該如何解碼** | 2. request-header 使用端專用報頭 > 通知服務器關於**客戶端的請求訊息**,**客戶端報頭大多以 `Accpet` 開頭**,它會告訴服務端它所接收的資料類型、語言、編碼… 等等設定 | Key | 功能 | | -------- | -------- | | `Host` | **請求的主機名稱**,多個域名指向同一個 IP 稱為 **虛擬主機** | | `User-Agent` (代理) | **客戶端資訊**,遊覽器類型、操作系統等等 | | `Accept` | **客戶端可處理的內容類型列表**,用於指定客戶端接收的數據類型 | | `Accept-Encoding` | **客戶端可接受的編碼類型** | | `Accept-Language` | **客戶端遊覽器所支持的語言** | | `Connection` | **客戶端 & 服務器端連接方式相關**,Ex: keep-alive 保持連線 | 3. response-header 服務端專用報頭 > 用於 **伺服器傳遞自身訊息**的響應,**伺服器端報頭大多以 `Content` 開頭**,用來指定回傳的資料格式 | Key | 功能 | | -------- | -------- | | `Location` | 重新定向,常用於要求 Client 端更換域名 | | `Server` | **與 User-Agent 相對應,代表了服務器端的規格** | entity-header 實體報頭 > 定義被傳送資源的信息,**簡單來說就是 ++描述傳送的資源++** 所用的 Header | Key | 功能 | | -------- | -------- | | `Content-Language` | 內容語言(人們用得自然語言) | | `Content-Length` | 實體主體的大小,但為`Byte` | | `Content-Location` | 重新導向 URI 的位置 | | `Content-MD5` | 用於驗證訊息主體的完整性(通常 128 bit) | | `Content-Range` | 指定實體資料的範圍 | | `Content-Type` | 內容主體的媒體類型 | | `Content-Encoding` | 內容的編碼模式,來獲得正文的解碼方式 | | **`Last-Modified`** | 該資源最後修改的日期 & 時間 | | **`Expires`** | 實體報頭給出響應過期的日期 & 時間 | **--[網頁範例](https://www.wanandroid.com/project/tree/json)--** (開啟網頁後,打開 F12 開發者模式,選擇 `Network` 就可以見到) > ![image](https://hackmd.io/_uploads/S1p68KuWA.png) ## Http 緩存機制 * 存在 http 的 **Header 頭訊息 Cache-Control** * 為了不要讓客戶端太過頻繁訪問伺服器,否則導致流量消耗過大、負擔過重,使用緩存機制 (雙方不一定都有此機制),以下有幾種常用的緩存機制 1. `Cache-control` -> ++**Max-age**++ > 為了修正 Http1.1 Expires 的漏洞 (C/S 時間不一致),Max-age 的單位為秒 2. `Cache-control` -> ++**no-cache**++ > **會先經過對比緩存**,傳緩存標誌給伺服器端,如果有需要才會請求報文,否則伺服器返回 304 代表該緩存可用 3. `Cache-control` -> ++**no-store**++ > 連對比緩存都沒有,**每次都會發送請求訊息報文** ### 緩存過程 * 下圖是第一次請求時的流程,當**返回數據時會將響應頭中的 `Cache-control` 規則存入本地的緩存**,之後每次請求都會進行比對,這樣才不會浪費資源 > ![](https://i.imgur.com/6EOtWmb.png) * **強制緩存**,每次比對都會本地緩存,比對 **==expires== (Http\1.0)、private、public、max-age、no-store (每次都請求數據)、no-cache (對比緩存)**,**當數據已過期就會再次請求伺服器,否則會繼續使用緩存資源** > ![](https://i.imgur.com/C00XCFF.png) 強制緩存中的 `cache-control` ==**使用 no-cache 緩存**== 機制,需要透過 **++對比緩存++**,**成功返回 304 代表不用更新數據** (服務端 & 客戶端都要支持) > ![](https://i.imgur.com/bmygFP1.png) ### 對比緩存 * 對比緩存一定有一個**對比的標示**,而**決定該標示是否有用在於伺服器**,**而該標示也有優先級**,該標示如下表 | 優先級 | 對比標示 | 功能 | 作用 | | - | -------- | -------- | -------- | | **低** | `Last-Modified` / `If-Modified-Since` | 伺服器會同時返回這兩個標示,當客戶端要再要求資訊時會傳出 `If-Modified-Since`,伺服器端就會比對 | **在伺服器端比對**,`Last-Modified` < `If-Modified-Since` 更新;`Last-Modified` > `If-Modified-Since` 返回 304 取用暫存 | | **高** | `Etag` / `If-None-Match` | 伺服器會返回這兩個標示,當客戶端在要求時會傳出 `If-None-Match`,讓伺服器端比對該條訊息 | **在伺服器端比對**,比對 `Etag` 是否相同,不同則需要更新,相同返回 304 | > ![](https://i.imgur.com/pEwu1Ov.png) ## Http 版本區別 ### Http 1.0 * 請求 & 響應支持頭域 (Header Message) * 響應對象以一個響應狀態行開始,並不只限於超文本 * **開始支持客戶端通過 POST 方法向伺服器提交數據,支持的請求方法有 GET、PUT、HEAD** * **頭域支持長連接 (須設定,默認是端連結)、緩存訊息** ### Http 1.1 * **頭域支持 ==keepalive 連結==** * chunked 編碼傳輸、字節範圍請求 * **請求頭域支援 Host** * 新增請求碼,OPTIONS、PUT、DELETE、TRACE、CONNECT 方法 * 緩存處理 > 基於 1.0 上加入了一些 cache 的特性,引入實體標籤,依般稱為 e-tags,新增更強大的頭域 Cache-Control 報頭 ### Http 2.0 | 名稱 | 功能 | | -------- | -------- | | **多路覆用 (二進制分貞)** | **Http 2.0 最大的特點**,不改動 Http 格式 (保留方法、狀態碼、頭域...),**==改進傳輸效能,++新增二進制分貞層++==,將信息切成更小的單元傳輸,並採用二進制格式傳輸** | | 頭部壓縮 | 當客戶端**向同一個伺服器**請求多個資源時,會有大量相似訊息、這就**需要頭部壓縮,增高傳輸效率** | | 隨時復位 | Http 1.1 的一個缺點在於,當 Http 訊息有一定長度大小數據傳輸時,不能隨時中斷它 (中斷 TCP 連接的代價太高,可能導致全文件重新傳輸),Http 2.0 的 REST_STREAM 能快速、方便的停止一個訊息傳輸 | | 服務端推流 (Server Push) | 當客戶端請一個資源後,需要用到多個資源時,無須詢問客戶端就會自動把需要的資源存入緩存 | | 優先權 & 依賴 | **每一個流都可以有優先級別,放便優先級加載** | ## Https 請求 發出 Https 請求時的處理順序是… 0. 透過 DNS 域名解析器,解析目的 IP 地址 1. 三握手建立 TCP 傳輸層連接 2. **客戶端向服務器發送請求行命令** `GET www.google.com HTTP/1.1` > 客戶端發送,請求頭訊息 3. **服務器端響應訊息** Http/1.1 200 OK > 返回響應頭訊息 4. 服務器向客戶端發送數據 5. 關閉 TCP 連線 ### Https 請求過程 * **Https 是基於 Http 新增 SSL 協議來保護傳輸訊息,比起 Http 多了一個握手的過程**,[**可參考知乎**](https://zhuanlan.zhihu.com/p/37738632)、[**BINANCE**](https://www.binance.vision/zt/security/symmetric-vs-asymmetric-encryption) | 加密方式 | 意義 | 注意 | 密鑰長度 | 應用 | | -------- | -------- | - | - | - | | 對稱加密 | 用同一把 Key 加密、解密 | 容易被集線器、交換器、路由器等等的中間設備盜取、攔截 | 通常 128、256 **(單位 Bit)** | DES、AES、3DES、IDEA、RC5 | | 非對稱加密 | 加密的密鑰稱為 public key (可與人共享),解密用 private key(需保密) | 較耗效能 | 與數學運算聯繫 **(單位 Bit)** | RSA、E1Gamal、Rabin | ### 單向認證 * 整個認證過程仍都是 **明文傳輸** * **會產生三次隨機數,前兩次是非對稱加密,==第三次產生的隨機數,是為了之後溝通用的對稱加密 Key==** :::success 1. 發送客戶端 SSL 版本訊息 (Client 可接受的 SSL) 2. 服務端給客戶端返回確定的 SSL 版本、**隨機數**、證書、公鑰訊息 3. 客戶端驗證證書合法性 4. 客戶端發送自己可支持的加密方法給服務器 5. 服務器將選擇好的加密方式交給客戶端 (明文) 6. 客戶端收到加密方式、**==產生隨機碼==,作為++對稱加密++密鑰,並使用 服務器公鑰 加密後**,將訊息加密後傳給服務端 7. 服務端使用 private key 解密,獲得對稱的密鑰 8. **最終使用對稱加密通訊** ::: > ![](https://i.imgur.com/Qd1k4Uq.png)來源於網路 ### 雙向認證 :::success 1. 發送客戶端 SSL 版本訊息 (Client 可接受的 SSL) 2. 服務端給客戶端返回確定的 SSL 版本、**隨機數**、證書、公鑰訊息 3. 客戶端驗證證書合法性,==發送客戶端的證書、公鑰== 4. ==服務器驗證客戶端證書== 5. 客戶端發送自己可支持的加密方法給服務器 6. 服務器將選擇好的加密方式交給客戶端 (明文) 7. 客戶端收到加密方式、**產生隨機碼,作為++對稱加密++密鑰,並使用 客戶端公鑰 加密後**,將訊息加密後傳給服務端 8. 服務端使用 private key 解密,獲得對稱的密鑰 9. **最終使用對稱加密通訊** ::: > ![](https://i.imgur.com/f87P2a4.png) 來源於網路 ## Socket 通訊 Socket 也就是套接字,**是針對 ==TCP/IP 協議封裝== 的接口 API**,用來描述 IP & Port :::info 其中網路通訊必須的訊息如下 1. 連接者所使用的協議 2. 本地主機 IP 地址 3. 要連接的協議端口 4. 遠端 IP 地址 5. IP 所使用的 Port ::: ### 簡單 Socket 通訊 > 以下會使用基礎的 Socket 功能 | API | 功能 | | -------- | -------- | | [**ServerSocket**](https://docs.oracle.com/javase/7/docs/api/java/net/ServerSocket.html) | 創建 Socket 服務端,可指定 Port | | [**Socket**](https://docs.oracle.com/javase/7/docs/api/java/net/Socket.html) | 創建 Socket 客戶端,需要指定 Host & Port | * 服務端程式如下:創建 ServerSocket ```java= import java.io.IOException; import java.io.*; import java.net.ServerSocket; import java.net.Socket; public class SocketServer { public static void main(String[] args) { try { ServerSocket server = new ServerSocket(22222); System.out.println("ServerSocket start accpect..."); Socket s = server.accept(); InputStream is = s.getInputStream(); InputStreamReader isr = new InputStreamReader(is); BufferedReader br = new BufferedReader(isr); String str; System.out.println("Hi, you met port is 22222, Start accpect Msg: \n"); while((str = br.readLine()) != null) { System.out.println(str); } br.close(); isr.close(); is.close(); //s.shutdownInput(); "1. " System.out.println("ServerSocket finish accpect !"); server.close(); } catch (IOException e) { e.printStackTrace(); } } } ``` > 如果**已經手動關閉就不用調用 API 的 shutdownInput**,否則拋出錯誤 * 客戶端客戶端程式:透過 Socket 創建連線目標 ```java= import java.io.IOException; import java.io.*; import java.net.InetAddress; import java.net.Socket; public class SocketClient { public static void main(String[] args) { try { Socket client = new Socket("127.0.0.1", 22222); // "1. " //"2. " OutputStream os = client.getOutputStream(); OutputStreamWriter osw = new OutputStreamWriter(os); BufferedWriter bw = new BufferedWriter(osw); InetAddress address = InetAddress.getLocalHost(); String ip = address.getHostAddress(); bw.write("Hello, I'm Socket Client, ip: " + ip); bw.flush(); client.shutdownOutput(); // 一定要 shutdown Output "3. " client.close(); } catch (IOException e) { e.printStackTrace(); } } } ``` 1. 在創建 Socket 後就會 **自動 (不用調用 API)** 依照你設定的 host、port 連結 2. 並可獲取輸入輸出流 :::warning **必須要關閉資源才會真正輸出**(記得調用 `shutdownOutput`) ::: **--實作--** > ![](https://i.imgur.com/Dschqxc.png) ## Appendix & FAQ :::info ::: ###### tags: `網路基礎` `Http`

    Import from clipboard

    Paste your markdown or webpage here...

    Advanced permission required

    Your current role can only read. Ask the system administrator to acquire write and comment permission.

    This team is disabled

    Sorry, this team is disabled. You can't edit this note.

    This note is locked

    Sorry, only owner can edit this note.

    Reach the limit

    Sorry, you've reached the max length this note can be.
    Please reduce the content or divide it to more notes, thank you!

    Import from Gist

    Import from Snippet

    or

    Export to Snippet

    Are you sure?

    Do you really want to delete this note?
    All users will lose their connection.

    Create a note from template

    Create a note from template

    Oops...
    This template has been removed or transferred.
    Upgrade
    All
    • All
    • Team
    No template.

    Create a template

    Upgrade

    Delete template

    Do you really want to delete this template?
    Turn this template into a regular note and keep its content, versions, and comments.

    This page need refresh

    You have an incompatible client version.
    Refresh to update.
    New version available!
    See releases notes here
    Refresh to enjoy new features.
    Your user state has changed.
    Refresh to load new user state.

    Sign in

    Forgot password

    or

    By clicking below, you agree to our terms of service.

    Sign in via Facebook Sign in via Twitter Sign in via GitHub Sign in via Dropbox Sign in with Wallet
    Wallet ( )
    Connect another wallet

    New to HackMD? Sign up

    Help

    • English
    • 中文
    • Français
    • Deutsch
    • 日本語
    • Español
    • Català
    • Ελληνικά
    • Português
    • italiano
    • Türkçe
    • Русский
    • Nederlands
    • hrvatski jezik
    • język polski
    • Українська
    • हिन्दी
    • svenska
    • Esperanto
    • dansk

    Documents

    Help & Tutorial

    How to use Book mode

    Slide Example

    API Docs

    Edit in VSCode

    Install browser extension

    Contacts

    Feedback

    Discord

    Send us email

    Resources

    Releases

    Pricing

    Blog

    Policy

    Terms

    Privacy

    Cheatsheet

    Syntax Example Reference
    # Header Header 基本排版
    - Unordered List
    • Unordered List
    1. Ordered List
    1. Ordered List
    - [ ] Todo List
    • Todo List
    > Blockquote
    Blockquote
    **Bold font** Bold font
    *Italics font* Italics font
    ~~Strikethrough~~ Strikethrough
    19^th^ 19th
    H~2~O H2O
    ++Inserted text++ Inserted text
    ==Marked text== Marked text
    [link text](https:// "title") Link
    ![image alt](https:// "title") Image
    `Code` Code 在筆記中貼入程式碼
    ```javascript
    var i = 0;
    ```
    var i = 0;
    :smile: :smile: Emoji list
    {%youtube youtube_id %} Externals
    $L^aT_eX$ LaTeX
    :::info
    This is a alert area.
    :::

    This is a alert area.

    Versions and GitHub Sync
    Get Full History Access

    • Edit version name
    • Delete

    revision author avatar     named on  

    More Less

    Note content is identical to the latest version.
    Compare
      Choose a version
      No search result
      Version not found
    Sign in to link this note to GitHub
    Learn more
    This note is not linked with GitHub
     

    Feedback

    Submission failed, please try again

    Thanks for your support.

    On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?

    Please give us some advice and help us improve HackMD.

     

    Thanks for your feedback

    Remove version name

    Do you want to remove this version name and description?

    Transfer ownership

    Transfer to
      Warning: is a public team. If you transfer note to this team, everyone on the web can find and read this note.

        Link with GitHub

        Please authorize HackMD on GitHub
        • Please sign in to GitHub and install the HackMD app on your GitHub repo.
        • HackMD links with GitHub through a GitHub App. You can choose which repo to install our App.
        Learn more  Sign in to GitHub

        Push the note to GitHub Push to GitHub Pull a file from GitHub

          Authorize again
         

        Choose which file to push to

        Select repo
        Refresh Authorize more repos
        Select branch
        Select file
        Select branch
        Choose version(s) to push
        • Save a new version and push
        • Choose from existing versions
        Include title and tags
        Available push count

        Pull from GitHub

         
        File from GitHub
        File from HackMD

        GitHub Link Settings

        File linked

        Linked by
        File path
        Last synced branch
        Available push count

        Danger Zone

        Unlink
        You will no longer receive notification when GitHub file changes after unlink.

        Syncing

        Push failed

        Push successfully