?
目錄
一、HTTP
1、URL
2、協議格式
3、請求方法
4、狀態碼
5、Header信息
6、會話保持Cookie
7、長連接
8、簡易版HTTP服務器代碼
一、HTTP
我們在編寫網絡通信代碼時,我們可以自己進行協議的定制,但實際有很多優秀的工程師早就寫出了許多非常成熟且好用的應用層協議來供我們直接參考使用,其中最典型的就是 HTTP(超文本傳輸協議),它是一個簡單的請求-響應協議,通常運行在 TCP 之上。所謂應用層協議,就是程序員基于socket接口之上編寫的具體邏輯,做的很多工作都是和文本處理相關的(協議分析與處理),HTTP 協議具有大量的文本分析和協議處理。
1、URL
URL?就是我們平時俗稱的?“網址”。在全球范圍內,只要找到 url 就能訪問該資源。
http://server ip[:80]/a/b/c/d/e.html------------https://server ip[:80]/a/b/c/d/e.html
①要訪問一個服務器,ip 地址和端口號是必須要有的,有 ip 地址就可以找到這臺唯一的機器,能夠訪問到端口號就可以找到給我們提供服務對應端口的進程,可是上圖在 url 中并沒有體現出來,是因為一般在請求時,端口號是被省略的(在請求網絡服務時,對應的端口號都是眾所周知的(客戶端知道))。
②使用瀏覽器訪問 URL(統一資源定位符):通過域名(server ip)找到唯一的一臺網絡主機,而域名后面就是該機器提供服務的進程,接著是客戶想訪問的資源路徑,通過資源路徑找到想要的文件名,可能是圖片或者文本,把資源(客戶想訪問的資源路徑 + 客戶要的文件名)返回給瀏覽器。
③HTTP 的本質就是通過 HTTP 協議從服務端拿下文件資源,而因為文件資源的種類特別多,HTTP ?都能搞定,所以叫做超文本傳輸協議。
④客戶端和服務器通過urlencode 和 urldecode,來翻譯URL的內容。實際當服務器拿到對應的 URL 后,也需要對編碼后的參數進行解碼,此時服務器才能拿到你想要傳遞的參數,解碼實際就是編碼的逆過程。
2、協議格式
HTTP 是基于請求和響應的應用層服務,底層采用 TCP,作為客戶端可以向服務器發起 request,服務器收到這個 request 之后,會對這個 request 做數據分析,得出你想要訪問什么資源,然后服務器再構建 response,完成這一次 HTTP 的請求,返回響應。由于 HTTP 是基于請求和響應的應用層訪問,所以必須要知道 HTTP 對應的請求格式和響應格式。
2.1、HTTP請求
①首行:[方法] + [url] + [版本]
②Header:請求的屬性,冒號分割的鍵值對,每組屬性之間使用 \n 分隔,遇到空行表示 Header 部分結束。
③Body:空行后面的內容都是 Body,Body 允許為空字符串。如果 Body 存在,則在 Header 中會有一個 Content-Length 屬性來標識 Body 的長度。
2.2、HTTP響應
①首行:[版本號] + [狀態碼] + [狀態碼解釋]
②Header:請求的屬性,冒號分割的鍵值對,每組屬性之間使用 \n 分隔,遇到空行表示 Header 部分結束。
③Body:空行后面的內容都是 Body,Body 允許為空字符串。如果 Body 存在,則在 Header 中會有一個 Content-Length 屬性來標識 Body 的長度,如果服務器返回了一個 html 頁面,那么 html 頁面內容就是在 body 中。
2.3、如何保證請求和響應被應用層完整讀取?
HTTP 所有請求字段都是按行為單位的字符串,比如說對于 HTTP 請求,我們使用 while 循環按行讀取,直到遇到空行為止,這樣就可以保證把請求行和請求報頭讀完。而報頭的 key: val 結構就有一個屬性是 Content-Length: XXX,它表示的是正文的長度,由此,正文的也能完整讀取了。
2.4、如果現在我們想獲得name的key值,如何把數據從字符串中反序列化?
①對于報頭部分,其實請求 / 響應報頭布置包含 name: val 信息,后邊還有字符串分隔符:name: val\r\n,序列化直接發送就行,想要反序列化就可以按照 \r\n 來按行提取,所以 HTTP 報頭是用特殊字符進行信息分離。
②對于正文部分,不需要做處理,如果需要的話,可以設計自定義序列化與反序列化方案。
3、請求方法
其中最常用的就是??GET??方法和??POST??方法。
①GET:通過 URL 傳遞參數,要提交的參數拼接到到 url 的后邊。
②POST:通過請求正文提交參數。
因為 POST 方法是通過正文傳參的,所以一般不會回顯,用戶看不到,私密性(不等于安全性,加解密才具有安全性)更好,而 GET 方法會回顯輸入的私密信息,不夠私密。但無論是 GET 還是 POST 方法都不安全(HTTP 請求都是可以被抓到的,想要安全必須加密,就得使用 HTTPS 協議)。一般情況下,傳遞大字段或者較為私密的數據的時候使用 POST 方法,其他的使用 GET 方法。
4、狀態碼
常見的狀態碼,比如?200(OK),404(Not Found),403(Forbidden),302(Redirect,重定向),504(Bad Gateway)
重定向狀態碼:
通過各種方法將各種網絡請求重新定個方向轉到其它位置(跳轉網站),此時這個服務器相當于提供了一個引路的服務。當我們發送請求給服務端,服務端返回一個新的 url,狀態碼是 3,瀏覽器自動用這個新的 url 繼續發送請求給新的地址,所以重定向是由客戶端完成的。而重定向又分為臨時重定向和永久重定向,其中狀態碼 301(Moved Permanently)表示的就是永久重定向,而狀態碼 302(Found)和 307(Temporary Redirect)表示的是臨時重定向。
臨時重定向和永久重定向本質是影響客戶端的標簽,決定客戶端是否需要更新目標地址。
① 如果某個網站是永久重定向,那么第一次訪問該網站時由瀏覽器幫你進行重定向,但后續再訪問該網站時就不需要瀏覽器再進行重定向了,此時訪問的就是重定向后的網站。
② 如果某個網站是臨時重定向,那么每次訪問該網站時如果需要進行重定向,都需要瀏覽器來幫我們完成重定向跳轉到目標網站。
5、Header信息
- Content-Type:數據類型(text / html 等)。
- Content-Length:Body 的長度。
- Host:客戶端告知服務器, 所請求的資源是在哪個主機的哪個端口上。
- User-Agent:聲明用戶的操作系統和瀏覽器版本信息。
- referer:當前頁面是從哪個頁面跳轉過來的。
- location:搭配 3xx 狀態碼使用,告訴客戶端接下來要去哪里訪問。
- Cookie:用于在客戶端存儲少量信息,通常用于實現會話(session)的功能。
6、會話保持Cookie
HTTP 的特征:1、簡單快捷? ? 2、無連接? ? 3、無狀態
HTTP 實際上是一種無狀態協議,每次請求并不會記錄它歷史上請求過什么。HTTP 的每次請求/響應之間是沒有任何關系的,但在使用瀏覽器時發現并不是這樣的,比如在登錄一次 CSDN 后,就算把 CSDN 網站關閉甚至重啟電腦,當再次打開 CSDN 網站時,CSDN 并沒有要求我們再次輸入賬號和密碼,這實際上是通過 Cookie 技術實現的,點擊瀏覽器當中鎖的標志就可以看到對應網站的各種 Cookie 數據。
這些 cookie 數據實際都是對應的服務器方寫的,如果你將對應的某些 cookie 刪除,那么此時可能就需要你重新進行登錄認證了,因為你刪除的可能正好就是你登錄時所設置的 cookie 信息。會話保持不是 HTTP 協議天然具備的特點,而是瀏覽器為了滿足用戶的使用需求,做了相應的工作。
6.1、Cookie技術的設計
用戶在第一次輸入賬號和密碼時,瀏覽器會進行保存(Cookie),近期再次訪問同一個網站(發送 http 請求),瀏覽器會自動將用戶信息添加到報頭中推送給服務器。這樣只要用戶首次輸入密碼,一段時間內將不用再做登錄操作了。Cookie 又分為 Cookie 內存和 Cookie 文件。
6.2、Cookie的內存和文件
Cookie 就是在瀏覽器當中的一個小文件,文件里記錄的就是用戶的私有信息。Cookie 文件可以分為兩種,一種是內存級別的 Cookie 文件,另一種是文件級別的 Cookie 文件。
① 將瀏覽器關掉后再打開,訪問之前登錄過的網站,如果需要你重新輸入賬號和密碼,說明你之前登錄時瀏覽器當中保存的 Cookie 信息是內存級別的。
② 將瀏覽器關掉甚至將電腦重啟再打開,訪問之前登錄過的網站,如果不需要你重新輸入賬戶和密碼,說明你之前登錄時瀏覽器當中保存的 Cookie 信息是文件級別的(真實的文件,保存在磁盤,進程退出也不影響)。
6.3、Cookie安全問題
本地的 Cookie 如果被不法分子拿到了,那么此時這個非法用戶就可以用我們的 Cookie 信息,以我們的身份去訪問我們曾經訪問過的網站,將這種現象稱為 Cookie 被盜取了。
為了保證安全,我們可以把信息保存在服務端,在服務端形成一個文件:Session 文件,而因為有很多 Session 文件,所以給每個文件一個名字:Session ID。并將其返回給瀏覽器,瀏覽器存到 Cookie 的其實是 Session id。接下來我們把 Session ID 放到請求中,然后發送到服務端,在服務端獲取登錄信息(鑒權)。目前只保證了用戶信息的泄漏,接下來只能靠服務端的安全策略保障安全,例如賬號被異地登錄了,服務端察覺后只要讓 session id 失效即可,這樣異地登錄就會讓用戶重新驗證賬號密碼或手機或人臉信息(盡可能確保是本人),一定程度上保障了信息的安全。
7、長連接
HTTP 請求是基于 TCP 協議的,而 TCP 是需要進行連接的。對于一個完整的網頁來說,可能包含多種元素資源,那就需要發起多次 Connect。為了減少連接次數,需要客戶端和服務器均支持長鏈接,建立一條連接,傳輸完后不斷開連接,一直傳遞資源,不用頻繁創建連接。如果是短連接請求了一份資源后就會自動關閉連接。
客戶端和服務端怎么知道是否是長連接呢?
在報頭信息中會有 Connection 字段:
Connection: keep-alive //支持長連接
Connection: close //短連接