1. 程式人生 > >2.24 網路通訊6:搭建HTTP伺服器

2.24 網路通訊6:搭建HTTP伺服器

1、Web工作方式

我們平時瀏覽網頁的時候,會開啟瀏覽器,輸入網址後按下回車鍵,然後就會顯示出你想要 瀏覽的內容。在這個看似簡單的使用者行為背後,到底隱藏了些什麼呢?

對於普通的上網過程,系統其實是這樣做的:瀏覽器本身是一個客戶端,當你輸入URL的 時候,首先瀏覽器會去請求DNS伺服器,通過DNS獲取相應的域名對應的IP,然後通過 IP地址找到IP對應的伺服器後,要求建立TCP連線,等瀏覽器傳送完HTTP Request (請求)包後,伺服器接收到請求包之後才開始處理請求包,伺服器呼叫自身服務,返回 HTTP Response(響應)包;客戶端收到來自伺服器的響應後開始渲染這個Response包 裡的主體(body),等收到全部的內容隨後斷開與該伺服器之間的TCP連線。 這裡寫圖片描述

Web伺服器的工作原理可以簡單地歸納為:

  1. 客戶機通過TCP/IP協議建立到伺服器的TCP連線
  2. 客戶端向伺服器傳送HTTP協議請求包,請求伺服器裡的資源文件
  3. 伺服器向客戶機發送HTTP協議應答包,如果請求的資源包含有動態語言的內容,那麼伺服器會呼叫動態語言的解釋引擎負責處理“動態內容”,並將處理得到的資料返回給客戶端
  4. 客戶機與伺服器斷開。由客戶端解釋HTML文件,在客戶端螢幕上渲染圖形結果

2.Go如何使得Web工作

前面小節介紹瞭如何通過Go搭建一個Web服務,我們可以看到簡單應用一個net/http包 就方便的搭建起來了。那麼Go在底層到底是怎麼做的呢?

web工作方式的幾個概念

  • Request:使用者請求的資訊,用來解析使用者的請求資訊,包括post、get、cookie、url等資訊
  • Response:伺服器需要反饋給客戶端的資訊
  • Conn:使用者的每次請求連結
  • Handler:處理請求和生成返回資訊的處理邏輯

分析 http包執行機制

如下圖所示,是Go實現Web服務的工作模式的流程圖 這裡寫圖片描述

  1. 建立Listen Socket, 監聽指定的埠, 等待客戶端請求到來。
  2. Listen Socket接受客戶端的請求, 得到Client Socket, 接下來通過Client Socket與 客戶端通訊。
  3. 處理客戶端的請求, 首先從Client Socket讀取HTTP請求的協議頭, 如果是POST 方法, 還可能要讀取客戶端提交的資料,然後交給相應的handler處理請求, handler處理完 畢準備好客戶端需要的資料, 通過Client Socket寫給客戶端。

例項

匯入依賴包

import (
    "net/http"
    "io/ioutil"
    _"net/http/pprof"
)

定義路由處理,並監聽在指定埠

func main() {

    //定義對/hello路由的響應
    http.HandleFunc(
        "/hello",
        func(responseWriter http.ResponseWriter, request *http.Request) {
            //向響應中寫入客戶端地址
            responseWriter.Write([]byte(request.RemoteAddr+";"))
            //向響應中寫入客戶端方法
            responseWriter.Write([]byte(request.Method))
            //向響應中寫入內容
            responseWriter.Write([]byte("hello 祥哥 hello go"))
        })

    //定義對/sister路由的響應
    http.HandleFunc(
        "/sister",
        func(w http.ResponseWriter, r *http.Request) {
            w.Write([]byte("你妹"))
        })

    //定義對/fuck路由的響應
    http.HandleFunc("/fuck", func(writer http.ResponseWriter, request *http.Request) {
        //從本地html檔案中讀入HTML頁面的原始位元組
        contentBytes, _ := ioutil.ReadFile("/home/sirouyang/Desktop/demos/W3/day5/02HTTP/fuck.html")
        //向客戶端寫出響應
        writer.Write(contentBytes)
    })

    //開啟伺服器並監聽在8080埠
    http.ListenAndServe("127.0.0.1:8080", nil)
}