在講三次握手以前首先要介紹 TCP 報文中兩個重要的字段:一個是序號字段,另外一個是確認號字段,這兩個字段將在握手階段以及整個信息傳輸過程起到重要做用。html
若是不是三次握手,二次兩次的話,服務器就不知道客戶端是否接收到了本身的 SYNACK 報文段,從而沒法創建鏈接;四次握手就顯得多餘了。web
什麼 SYN 是洪泛攻擊? 在 TCP 的三次握手機制的第一步中,客戶端會向服務器發送 SYN 報文段。服務器接收到 SYN 報文段後會爲該TCP分配緩存和變量,若是攻擊分子大量地往服務器發送 SYN 報文段,服務器的鏈接資源終將被耗盡,致使內存溢出沒法繼續服務。redis
解決策略:
當服務器接受到 SYN 報文段時,不直接爲該 TCP 分配資源,而只是打開一個半開的套接字。接着會使用 SYN 報文段的源Id,目的Id,端口號以及只有服務器本身知道的一個祕密函數生成一個 cookie,並把 cookie 做爲序列號響應給客戶端。算法
若是客戶端是正常創建鏈接,將會返回一個確認字段爲 cookie + 1 的報文段。接下來服務器會根據確認報文的源Id,目的Id,端口號以及祕密函數計算出一個結果,若是結果的值 + 1等於確認字段的值,則證實是剛剛請求鏈接的客戶端,這時候才爲該 TCP 分配資源數據庫
這樣一來就不會爲惡意攻擊的 SYN 報文段分配資源空間,避免了攻擊。小程序
當客戶端要服務器斷開鏈接時,客戶端 TCP 會向服務器發送一個特殊的報文段,該報文段的 FIN 標誌位會被置1,接着服務器會向客戶端發送一個確認報文段。而後服務器也會客戶端發送一個 FIN 標誌位爲1的終止報文段,隨後客戶端回送一個確認報文段,服務器當即斷開鏈接。客戶端等待一段時間後也斷開鏈接。後端
其實四次揮手的過程是很容易理解的,因爲 TCP 協議是全雙工的,也就是說客戶端和服務端均可以發起斷開鏈接。兩邊各發起一次斷開鏈接的申請,加上各自的兩次確認,看起來就像執行了四次揮手。瀏覽器
爲何要有 TIME_WAIT 狀態?由於客戶端最後向服務器發送的確認 ACK 是有可能丟失的,當出現超時,服務端會再次發送 FIN 報文段,若是客戶端已經關閉了就收不到了。還有一點是避免新舊鏈接混雜。緩存
大量 CLOSE_WAIT 表示程序出現了問題,對方的 socket 已經關閉鏈接,而我方忙於讀或寫沒有及時關閉鏈接,須要檢查代碼,特別是釋放資源的代碼,或者是處理請求的線程配置。安全
詳情可參考如下博客:
http://www.javashuo.com/article/p-azhbueyb-ce.html
從上面的圖能夠看到滑動窗口左邊的是已發送而且被確認的分組,滑動窗口右邊是尚未輪到的分組。滑動窗口裏面也分爲兩塊,一塊是已經發送可是未被確認的分組,另外一塊是窗口內等待發送的分組。隨着已發送的分組不斷被確認,窗口內等待發送的分組也會不斷被髮送。整個窗口就會往右移動,讓還沒輪到的分組進入窗口內。
能夠看到滑動窗口起到了一個限流的做用,也就是說當前滑動窗口的大小決定了當前 TCP 發送包的速率,而滑動窗口的大小取決於擁塞控制窗口和流量控制窗口的二者間的最小值。
接着就講講什麼是流量控制窗口,什麼是擁塞控制窗口。
先講流量控制:
TCP 是全雙工的,客戶端和服務器都可做爲發送方或接收方,咱們如今假設一個發送方向接收方發送數據的場景來說解流量控制。首先咱們的接收方有一塊接收緩存,當數據來到時會先把數據放到緩存中,上層應用等緩存中有數據時就會到緩存中取數據。假如發送方沒有限制地不斷地向接收方發送數據,接收方的應用程序又沒有及時把接收緩存中的數據讀走,就會出現緩存溢出,數據丟失的現象,爲了解決這個問題,咱們引入流量控制窗口。
假設應用程序最後讀走的數據序號是 lastByteRead,接收緩存中接收到的最後一個數據序號是 lastByteRcv,接收緩存的大小爲 RcvSize,那麼必需要知足 lastByteRcv - lastByteRead <= RcvSize 才能保證接收緩存不會溢出,因此咱們定義流量窗口爲接收緩存剩餘的空間,也就是Rcv = RcvSize - (lastByteRcv - lastByteRead)。只要接收方在響應 ACK 的時候把這個窗口的值帶給發送方,發送方就能知道接收方的接收緩存還有多大的空間,進而設置滑動窗口的大小。
接着講解擁塞控制:
擁塞控制是指發送方先設置一個小的窗口值做爲發送速率,當成功發包並接收到ACK時,便以指數速率增大發送窗口的大小,直到遇到丟包(超時/三個冗餘ACK),才中止並調整窗口的大小。這麼作能最大限度地利用帶寬,又不至於讓網絡環境變得太過擁擠。
最終滑動窗口的值將設置爲流量控制窗口和擁塞控制窗口中的較小值。
HTTP和HTTPS的主要區別在於HTTP協議傳遞的是明文數據,而HTTPS傳遞的是加密過的數據,也就是說HTTPS更具備安全性。也正由HTTPS須要保證安全性,因此它的性能要比HTTP差一點。
單說安全性確定是不夠的,我打算擴展講一下HTTPS是怎麼解決安全性問題的,經過這些HTTP沒有機制,反映出HTTPS與HTTP的區別。下面嘗試把HTTPS加密的過程推導出來。推導過程不涉及複雜的實現細節:
假設如今A和B要進行安全的通訊,那麼究竟怎樣纔算是安全的通訊?很天然地會想到:A和B之間傳遞數據,這些數據只有A和B纔看得懂,中間人就算截取了信息但也看不懂,這纔算得上安全。
爲了能讓A和B才能看懂,就必需要對數據進行加密,並且首先想到的就是對稱加密。對稱加密的意思是A和B各持有一個相同的密鑰,它們傳遞信息時會用密鑰給信息加密,在消息到達端給消息解密,完成安全通訊。
在對稱加密中又會涉及到加密算法的選擇問題。現實世界中,一般是多個客戶端面向一個服務器的狀況,不可能讓每一個客戶端和服務器之間都採用相同的加密算法,若是是這樣那和沒加密差很少。因此註定每一個客戶端和服務器之間都會採用不一樣的加密方式。
要想對不一樣的機器使用不一樣的加密方式,最直接想到的就是使用隨機數。也就說客戶端和服務器之間每次都基於一個隨機數產生加密算法。(具體實現時爲了保證隨機,用到還不止一個隨機數)
這個產生加密算法的過程稱之爲協商,如今問題是協商的過程是透明的,也就是說中間人能夠截獲協商的過程,從而知道咱們的加密方式。爲了解決這個問題,咱們須要對協商的過程進行加密。
之因此能來到這一步,是由於咱們一開始就選擇使用了對稱加密,也就說一開始的對稱加密緻使瞭如今的問題,因此這時咱們不能再使用對稱加密了,不然會陷入死循環。
在密碼學領域,還有一種加密過程叫非對稱加密,它的邏輯是這樣的:通訊雙方一方持有私鑰,一方持有公鑰,通過私鑰加密的信息,都能經過公鑰進行解密。可是通過公鑰加密的數據,只有私鑰能夠解密。
按照非對稱加密的規則,咱們讓服務器持有私鑰,讓客戶端持有公鑰。這樣就能保證客戶端給服務器發送消息的時候是安全的(相反,服務器給客戶端發送消息就是不安全的),咱們能夠把協商時重要的邏輯安排在客戶端給服務器發送信息的過程當中,從而保證了協商過程的安全性。
如今用非對稱加密算法解決了協商的安全問題,可是非對稱加密的前提是客戶端須要得到公鑰,這又是一個問題了,客戶端與服務器打交道以前是互不知道雙方身份的,怎麼才能讓客戶端得到公鑰呢?
也就只有兩種辦法:
方法2顯然是不行的,尚且不說多了一個訪問節點,如何找到公共服務器的地址也是一個待解決的問題,因此仍是使用方法1。
可是方法1存在一個問題:若是中間人把服務器發送給客戶端的公鑰調包了怎麼辦?也就是說客戶端沒法知道發送公鑰的是不是正真的服務器。
客戶端沒法辨識服務端和中間人的問題稱爲「身份驗證」問題,也就是說咱們須要爲服務器向客戶端發送公鑰的過程進行加密。
這下完了,以前咱們因遇到對稱加密的瓶頸選擇了非對稱加密,如今使用非對稱加密也遇到了瓶頸。顯然這兩種加密方式都是不可用的了,不然會再次陷入死循環。
接下來咱們只好經過第三方機構的介入,解決這個問題。首先咱們本身保存有第三方權威機構的公鑰,而後第三方機構使用私鑰對服務器將要發送給客戶端的公鑰進行加密,客戶端接收到這個經加密的公鑰後(數字證書),就能經過本身保存的第三方機構公鑰進行解密。
到這裏爲止,咱們解釋了HTTPS中使用到的對稱加密,非對稱加密,CA,數字證書的概念,可是還差一個叫數字簽名的概念沒有解釋。
在現實生活中,CA不單止會給咱們正常公司發放證書,還會給中間人的壞公司發放證書,若是中間人把發放的證書調包了怎麼辦?這時咱們仍能用CA的私鑰進行解密,可是證書已經被調包了。
那麼客戶端怎樣驗證證書的真僞呢?答案是證書自己會告訴客戶端如何辨認真僞。比方說證書上面有一個證書編號,還有一個如何計算證書編號的方法,客戶端能夠根據計算證書編號的方法計算出本身要得到的證書的編號,而後把這個編號和證書上的編號進行比對,若是同樣證實沒有被調包。
這裏的證書編號指的就是數字簽名,證書指的就是數字證書。
總結一下HTTPS:HTTPS想要保證客戶端與服務器之間的通訊安全,就得使用對稱加密算法進行加密。協商對稱加密算法的過程經過非對稱加密算法來保證。在非對稱加密算法中,客戶端得到公鑰的過程須要第三方機構(CA)經過頒發數字證書保證安全性。
總得來講經過這一系列機制協商出了一個對稱加密算法後,客戶端與服務器之間就能經過該算法進行安全的通訊了。
我的以爲這個問題還能夠擴展一下,試想一下在鍵入 URL 以前,也就是剛開完機的時候,須要聯網,而後才能上網。這個階段包括了獲取本機 IP 地址,獲取 DNS 服務器 IP 地址,得到網關路由器 IP 和 MAC 地址等操做,把這些一塊兒答上去會不會好一些?如下是回答:
首先咱們須要準備一個 DHCP 報文,封裝在一個 UDP 報文段中,裏面包括本機端口號68和目的端口號67,而後到網絡層封裝成數據包裏面包括了本機的初始IP0.0.0.0,和廣播地址255.255.255.255。接着到鏈路層封裝成鏈路層幀。裏面包括廣播地址和本機網卡的MAC地址。最後發送到本地局域網中
這個數據包最終會被局域網中的 DHCP 服務器發現(有可能有多個 DHCP 服務器),DHCP 服務器會把可用的 IP 地址返回給咱們的主機。而後操做系統選擇一個 IP 地址併發送給 DHCP 服務器,最後 DHCP 服務器會返回一個包含本機 IP,DNS 服務器 IP,網關路由器 IP 的報文。
接下來咱們須要經過網關路由器的 IP 地址去得到網關路由器的 MAC 地址,這樣咱們才能夠把獲取網站 IP 的 DNS 請求報文由網關發送給 DNS 服務器。這時候咱們須要準備一個 ARP 請求報文,請求獲取網關路由器的 MAC 地址,這個報文一樣是以廣播的方式發送到局域網中,網關路由器接受到請求報文就會把本身的 MAC 地址返回給本機。
接下來一切都準備好了,能夠開始講鍵入URL以後的事情了:
首先咱們要訪問 DNS 服務器得到網站對應的 IP 地址,這時咱們須要把 DNS 報文封裝到一個 UDP 報文中,進而封裝到網絡層的數據包中,填上源 IP,目的 DNS 服務器 IP 地址。接着封裝鏈路層,填上網卡 MAC 地址和網關路由器 MAC 地址。接下來這個 DNS 請求報文就會經網關路由器發送給 DNS 服務器。
咱們假設 DNS 服務器緩存有該網站的 IP 地址,(若是沒有緩存會進一步向更高級的DNS服務器索要IP地址)。接着 DNS 服務器會返回該域名的 IP 地址。
拿到了該網站的IP地址後就能夠與該網站的服務器創建 TCP 鏈接了。創建 TCP 鏈接須要通過三次握手,過程以下:(更詳細的過程在開頭)
在三次握手創建鏈接後,本機就能夠向服務器發送 HTTP 請求了,服務器接受到了請求會作出響應的響應,把請求的數據發送給本機瀏覽器,最終瀏覽器把服務器響應的數據渲染顯示出來,咱們就看到了五彩繽紛的網頁。
首先狀態碼的開頭不一樣表明不一樣的類型:
1xx:表明指示信息,表示請求已接收,繼續處理
2xx:表明成功,表示請求已被成功接收,理解,接受
3xx:重定向,表示完成請求必須進行進一步的操做
4xx:客戶端錯誤,請求有語法錯誤或請求沒法實現
5xx:服務器端錯誤,服務器未能實現合法的請求
常見狀態碼:
200 OK:正常返回信息
400 Bad Request:客戶端請求有語法錯誤,不能被服務器所理解
403 Forbidden:服務器收到請求,可是拒絕提供服務
404 Not Found:請求資源不存在,輸入了錯誤的URL
500 Internal Server Error:服務器發生不可預期錯誤
503 Server Unavailable:服務器當前不能處理客戶端的請求,一段時間後可能恢復正常
因爲 http 協議是無狀態協議,若是客戶經過瀏覽器訪問 web 應用時沒有一個保存用戶訪問狀態的機制,那麼將不能持續跟蹤應用的操做。好比當用戶往購物車中添加了商品,web 應用必須在用戶瀏覽別的商品的時候仍保存購物車的狀態,以便用戶繼續往購物車中添加商品。
cookie 是瀏覽器的一種緩存機制,它可用於維持客戶端與服務器端之間的會話。因爲下面一題會講到session,因此這裏要強調cookie會將會話保存在客戶端(session則是把會話保存在服務端)
這裏以最多見的登錄案例講解cookie的使用過程:
session 是一種維持客戶端與服務器端會話的機制。可是與 cookie 把會話信息保存在客戶端本地不同,session 把會話保留在瀏覽器端。
咱們一樣以登錄案例爲例子講解 session 的使用過程:
看到這裏可能會引發疑問:把惟一的 session 標識返回給客戶端瀏覽器,而後保存起來,之後訪問時帶上,這難道不是 cookie 嗎?
沒錯,session 只是一種會話機制,在許多 web 應用中,session 機制就是經過 cookie 來實現的。也就是說它只是使用了 cookie 的功能,並非使用 cookie 完成會話保存。與 cookie 在保存客戶端保存會話的機制相反,session 經過 cookie 的功能把會話信息保存到了服務端。
進一步地說,session 是一種維持服務端與客戶端之間會話的機制,它能夠有不一樣的實現。以如今比較流行的小程序爲例,闡述一個 session 的實現方案:
通過上面兩道題的闡述,這道題就很清晰了
參考:
《計算機網絡:自頂向下方法》
http://www.javashuo.com/article/p-snqwjvkn-bu.html
http://www.javashuo.com/article/p-hsektion-cp.html