1. HTTP協議
1.1、HTTP報文結構
HTTP請求報文
一個HTTP請求報文由請求行(request line)、請求頭部(header)、空行和請求數據4個部分組成

HTTP響應報文
HTTP響應也由三個部分組成,分別是:狀態行、消息報頭、響應正文。

1.2、常見header
- Host, 請求頭
- Accept-Encoding,請求頭,可接受的文本壓縮演算法,如: gzip, deflate
- Accept-Language,請求頭,支持語言,客戶端瀏覽器的設置,如:zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3
- User-Agent,請求頭,瀏覽器信息,如:Mozilla/5.0 (Macintosh; Intel Mac OS X 10.7; rv:12.0) Gecko/20100101
- Cookie,請求頭,伺服器或客戶端在上次設置的COOKIE,包括作用域名(.360buy.com),過期時間,鍵與值。
- Content-Type, 響應的數據類型:text/html;charset=gbk
- Content-Length,響應的數據體大小
- Content-Encoding, 如果為文本、HTML信息,則使用的編碼方式
1.3、URL內容
URL(Uniform Resource Locator,統一資源定位符),URL由三部分組成:資源類型、存放資源的主機域名、資源文件名,URL的一般語法格式為:(帶方括弧[]的為可選項):
protocol://hostname[:port]/path/[;parameters][?query]#fragment格式說明:
- protocol(協議):指定使用的傳輸協議, 最常用的是HTTP協議,它也是目前WWW中應用最廣的協議。
- ftp 通過 FTP訪問資源。格式 ftp://
- http 通過 HTTP 訪問該資源。 格式 http://
- https 通過安全的 HTTPS 訪問該資源。 格式 https://
- hostname(主機名):是指存放資源的伺服器的域名系統 (DNS) 主機名或 IP 地址。
- :port(埠號):整數,可選,省略時使用方案的默認埠,各種傳輸協議都有默認的埠號,如http的默認埠為80。如果輸入時省略,則使用默認埠號。有時候出於安全或其他考慮,可以在伺服器上對埠進行重定義,即採用非標準埠號,此時,URL中就不能省略埠號這一項。
- path(路徑):由零或多個「/」符號隔開的字元串,一般用來表示主機上的一個目錄或文件地址。
- ;parameters(參數):這是用於指定特殊參數的可選項。
- ?query(查詢):可選,用於給動態網頁(如使用CGI、ISAPI、PHP/JSP/ASP/ASP.NET等技術製作的網頁)傳遞參數,可有多個參數,用「&」符號隔開,每個參數的名和值用「=」符號隔開。
- fragment(信息片斷):字元串,用於指定網路資源中的片斷。例如一個網頁中有多個名詞解釋,可使用fragment直接定位到某一名詞解釋。
1.4、KeepAlive參數
- KeepAlive值是個布爾值,有兩個值On和Off,簡單來說,當值為On的時候,用戶發起HTTP請求後,Apache不會立刻關閉這個連接,當還有用戶發起HTTP請求時,還會使用這個連接,
- 什麼時候關閉呢?看KeepAliveTimeout這個值,當時間達到KeepAliveTimeout這個值的時候才會關閉連接。當值為Off的時候,用戶發起HTTP請求後,Apache會立刻關閉這個連接,缺點就是每次訪問都要執行一次TCP握手,增加了CPU的開銷。
1.5、狀態碼
- 狀態碼200表示伺服器響應成功,伺服器找到了客戶端請求的內容,並將內容發送給了客戶端。
- 狀態碼302表示臨時跳轉。
- 狀態碼301代表的是永久性的重定向。
- 304狀態碼,被請求的資源內容沒有發生更改。
- 401 (未授權) 請求要求身份驗證。 對於需要登錄的網頁,伺服器可能返回此響應。
- 403 (禁止) 伺服器拒絕請求。
- 404 (未找到) 伺服器找不到請求的網頁。
- 500 (伺服器內部錯誤) 伺服器遇到錯誤,無法完成請求。
- 501 (尚未實施) 伺服器不具備完成請求的功能。 例如,伺服器無法識別請求方法時可能會返回此代碼。
- 502 (錯誤網關) 伺服器作為網關或代理,從上游伺服器收到無效響應。
- 503 (服務不可用) 伺服器目前無法使用(由於超載或停機維護)。 通常,這只是暫時狀態。
- 504 (網關超時) 伺服器作為網關或代理,但是沒有及時從上游伺服器收到請求。
- 505 (HTTP 版本不受支持) 伺服器不支持請求中所用的 HTTP 協議版本。
1.6、HTTP1.0/1.1/2.0 的區別
HTTP1.0最早在網頁中使用是在1996年,那個時候只是使用一些較為簡單的網頁上和網路請求上,而HTTP1.1則在1999年才開始廣泛應用於現在的各大瀏覽器網路請求中,同時HTTP1.1也是當前使用最為廣泛的HTTP協議
HTTP 1.0
HTTP 1.0 是在 1996 年引入的,從那時開始,它的普及率就達到了驚人的效果。
- HTTP 1.0 僅僅提供了最基本的認證,這時候用戶名和密碼還未經加密,因此很容易收到窺探。
- HTTP 1.0 被設計用來使用短鏈接,即每次發送數據都會經過 TCP 的三次握手和四次揮手,效率比較低。
- HTTP 1.0 只使用 header 中的 If-Modified-Since 和 Expires 作為緩存失效的標準。
- HTTP 1.0 不支持斷點續傳,也就是說,每次都會傳送全部的頁面和數據。
- HTTP 1.0 認為每台計算機只能綁定一個 IP,所以請求消息中的 URL 並沒有傳遞主機名(hostname)。
HTTP 1.1
HTTP 1.1 是 HTTP 1.0 開發三年後出現的,也就是 1999 年,它做出了以下方面的變化
- HTTP 1.1 使用了摘要演算法來進行身份驗證
- HTTP 1.1 默認使用長連接,長連接就是只需一次建立就可以傳輸多次數據,傳輸完成後,只需要一次切斷連接即可。長連接的連接時長可以通過請求頭中的 keep-alive 來設置
- HTTP 1.1 中新增加了 E-tag,If-Unmodified-Since, If-Match, If-None-Match 等緩存控制標頭來控制緩存失效。
- HTTP 1.1 支持斷點續傳,通過使用請求頭中的 Range 來實現。
- HTTP 1.1 使用了虛擬網路,在一台物理伺服器上可以存在多個虛擬主機(Multi-homed Web Servers),並且它們共享一個IP地址。
HTTP 2.0
HTTP 2.0 是 2015 年開發出來的標準,它主要做的改變如下
- 頭部壓縮,由於 HTTP 1.1 經常會出現 User-Agent、Cookie、Accept、Server、Range 等欄位可能會佔用幾百甚至幾千位元組,而 Body 卻經常只有幾十位元組,所以導致頭部偏重。HTTP 2.0 使用 HPACK 演算法進行壓縮。
- 二進位格式,HTTP 2.0 使用了更加靠近 TCP/IP 的二進位格式,而拋棄了 ASCII 碼,提升了解析效率
- 強化安全,由於安全已經成為重中之重,所以 HTTP2.0 一般都跑在 HTTPS 上。
- 多路復用,即每一個請求都是是用作連接共享。一個請求對應一個id,這樣一個連接上可以有多個請求。
2. 客戶端與伺服器通信
2.1、通信模型
目前主流的網路通信模型有以下兩種:
- 客戶/伺服器結構(Client/Server,縮寫為C/S,胖客戶):典型的C/S結構網路系統需要相應的客戶端才能實現通信。目前大多數APP都是這種模式,如QQ、微博等。
- 瀏覽器/伺服器結構(Browser/Server,縮寫為B/S,瘦客戶):典型的B/S結構網路系統只要通過瀏覽器即可訪問,不需要在客戶端機安裝特定的軟體。
2.2、通信方式
TCP通信
- 這種通信方式是實現C/S模式應用程序的主要方式。TCP是可靠的連接通信技術,主要使用套接字(Socket)。 Socket是TCP/IP協議中的傳輸層介面。TCP通信是使用TCP/IP協議、建立在穩定連接基礎上的、以流傳輸數據的通信方式。
- TCP(Transfer Control Protocol)協議是一種面向連接的、提供可靠傳輸的協議。它可以確保接收方完全正確地接收到發送方所發送的全部數據。發送方和接收方之間的兩個埠必須建立連接,以便在TCP協議的基礎上進行通信。在程序中,埠之間建立連接一般使用Socket(套接字)方法。
- 當伺服器的Socket等待伺服器請求(即等待建立連接)時,客戶機的Socket可以要求進行連接,一旦這兩個Socket連接成功,它們就可以進行雙向數據傳輸。TCP協議為實現可靠的數據傳輸提供了一個點對點的通道。
HTTP協議通信
這種通信方式實現B/S模式應用程序的主要方式。HTTP協議簡稱超文本傳輸協議,它是應用層協議,主要解決如何包裝數據,它建立在TCP/IP協議之上的一種應用,它是一種通用的、無狀態的、面向對象的協議。 HTTP協議的作用原理包括四個步驟:
- 連接:Web瀏覽器與Web伺服器建立連接。
- 請求:Web瀏覽器通過socket向Web伺服器提交請求。HTTP的請求一般是GET或POST命令(POST用於FORM參數的傳遞)。
- 應答:Web瀏覽器提交請求後,通過HTTP協議傳送給Web伺服器。Web伺服器接到後,進行事務處理,處理結果又通過HTTP傳回給Web瀏覽器,從而在Web瀏覽器上顯示出所請求的頁面。
- 關閉連接:當應答結束後,Web瀏覽器與Web伺服器必須斷開,以保證其它Web瀏覽器能夠與Web伺服器建立連接。
3. HTTPS加密
3.1、加密過程
- 客戶端請求伺服器獲取 證書公鑰
- 客戶端(SSL/TLS)解析證書(無效會彈出警告)
- 生成隨機值
- 用 公鑰加密 隨機值生成密鑰
- 客戶端將 秘鑰 發送給伺服器
- 服務端用 私鑰 解密 秘鑰 得到隨機值
- 將信息和隨機值混合在一起 進行對稱加密
- 將加密的內容發送給客戶端
3.2、中間人攻擊
中間人的確無法得到瀏覽器生成的密鑰B,這個密鑰本身被公鑰A加密了,只有伺服器才有私鑰A』解開拿到它呀!然而中間人卻完全不需要拿到密鑰A』就能幹壞事了。請看:
- 某網站擁有用於非對稱加密的公鑰A、私鑰A』。
- 瀏覽器向網站伺服器請求,伺服器把公鑰A明文給傳輸瀏覽器。
- 中間人劫持到公鑰A,保存下來,把數據包中的公鑰A替換成自己偽造的公鑰B(它當然也擁有公鑰B對應的私鑰B』)。
- 瀏覽器隨機生成一個用於對稱加密的密鑰X,用公鑰B(瀏覽器不知道公鑰被替換了)加密後傳給伺服器。
- 中間人劫持後用私鑰B』解密得到密鑰X,再用公鑰A加密後傳給伺服器。
- 伺服器拿到後用私鑰A』解密得到密鑰X。
這樣在雙方都不會發現異常的情況下,中間人得到了密鑰B。根本原因是瀏覽器無法確認自己收到的公鑰是不是網站自己的
3.3、CA證書
CA證書是由CA(Certification Authority)認證機構發布的數字證書。其內容包含:電子簽證機關的信息、公鑰用戶信息、公鑰、簽名和有效期。這裡的公鑰服務端的公鑰,這裡的簽名是指:用hash散列函數計算公開的明文信息的信息摘要,然後採用CA的私鑰對信息摘要進行加密,加密完的密文就是簽名。 即:證書 = 公鑰 + 簽名 +申請者和頒發者的信息。 客戶端中因為在操作系統中就預置了CA的公鑰,所以支持解密簽名(因為簽名使用CA的私鑰加密的)
SSL證書是CA證書的一種,CA是負責簽發證書、認證證書、管理已頒發證書的機關。 它制定政策和具體步驟來驗證、識別用戶身份,並對用戶證書進行簽名,以確保證書持有者的身份和公鑰的擁有權。 SSL證書(http://ssl.idcspy.net/)就是CA機構簽發的。 一般的CA證書,可以直接在WINDOWS上生成。
- SSL證書,用於加密HTTP協議,也就是HTTPS。
- 代碼簽名證書,用於簽名二進位文件,比如Windows內核驅動,Firefox插件,Java代碼簽名等等。
- 客戶端證書,用於加密郵件。
- 雙因素證書,網銀專業版使用的USB Key裡面用的就是這種類型的證書。
網站在使用HTTPS前,需要向「CA機構」申請頒發一份數字證書,數字證書里有證書持有者、證書持有者的公鑰等信息,伺服器把證書傳輸給瀏覽器,瀏覽器從證書里取公鑰就行了,證書就如身份證一樣,可以證明「該公鑰對應該網站」。然而這裡又有一個顯而易見的問題了,證書本身的傳輸過程中,如何防止被篡改?即如何證明證書本身的真實性?身份證有一些防偽技術,數字證書怎麼防偽呢?
3.4、數字簽名
我們把證書內容生成一份「簽名」,比對證書內容和簽名是否一致就能察覺是否被篡改。這種技術就叫數字簽名。
數字簽名製作過程:
- CA擁有非對稱加密的私鑰和公鑰。
- CA對證書明文信息進行hash。
- 對hash後的值用私鑰加密,得到數字簽名。
明文和數字簽名共同組成了數字證書,這樣一份數字證書就可以頒發給網站了。那瀏覽器拿到伺服器傳來的數字證書後,如何驗證它是不是真的?(有沒有被篡改、掉包)
瀏覽器驗證過程:
- 拿到證書,得到明文T,數字簽名S。
- 用CA機構的公鑰對S解密(由於是瀏覽器信任的機構,所以瀏覽器保有它的公鑰。詳情見下文),得到S』。
- 用證書里說明的hash演算法對明文T進行hash得到T』。
- 比較S』是否等於T』,等於則表明證書可信。
4. Session、Cookie & Token
4.1、cookie
- HTTP協議本身是無狀態的。什麼是無狀態呢,即伺服器無法判斷用戶身份。
- **cookie是由Web伺服器保存在用戶瀏覽器上的小文件(key-value格式),包含用戶相關的信息。**客戶端向伺服器發起請求,如果伺服器需要記錄該用戶狀態,就使用response向客戶端瀏覽器頒發一個Cookie。客戶端瀏覽器會把Cookie保存起來。當瀏覽器再請求該網站時,瀏覽器把請求的網址連同該Cookie一同提交給伺服器。伺服器檢查該Cookie,以此來辨認用戶身份。
4.2、session
- session是依賴Cookie實現的。session是伺服器端對象session 是瀏覽器和伺服器會話過程中,伺服器分配的一塊儲存空間。伺服器默認為瀏覽器在cookie中設置 sessionid,瀏覽器在向伺服器請求過程中傳輸 cookie 包含 sessionid ,伺服器根據 sessionid 獲取出會話中存儲的信息,然後確定會話的身份信息。
- 典型的場景是購物車,當你要添加商品到購物車的時候,系統不知道是哪個用戶操作的,因為 HTTP 協議是無狀態的。服務端給特定的用戶創建特定的 Session 之後就可以標識這個用戶並且跟蹤這個用戶了。
cookie與session區別
- 存儲位置與安全性:cookie數據存放在客戶端上,安全性較差,session數據放在伺服器上,安全性相對更高;
- 存儲空間:單個cookie保存的數據不能超過4K,**很多瀏覽器都限制一個站點最多保存20個cookie,**session無此限制
- 佔用伺服器資源:session一定時間內保存在伺服器上,當訪問增多,佔用伺服器性能,考慮到伺服器性能方面,應當使用cookie。
4.3、Token
Token的引入:Token是在客戶端頻繁向服務端請求數據,服務端頻繁的去資料庫查詢用戶名和密碼並進行對比,判斷用戶名和密碼正確與否,並作出相應提示,在這樣的背景下,Token便應運而生。
Token的定義:Token是服務端生成的一串字元串,以作客戶端進行請求的一個令牌,當第一次登錄後,伺服器生成一個Token便將此Token返回給客戶端,以後客戶端只需帶上這個Token前來請求數據即可,無需再次帶上用戶名和密碼。
使用Token的目的:Token的目的是為了減輕伺服器的壓力,減少頻繁的查詢資料庫,使伺服器更加健壯。
Token 是在服務端產生的。如果前端使用用戶名/密碼向服務端請求認證,服務端認證成功,那麼在服務端會返回 Token 給前端。前端可以在每次請求的時候帶上 Token 證明自己的合法地位
session與token區別
- session機制存在伺服器壓力增大,CSRF跨站偽造請求攻擊,擴展性不強等問題;
- session存儲在伺服器端,token存儲在客戶端
- token提供認證和授權功能,作為身份認證,token安全性比session好;
- session這種會話存儲方式方式只適用於客戶端代碼和服務端代碼運行在同一台伺服器上,token適用於項目級的前後端分離(前後端代碼運行在不同的伺服器下)
5. socket網路編程
5.1、socket套接字
- Socket的英文原義是「孔」或「插座」。作為BSD UNIX的進程通信機制,取後一種意思。通常也稱作」套接字」,用於描述IP地址和埠,是一個通信鏈的句柄,可以用來實現不同虛擬機或不同計算機之間的通信。
- 將傳輸層及以下的網路協議封裝,提供簡單使用的介面(API)給應用層的軟體,專門面向C/S架構模型設計的
- 三元組:IP地址、協議、埠號
網路層的「ip地址」可以唯一標識網路中的主機,而傳輸層的「協議+埠」可以唯一標識主機中的應用程序(進程)。這樣利用三元組(ip地址,協議,埠)就可以標識網路的進程了,網路中的進程通信就可以利用這個標誌與其它進程進行交互。
5.2、套接字的連接過程
- 伺服器監聽:不指定具體的客戶端套接字,處於等待連接的狀態,實時監控網路狀態
- 客戶端請求:指由客戶端的套接字提出請求,目標是伺服器端的套接字,需要指出伺服器端套接字的地址和埠號
- 連接確認:當伺服器端套接字監聽到客戶端套接字的連接請求,就響應請求建立一個新的進程,並返回客戶端伺服器的套接字描述,當客戶端確認描述,連接就正式建立,伺服器端繼續處於監聽狀態
5.3、套接字(socket)函數
服務端
- s.bind() 綁定(主機,埠號)到套接字
- s.listen() 開始TCP監聽必須制定最大連接數(操作系統同時能夠鏈接的最大數目)
- s.accept() 被動接受TCP客戶的連接,(阻塞式)等待連接到來(阻塞:無響應直到接受到連接請求)
客戶端
- s.connect() 主動初始化TCP伺服器連接
- s.connec_ex() connect()函數的擴展版本,出錯時返回出錯碼,不拋出異常
公共用途
- s.recv() 接收TCP數據不可接收』空』
- s.send() 發送TCP數據待發送數量大於己端緩存剩餘區空間時,數據丟失,不會發完
- s.sendall() 發送完整的TCP數據,循環調用s.send通常給數據加上報頭將數據打包更安全可靠,不常用sendall
- s.recvfrom() 接收UDP數據
- s.sendto() 發送UDP數據
- s.getpeername() 連接到當前套接字的遠端的地址
- s.getsockname() 當前套接字的地址
- s.getsockopt() 返回指定套接字的參數
- s.setsockopt() 設置指定套接字的參數
- s.close() 關閉套接字
面向鎖的套接字方法
- s.setblocking() 設置套接字的阻塞與非阻塞模式
- s.settimeout() 設置阻塞套接字操作的超時時間
- s.gettimeout() 得到阻塞套接字操作的超時時間
面向文件的套接字的函數
- s.fileno() 套接字的文件描述符
- s.makefile() 創建一個與該套接字相關的文件
末
【面試系列】文章會持續更新,歡迎關注公眾號「任冬學編程」,聽說點贊都能脫單哦!
– END –
原創文章,作者:投稿專員,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/208693.html
微信掃一掃
支付寶掃一掃