web服務器的工作原理
- 客戶端通過TCP/IP協議建立到服務器的TCP的連接
- 客戶端向服務器發送HTTP協議請求包,請求服務器裡的資源文檔
- 服務器向客戶端發送HTTP協議應答包,如果請求的資源包含動態語言的內容,那麼服務器會調用動態語言解釋引擎負責處理動態內容,並將處理得到的數據返回給客戶端
- 客戶端與服務器斷開。由客戶端解釋HTML文檔,渲染圖形結果
URL和DNS解析
URL(Uniform Resource Locator)
統一資源定位符的英文縮寫,基本格式如下:
- scheme://host[:port#]/path/.../[?query-string][#anchor]
- scheme 指定底層使用協議(http,https,ftp)
- host HTTP服務器的IP地址或者域名
- port# HTTP服務器默認端口是80,可以省略。如果使用了別的端口必須指定
- path 訪問資源的路徑
- query-string 發送給http服務器的數據
- anchor 錨
DNS(Domain Name System)
域名系統英文縮寫,使用TCP/IP網絡,從事將主機名或者域名轉換為實際IP地址的工作
DNS解析過程
- 瀏覽器中輸入域名,操作系統會先檢查自己本地的hosts文件是否有這個網絡映射關係,如果有,就先調用這個IP地址映射,完成域名解析
- hosts沒有域名,查找本地DNS解析器緩存,如果有直接返回
- 還沒找到,會查找TCP/IP參數中設置的首選DNS服務器,我們叫它本地DNS服務器,此服務收到查詢時,如果要查詢的域名包含在本地配置區域資源中,則返回解析結果給客戶機,完成域名解析,此解析具有權威性
- 如果要查詢的域名,不由本地DNS服務器區域解析,但該服務已經緩存了地址映射關係,則調用這個IP地址映射,完成域名解析,此解析不具有權威性
- 上述過程實習,則根據本地DNS服務器的設置進行查詢,如果未用轉發模式,則把請求發給根服務器,根服務器返回一個負責該頂級服務器的IP,本地DNS服務器收到IP信息後,再連接該IP上的服務器進行解析,如果仍然無法解析,則發送下一級DNS服務器,重複操作,直到找到
- 轉發模式則把請求轉發至上一級DNS服務器,如果仍然不能解析,再轉發給上上級。不管是否轉發,最後都把結果返回給本地DNS服務器
- 上述一個是迭代查詢,一個是遞歸查詢。遞歸查詢的過程是查詢者發生了更替,而迭代查詢過程,查詢者不變
HTTP協議詳解
HTTP是一種讓web服務器與瀏覽器(客戶端)通過internet發送與接受數據的協議
建立在TCP協議之上,一般採用80端口
它是一個請求、響應協議。客戶端建立連接併發送請求。服務端不能主動去與客戶端聯繫,也不能發送一個回調連接,客戶端可提前中斷連接。
HTTP請求是無狀態的,每個請求之間沒有關聯。為了解決這個問題引入了cookie機制
Dos(拒絕服務攻擊)和Ddos(分佈式拒絕服務攻擊),是一種利用TCP協議缺陷,發送大量偽造TCP連接請求,從而使被攻擊方資源耗盡
HTTP請求包
- Request line
- Request header
- body
請求方法
GET、PSOT、PUT、DELETE
GET和POST區別
- GET提交的數據放在URL之後,以?分割URL和傳輸數據,參數之間以&相連。POST方法把提交數據放在HTTP的body中
- GET提交數據大小有限制,因為瀏覽器對URL長度有限制,而POST方法提交數據沒有限制
- GET提交數據有安全問題,用戶名和密碼都出現在URL上,如果頁面被緩存其他人可以訪問這臺機器就可以獲得帳號和密碼
HTTP響應包
狀態行
服務器使用的WEB軟件名及版本、發送時間、服務器發送信息的類型、表示http包的分段發送、保持連接狀態、主題內容長度、空行用來分割消息頭和主題、消息體
狀態行由HTTP協議版本號、狀態嗎、狀態消息三部分組成
狀態嗎
- 1XX 提示信息--表示請求被成功接收,繼續處理
- 2XX 成功--表示請求被成功接收,理解,接受
- 3XX 重定向--要完成請求必須進行更進一步處理
- 4XX 客戶端錯誤--請求語法錯誤或者請求無法實現
- 5XX 服務器端錯誤--服務器未能實現合法請求
HTTP協議和Connection:keep_alive的區別
HTTP是一個無狀態面向連接的協議,無狀不代表HTTP不能保持TCP連接
keep-alive,當一個網頁打開完成後,客戶端和服務端之間用於HTTP數據的TCP連接不會關閉,,再次訪問時,繼續使用之前建立的連接
keep-alive不會永久保持連接,有一個保持時間
第一次請求url,服務器返回的是html頁面,然後瀏覽器開始渲染HTML:當解析到HTML DOM裡面的圖片連接,css腳本和js腳本的連接,瀏覽器會自動發起一個請求靜態資源的HTTP請求,獲取相應靜態資源,厚燃瀏覽器會渲染出來,最終將所有資源整合、渲染、完整展現在屏幕上。
網頁優化有一向措施是減少HTTP請求次數,把儘量多的css和js資源合併在一起
http包運行機制
創建listen socket,監聽指定端口,等待客戶端請求到來
listen socket接受客戶端的請求,得到client socket,接下來通過client socket與客戶端通信
處理客戶端請求,先從client socket讀取http請求的協議頭,如果是POST方法,還可能要讀取客戶端提交的數據,然後交給相應的handler處理請求,handler處理完畢後,通過client socket寫給客戶端
梳理代碼執行過程
- 首先調用Http.HandleFunc,按順序做如下操作
- 調用DefaultServerMux的HandleFunc
- 調用DefaultServerMux的Handle
- 往DefaultServeMux的map[string]muxEntry中增加對應的handler和路由規則
- 其次調用http.ListenAndServe,按順序做如下操作
- 實例化Server
- 調用Server的ListenAndServe()
- 調用net.listen("tcp",addr)監聽端口
- 啟動一個for循環,在循環體中Accept請求
- 對每個請求實例化一個Conn,並且開啟一個goroutine為這個請求進行服務go c.serve()
- 讀取每個請求的內容w, err := c.readRequest()
- 判斷handler是否為空,如果沒有設置handler,handler就設置為DefaultServeMux
- 調用handler的ServeHttp
- 根據request選擇handler,並且進入到這個handler的ServeHttp
- 選擇handler
- 判斷是否有路由能滿足這個request
- 如果有路由滿足,調用路由handler的ServeHttp
- 如果沒有路由滿足,調用NotFoundHandler的ServeHttp
表單
Request本身提供了FormValue()函數,如r.Form["username"]可以寫成r.FormValue("username")
r.FormValue會自動調用r.ParseForm
模版使用
變量名首字母要大寫,不然模版無法識別
閱讀更多 oscube 的文章