Golang-web基礎
1. Golang-web工作機制
1.web工作方式:
瀏覽器URL –> 請求DNS服務器 ->解析域名到對應的IP –> 建立TCP協議 –>發送Http Request –>Web服務器處理請求 –>Http Response返回客戶端 –>渲染響應體 –>呈現給用戶UI界面
2.Http請求
GET請求: http://xx.xx.com?name=test1&id=123 //用?分隔URL和傳輸數據,參數之間用&連接 URL有長度限制、明文傳輸,參數在URL中。
3.http響應
狀態碼:1XX:請求被接收,繼續處理 2XX:成功,請求已經被成功處理 3XX:重定向 4XX:客戶端錯誤 5XX:服務器端錯誤
4.http包運行的流程:
(1.)創建Listen Socket 監聽指定端口,等待客戶端的請求到來。
(2.)ListenSocket 接收客戶端的請求,得到Client Socket,通過Client Socket與客戶端通信。
(3.)處理客戶端的請求,首先從Client Socket讀取Http請求的協議頭,如果是post請求,還需要讀取客戶端提交的數據,然後交給相應的handler處理請求,handler處理完後,將數據返回給客戶端。
(4.)具體實現:
初始化一個server, 調用 net.Listen(“tcp”,addr) 監控端口 ,srv.Serve(net.Listener)接收客戶端的請求信息。創建連接,執行gorouting
(5.) Go http的兩個核心功能,conn和ServMux,實現高並發和高性能。
srv.netConn(rw) //每次請求都會創建一個連接,這個鏈接中保存了這次請求的信息,並將該信息傳遞給對應的handler,handler讀取響應的header信息。這樣就保持了每個請求的獨立性。
go c.serve()
type ServeMux struct {
mu sync.RWMutex //鎖,由於請求設計到並發處理,因此需要加鎖
m map[string]muxEnty //路由規則,一個string(路由表達式)對應一個Mux實體{ explicit bool //是否精確匹配 h Handler //這個路由表達式對應哪個handler pattern string //匹配字符串}
hosts bool //是否在任意的規則中帶有host信息
}
type Handler interface {
ServeHTTP(RespnseWriter,*Request) //路由實現器
}
type HandlerFunc func(ResponseWriter, *Request)
// ServeHTTP calls f(w, r).
func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {
f(w, r)
}
func (mux *ServeMux) ServeHTTP(w ResponseWriter, r *Request) {
if r.RequestURI == "*" {
w.Header().Set("Connection", "close")
w.WriteHeader(StatusBadRequest)
return
}
h, _ := mux.Handler(r)
h.ServeHTTP(w, r)
}func (mux *ServeMux) Handler(r *Request) (h Handler, pattern string) {
if r.Method != "CONNECT" {
if p := cleanPath(r.URL.Path); p != r.URL.Path {
_, pattern = mux.handler(r.Host, p)
return RedirectHandler(p, StatusMovedPermanently), pattern
}
}
return mux.handler(r.Host, r.URL.Path)
}func (mux *ServeMux) handler(host, path string) (h Handler, pattern string) {
mux.mu.RLock()
defer mux.mu.RUnlock()// Host-specific pattern takes precedence over generic ones
if mux.hosts {
h, pattern = mux.match(host + path)
}
if h == nil {
h, pattern = mux.match(path)
}
if h == nil {
h, pattern = NotFoundHandler(), ""
}
return
}5.執行流程:
首先調用Http.HandleFunc
按順序做了幾件事:
1 調用了DefaultServeMux的HandleFunc
2 調用了DefaultServeMux的Handle
3 往DefaultServeMux的map[string]muxEntry中增加對應的handler和路由規則
其次調用http.ListenAndServe(":9090", nil)
按順序做了幾件事情:
1 實例化Server
2 調用Server的ListenAndServe()
3 調用net.Listen("tcp", addr)監聽端口
4 啟動一個for循環,在循環體中Accept請求
5 對每個請求實例化一個Conn,並且開啟一個goroutine為這個請求進行服務go c.serve()
6 讀取每個請求的內容w, err := c.readRequest()
7 判斷handler是否為空,如果沒有設置handler(這個例子就沒有設置handler),handler就設置為DefaultServeMux
8 調用handler的ServeHttp
9 在這個例子中,下面就進入到DefaultServeMux.ServeHttp
10 根據request選擇handler,並且進入到這個handler的ServeHTTP
mux.handler(r).ServeHTTP(w, r)
11 選擇handler:A 判斷是否有路由能滿足這個request(循環遍歷ServerMux的muxEntry)
B 如果有路由滿足,調用這個路由handler的ServeHttp
C 如果沒有路由滿足,調用NotFoundHandler的ServeHttp
Golang-web基礎