再談協(xié)議
? ? ? ? 在之前利用套接字進(jìn)行通信的時(shí)候,我們都是利用 “字符串” 進(jìn)行流式的發(fā)送接收,但是我們平常進(jìn)行交流通信肯定不能只是簡(jiǎn)單的發(fā)送字符串。
? ? ? ? 比如我們用QQ進(jìn)行聊天,我們不僅需要得到對(duì)方發(fā)送的消息,還要知道對(duì)方的昵稱(chēng),頭像等一系列數(shù)據(jù),也就是說(shuō)我們需要得到一個(gè)結(jié)構(gòu)化的數(shù)據(jù)!
? ? ? ??而想要正確的得到一個(gè)結(jié)構(gòu)化的數(shù)據(jù),就需要我們定制一層應(yīng)用層協(xié)議或者使用特定的應(yīng)用層協(xié)議。
應(yīng)用層協(xié)議
? ? ? ? 無(wú)論是哪一層的協(xié)議,我們都會(huì)給數(shù)據(jù)添加自定義的報(bào)頭,應(yīng)用層協(xié)議的報(bào)頭也不例外。
報(bào)頭:該層協(xié)議所需要的一些特定的數(shù)據(jù)?
? ? ? ? 而只有添加了報(bào)頭后,再將數(shù)據(jù)根據(jù)協(xié)議內(nèi)容來(lái)序列化或者反序列化才能保證正確傳輸數(shù)據(jù)。
序列化:將結(jié)構(gòu)化的數(shù)據(jù)通過(guò)協(xié)議內(nèi)容轉(zhuǎn)化為可以進(jìn)行網(wǎng)絡(luò)傳輸?shù)男问?/strong>(如字符串)
反序列化:將接收到的數(shù)據(jù)通過(guò)協(xié)議內(nèi)容轉(zhuǎn)化為結(jié)構(gòu)化的數(shù)據(jù)
? ? ? ? 而添加報(bào)頭就需要明確報(bào)文和報(bào)文邊界,有以下三種方式
- 定長(zhǎng):使用固定的長(zhǎng)度表示報(bào)文
- 特殊符號(hào):用特殊符號(hào)分隔報(bào)文和報(bào)頭
- 自描述方式:報(bào)文內(nèi)部包含了報(bào)文長(zhǎng)度等一些能夠描述報(bào)文邊界位置的信息
?Http協(xié)議
? ? ? ? 雖說(shuō)我們能夠自己定義協(xié)議,但是定義協(xié)議費(fèi)時(shí)費(fèi)力,還不能出差錯(cuò)。
? ? ? ? 而現(xiàn)實(shí)中已經(jīng)有很多大佬給我們定制了現(xiàn)成的協(xié)議,讓我們使用,比如——Http協(xié)議;
? ? ? ??Http默認(rèn)端口---80;
URL? ??
- ?URL:統(tǒng)一資源定位符(也就是網(wǎng)址)
? ? ? ? ?http協(xié)議的URL格式如上。
? ? ? ? 實(shí)際上,我們?cè)L問(wèn)的資源都是存儲(chǔ)在對(duì)應(yīng)網(wǎng)站的服務(wù)器的磁盤(pán)上的,因此我們?cè)L問(wèn)的URL也需要帶上訪(fǎng)問(wèn)的文件的路徑。
? ? ? ? 而這個(gè)服務(wù)器地址就是服務(wù)器的ip地址。
? ? ? ? 最后,ip地址加上端口號(hào)和文件路徑,就能夠成功的請(qǐng)求到服務(wù)器的資源。
urlencode和urldecode
? ? ? ? 在URL中,有一些特殊字符被當(dāng)做特殊意義理解了,比如 '/','@' 之類(lèi)的,因此當(dāng)我們使用瀏覽器進(jìn)行搜索的時(shí)候,瀏覽器會(huì)將搜索的內(nèi)容做一些特殊處理。
????????
? ? ? ? ?比如我們搜索c++,就會(huì)發(fā)現(xiàn) ++ 這兩個(gè)字符被替換成了 '%2B' 的樣式,這就是urlencode;
? ? ? ? 而 urldecode 則是將對(duì)應(yīng)的字符翻譯成原來(lái)的模樣。
- urlencode : 將中文和特殊字符給轉(zhuǎn)義化
- urldecode :將url請(qǐng)求中的轉(zhuǎn)移化的字符進(jìn)行解碼
? ? ? ? 每當(dāng)我們向服務(wù)器請(qǐng)求資源時(shí),瀏覽器就會(huì)向服務(wù)器發(fā)起請(qǐng)求。
Http請(qǐng)求格式
? ? ? ? ?每一個(gè)瀏覽器向服務(wù)器發(fā)送請(qǐng)求時(shí),瀏覽器會(huì)發(fā)送這么長(zhǎng)一串報(bào)頭給服務(wù)器。
? ? ? ? 這個(gè)報(bào)頭有很多信息,比如 Conten-Length(正文長(zhǎng)度)等一些信息。
- 首行格式: 【方法】 + 【url】+ 【http協(xié)議版本】
- Header:請(qǐng)求的屬性,冒號(hào)分割的鍵值對(duì),每組之間用 '\n'分割,在Header之后便是空行
- body:空行后面的內(nèi)容都是Body,?Body允許為空字符串. 如果Body存在, 則在Header中會(huì)有一個(gè) Content-Length屬性來(lái)標(biāo)識(shí)Body的長(zhǎng)度
? ? ? ? 當(dāng)服務(wù)器收到請(qǐng)求后,就會(huì)發(fā)送對(duì)應(yīng)的響應(yīng)。?
Http響應(yīng)格式
- 首行:【版本號(hào)】+【狀態(tài)碼】+【狀態(tài)碼解釋】
- Header:請(qǐng)求的屬性,以冒號(hào)分割的鍵值對(duì),每行以'\n'分割,遇到空行Header結(jié)束
- body:空行后就是body,允許body為空字符串,若body存在,Header中會(huì)由一個(gè)Content-Length來(lái)表示body長(zhǎng)度,若返回的是一個(gè)html頁(yè)面,那個(gè)html頁(yè)面內(nèi)容就在body中
Http的方法
? ? ? ? ?在這么多方法中,Get和Post是用的最多的,那么Get和Post之間有什么區(qū)別呢?
使用Get方法
? ? ?
? ? ? ? ?當(dāng)我們使用Get方式提交表單的時(shí)候,我們發(fā)現(xiàn)URL中會(huì)存在我們輸入的用戶(hù)名和密碼
? ? ? ? ?也就是說(shuō)Get方法是通過(guò)URL來(lái)傳參的。
使用Post方式
? ? ? ? ?而是用Post方式來(lái)訪(fǎng)問(wèn)則不會(huì)在URL中看到賬號(hào)和密碼
? ? ? ? Post方式中的賬號(hào)和密碼都是存儲(chǔ)在正文當(dāng)中的。?
?Get和Post的區(qū)別
- Get通過(guò)URL傳參,Post通過(guò)正文傳參,Post更有私密性
- Get能夠傳遞的參數(shù)長(zhǎng)度有限,Post則沒(méi)有該限制
- Get請(qǐng)求的參數(shù)會(huì)保存在瀏覽器記錄中,Post則不會(huì)
? ? ? ? 雖說(shuō)Post更具有私密性,但是實(shí)際上它們二者都不是安全的,只是Post更加具有私密性罷了
Http狀態(tài)碼
????????
- ? 常見(jiàn)的狀態(tài)碼有 200(OK),404(Not Found),403(Forbidden),302(Redirect)等等。?
????????其中3開(kāi)頭的狀態(tài)碼需要詳細(xì)講一下。
? ? ? ? ?重定向分為臨時(shí)重定向和永久重定向。
- 臨時(shí)重定向:狀態(tài)碼302,對(duì)舊網(wǎng)址沒(méi)有影響,但新網(wǎng)址沒(méi)有排名
- 永久重定向:狀態(tài)碼301,新網(wǎng)址完全繼承舊網(wǎng)址,舊網(wǎng)址的排名清零
現(xiàn)象:
- 永久重定向時(shí),瀏覽器會(huì)將輸入欄網(wǎng)址自動(dòng)更新為新網(wǎng)址
- 臨時(shí)重定向時(shí),瀏覽器的輸入欄網(wǎng)址依舊為舊網(wǎng)址,但是內(nèi)容是新網(wǎng)址
Http常見(jiàn)Header
- Content-Type:數(shù)據(jù)類(lèi)型(text/html之類(lèi)的)
- Content-Length:Body的長(zhǎng)度
- Host:客戶(hù)端告知服務(wù)端,所請(qǐng)求的資源在哪個(gè)主機(jī)上
- User-Agent:聲明用戶(hù)所用的操作系統(tǒng)和瀏覽器版本信息
- referer:當(dāng)前頁(yè)面是從哪個(gè)頁(yè)面跳轉(zhuǎn)過(guò)來(lái)的
- location:搭配3xx的狀態(tài)碼,告知客戶(hù)端跳轉(zhuǎn)到哪個(gè)頁(yè)面
- Cookie:用于在客戶(hù)端存儲(chǔ)少量信息,用于實(shí)現(xiàn)Session功能
長(zhǎng)連接
? ? ? ? 一張完整的網(wǎng)頁(yè)一般由多種元素組成,因此需要多次請(qǐng)求,但是http是基于TCP協(xié)議的,而TCP是面向連接的,因此請(qǐng)求一張網(wǎng)頁(yè)也許會(huì)存在頻繁創(chuàng)建連接的問(wèn)題。
? ? ? ? 而長(zhǎng)連接就是為了解決該問(wèn)題而存在的。
? ? ? ? 它通過(guò)建立一條鏈接,獲取資源的任何行為都必須通過(guò)這個(gè)鏈接完成,從而解決頻繁創(chuàng)建連接的問(wèn)題。
http會(huì)話(huà)保持
? ? ? ? 會(huì)話(huà)保持這個(gè)功能是用戶(hù)在實(shí)際體驗(yàn)過(guò)程中所需要的一個(gè)功能,表面現(xiàn)象就是當(dāng)你登錄了一個(gè)網(wǎng)站,那么你即使退出了該網(wǎng)站或者退出了該瀏覽器,下一次訪(fǎng)問(wèn)該網(wǎng)站時(shí),網(wǎng)站依舊知道你是哪個(gè)用戶(hù)。
????????會(huì)話(huà)保持有兩種方法。
老方法
? ? ? ? 老方法是通過(guò)在客戶(hù)端保存用戶(hù)信息,每次訪(fǎng)問(wèn)同一個(gè)網(wǎng)站瀏覽器都會(huì)自動(dòng)推送歷史保留信息,從而實(shí)現(xiàn)會(huì)話(huà)保持。
? ? ? ? 而這個(gè)信息稱(chēng)為cookie。
Cookie
- 用來(lái)保存用戶(hù)信息
- cookie文件:瀏覽器關(guān)閉后cookie會(huì)以文件形式保存下來(lái)
- cookie內(nèi)存:瀏覽器關(guān)閉后cookie不會(huì)以文件形式保存下來(lái)
? ? ? ? 但是老方法有一個(gè)問(wèn)題,那就是cookie信息是保存到客戶(hù)端的,一般的客戶(hù)端很難防止木馬盜取用戶(hù)信息,就會(huì)導(dǎo)致用戶(hù)賬號(hào)被盜。
? ? ? ? 而新方案則另辟蹊徑。
新方案
? ? ? ? 新方案將用戶(hù)信息存在服務(wù)器中,用session保存文件,并且返回對(duì)應(yīng)的session id,而每次客戶(hù)端請(qǐng)求就是通過(guò)session id 來(lái)訪(fǎng)問(wèn)對(duì)應(yīng)的session文件。
? ? ? ? 雖然客戶(hù)端的session id 依舊可能會(huì)被盜,但是這樣至少可以保證用戶(hù)的信息沒(méi)有被泄露。
? ? ? ??而且服務(wù)器可以通過(guò)查看用戶(hù)的 ip 地址等方案來(lái)判斷 session id 是否需要失效,從而保證了用戶(hù)信息的安全。
Https協(xié)議
????????了解了一些http協(xié)議的細(xì)節(jié),那么自然也需要來(lái)了解Https協(xié)議。
? ? ? ? https協(xié)議實(shí)際上就是單純的在http協(xié)議和傳輸層之間添加了一層加密協(xié)議,從而保證用戶(hù)信息的安全。
? ? ? ? ?由于http協(xié)議內(nèi)容都是明文傳輸?shù)模虼诵枰砑蛹用軈f(xié)議防止用戶(hù)信息被篡改。
什么是加密
- 將明文通過(guò)一系列變換生成密文。
- 將密文通過(guò)一系列變換生成明文。
? ? ? ? 一般加密過(guò)程中,都需要多個(gè)密鑰來(lái)輔助加密和解密。
為什么加密
? ? ? ? 有時(shí)候我們上網(wǎng)下載東西時(shí),明明搜索下載的是A,但是下載完卻發(fā)現(xiàn)下載的是B,這就是我們?cè)谡?qǐng)求下載時(shí),響應(yīng)被劫持了。
? ? ? ? 我們?cè)诰W(wǎng)絡(luò)上傳輸?shù)娜魏螖?shù)據(jù)包都會(huì)經(jīng)過(guò)運(yùn)營(yíng)商的網(wǎng)絡(luò)設(shè)備(路由器等),運(yùn)營(yíng)商的網(wǎng)絡(luò)設(shè)備就可以解析出你傳輸?shù)臄?shù)據(jù)內(nèi)容并進(jìn)行篡改。
? ??
當(dāng)我們未被劫持時(shí),我們下載的東西就是正確的。
?而當(dāng)我們被劫持了,下載的東西就是別的軟件了。
? ? ? ? ?因此我們需要通過(guò)加密來(lái)防止這種中間人攻擊。
加密方式
? ? ? ? 為了防止中間人攻擊,https退出了兩種加密方式。
對(duì)稱(chēng)加密
- 采用單鑰密碼系統(tǒng)的加密方法,一個(gè)密鑰可以用來(lái)加密和解密。
- 常見(jiàn)算法:DES,3DES,AES,TDEA,RC2等。
- 特點(diǎn):算法公開(kāi),計(jì)算量小,加密速度快,加密效率高。
非對(duì)稱(chēng)加密
- 需要兩個(gè)密鑰來(lái)進(jìn)行加密和解密,分別是公開(kāi)密鑰(public key)和私有密鑰(private key)。
- 常見(jiàn)算法:RSA,DSA,ECDSA。
- 特點(diǎn):算法強(qiáng)度復(fù)雜,安全性依賴(lài)于算法和密鑰,但是由于算法復(fù)雜,使得加密速度沒(méi)有對(duì)稱(chēng)加密快。
? ? ? ? 非對(duì)稱(chēng)加密有一個(gè)特點(diǎn),那就是兩個(gè)密鑰可以反著使用。
? ? ? ? 可以用公鑰加密,私鑰解密,也可以用私鑰加密,公鑰解密。
數(shù)據(jù)摘要&&數(shù)據(jù)指紋
- 數(shù)據(jù)摘要是通過(guò)單向散列函數(shù)對(duì)信息進(jìn)行運(yùn)算,生產(chǎn)一段固定長(zhǎng)度的數(shù)字摘要。
- 常見(jiàn)算法:MD5,SHA1,SHA256等,由于是將無(wú)限生產(chǎn)有限,有可能出現(xiàn)碰撞,但是概率很小。
- 特點(diǎn):并不是一種加密方式,無(wú)法通過(guò)數(shù)據(jù)摘要反推原信息,通常用來(lái)進(jìn)行數(shù)據(jù)對(duì)比。
數(shù)字簽名
- 將數(shù)據(jù)摘要進(jìn)行加密生產(chǎn)的簽名。
https的加密方案
? ? ? ? 當(dāng)我們了解到https的加密手段后,我們?cè)賮?lái)看看加密方案。
方案一:都使用對(duì)稱(chēng)加密
? ? ? ? ?在客戶(hù)端和服務(wù)器之間的交流之中,都是通過(guò)客戶(hù)端發(fā)送請(qǐng)求后,服務(wù)器再將密鑰X發(fā)送給客戶(hù)端。
? ? ? ? 乍一看,也許沒(méi)問(wèn)題,但是如果有中間人攻擊的話(huà),很容易就能將數(shù)據(jù)劫持掉。
? ? ? ? 而且由于密鑰是明文傳送的,黑客持有了密鑰,后續(xù)的加密操作也沒(méi)有作用了。那么無(wú)論客戶(hù)端發(fā)送什么密文給服務(wù)器,黑客都能夠隨意修改。
? ? ? ? 也許有同學(xué)會(huì)想,那我將密鑰給加密怎么樣呢?
? ? ? ? 這就陷入了一個(gè)套娃的循環(huán)了。
方案二:都采用非對(duì)稱(chēng)加密
? ? ? ? 如圖所示,采用非對(duì)稱(chēng)加密時(shí),服務(wù)器發(fā)送的響應(yīng)必須通過(guò)私鑰加密,但是私鑰加密的密文可以通過(guò)公鑰解密,此時(shí)黑客已經(jīng)劫持了公鑰,那么響應(yīng)就能夠被隨便修改了。
?方案三:雙方都是用非對(duì)稱(chēng)加密
? ? ? ??
????????
? ? ? ? ?當(dāng)雙方都采用非對(duì)稱(chēng)加密時(shí),客戶(hù)端將數(shù)據(jù)通過(guò) FS 加密,因此只有服務(wù)器能夠解密,而服務(wù)器發(fā)送的響應(yīng)能夠通過(guò)客戶(hù)端的 KS 加密,因此只有客戶(hù)端能夠解密。
? ? ? ? 但是這樣有一個(gè)缺點(diǎn):慢。
? ? ? ? 之前提過(guò),非對(duì)稱(chēng)加密很慢,而這樣雙方都使用非對(duì)稱(chēng)加密就更慢了。
方案四:對(duì)稱(chēng)加密+非對(duì)稱(chēng)加密
? ? ? ? ?像這樣,服務(wù)器明文發(fā)送了公鑰給客戶(hù)端,客戶(hù)端內(nèi)部決定密鑰為 X 然后通過(guò) FS 加密發(fā)送給服務(wù)器,這樣客戶(hù)端和服務(wù)器就通過(guò) 密鑰 X 來(lái)加密,而且即便中間人后面來(lái)劫持也無(wú)法篡改密文。
? ? ? ??但是這樣依舊有一個(gè)問(wèn)題——那就是假如一開(kāi)始中間人就開(kāi)始劫持會(huì)怎么樣?
? ? ? ? 如果中間人一開(kāi)始就劫持了,那么中間人就能夠篡改發(fā)送的公鑰 FS,這樣后面的加密解密就都在中間人的監(jiān)視下了。
? ? ? ? 而這個(gè)問(wèn)題上面四個(gè)方案都存在。
中間人攻擊
? ? ? ? 在上面幾個(gè)方案中,只要中間人一開(kāi)始就已經(jīng)開(kāi)始攻擊了,那么中間人能夠輕易獲取公鑰并篡改公鑰為中間人自己的公鑰,而且服務(wù)器和客戶(hù)端都無(wú)法察覺(jué),這樣客戶(hù)端和服務(wù)器之間的交流都會(huì)被中間人獲取到。
- 服務(wù)器具有?對(duì)稱(chēng)加密算法的公鑰S,私鑰S'
- 中間?具有?對(duì)稱(chēng)加密算法的公鑰M,私鑰M'
- 客?端向服務(wù)器發(fā)起請(qǐng)求,服務(wù)器明?傳送公鑰S給客?端
- 中間?劫持?jǐn)?shù)據(jù)報(bào)?,提取公鑰S并保存好,然后將被劫持報(bào)?中的公鑰S替換成為??的公鑰M, 并將偽造報(bào)?發(fā)給客?端
- 客?端收到報(bào)?,提取公鑰M(??當(dāng)然不知道公鑰被更換過(guò)了),??形成對(duì)稱(chēng)秘鑰X,?公鑰M加密X,形成報(bào)?發(fā)送給服務(wù)器
- 中間?劫持后,直接???的私鑰M'進(jìn)?解密,得到通信秘鑰X,再?曾經(jīng)保存的服務(wù)端公鑰S加密后,將報(bào)?推送給服務(wù)器
- 服務(wù)器拿到報(bào)?,???的私鑰S'解密,得到通信秘鑰X
- 雙?開(kāi)始采?X進(jìn)?對(duì)稱(chēng)加密,進(jìn)?通信。但是?切都在中間?的掌握中,劫持?jǐn)?shù)據(jù),進(jìn)?竊聽(tīng)甚?修改,都是可以的
? ? ? ? 為了解決這個(gè)問(wèn)題,我們需要了解一個(gè)新概念。
證書(shū)
CA認(rèn)證
? ? ? ??每個(gè)服務(wù)器在使用HTTPS之前,都要向CA申請(qǐng)一份數(shù)字證書(shū),數(shù)字證書(shū)中包含申請(qǐng)者信息,公鑰信息等。
? ? ? ? 而有證書(shū)的服務(wù)器會(huì)將證書(shū)傳輸給客戶(hù)端,客戶(hù)端直接從證書(shū)中獲取公鑰。
每個(gè)證書(shū)中包含了以下信息:
- 證書(shū)發(fā)布機(jī)構(gòu)
- 證書(shū)有效期
- 公鑰
- 證書(shū)所有者
- 簽名
? ? ? ? ?CA機(jī)構(gòu)中有他們自己維護(hù)的公鑰和私鑰,由此來(lái)保證證書(shū)的可靠性。
? ? ? ? 那么具體過(guò)程是如何做的呢?
數(shù)據(jù)簽名
? ? ? ? CA機(jī)構(gòu)的證書(shū)通過(guò)數(shù)據(jù)簽名來(lái)保證證書(shū)的可靠性。
? ? ? ? 當(dāng)服務(wù)器申請(qǐng)證書(shū)時(shí),CA在對(duì)服務(wù)器進(jìn)行審核后,會(huì)為該網(wǎng)站專(zhuān)門(mén)形成數(shù)字簽名。
簽名
- CA首先將服務(wù)器的數(shù)據(jù)通過(guò)單向散列函數(shù)來(lái)生成數(shù)據(jù)指紋。
- 然后通過(guò)CA的私鑰來(lái)生成數(shù)據(jù)簽名
- 最后將明文信息和數(shù)據(jù)簽名放在一起形成證書(shū)
驗(yàn)證
- 最后客戶(hù)端驗(yàn)證則是將證書(shū)拆開(kāi)
- 數(shù)據(jù)簽名通過(guò)CA公鑰解密成數(shù)據(jù)指紋(每個(gè)瀏覽器中都有CA的公鑰)
- 明文信息則通過(guò)散列函數(shù)生成散列值
- 最后判斷數(shù)據(jù)指紋是否相同
需要驗(yàn)證的信息:
- 證書(shū)是否過(guò)期
- 證書(shū)的發(fā)布機(jī)構(gòu)是否可信
- 驗(yàn)證證書(shū)是否被篡改
方案五:采用證書(shū)+對(duì)稱(chēng)加密+非對(duì)稱(chēng)加密
? ? ? ? ?最后方案5是在方案4的基礎(chǔ)上加入證書(shū)。
- 在最開(kāi)始建立連接后,服務(wù)器發(fā)送的并非單純的公鑰,而是證書(shū)
- 當(dāng)客戶(hù)端收到證書(shū)的時(shí)候就需要驗(yàn)證證書(shū)是否可信
- 之后再通過(guò)證書(shū)中包含的服務(wù)器的公鑰來(lái)加密密鑰
- 這樣后續(xù)密文的解密和加密都十分便捷了
證書(shū)有沒(méi)有可能被中間人篡改?
- 即便中間人篡改了證書(shū),他依舊沒(méi)有CA機(jī)構(gòu)的私鑰,就無(wú)法在hash后用私鑰加密形成簽名,也就沒(méi)辦法對(duì)篡改后的證書(shū)形成匹配的簽名
- 若強(qiáng)行篡改,那么客戶(hù)端會(huì)檢測(cè)到明文和簽名解密后的值不同,客戶(hù)端會(huì)終止傳輸信息,防止泄露。
證書(shū)有沒(méi)有可能被整個(gè)掉包?
- 中間人沒(méi)有CA私鑰,因此無(wú)法制作假的證書(shū)
- 中間人只能申請(qǐng)真的證書(shū)來(lái)替換證書(shū)
- 但是證書(shū)中還有域名,若是域名不一致,依舊會(huì)被檢測(cè)到
- 記?。褐虚g人沒(méi)有CA私鑰,任何證書(shū)都無(wú)法被合法修改,包括自己
為什么摘要需要使用CA私鑰加密?
? ? ? ? 由于摘要算法的特性:定長(zhǎng),分散,不可逆,導(dǎo)致我們判斷證書(shū)是否相同的標(biāo)準(zhǔn)是摘要是否一致,若是不采用CA私鑰加密,客戶(hù)端沒(méi)有CA的公鑰來(lái)進(jìn)行解密,中間人只需要將內(nèi)容修改,同時(shí)將摘要修改,那么客戶(hù)端就無(wú)法分辨了。
? ? ? ? 而有了CA私鑰加密,就能夠保證中間人無(wú)法篡改證書(shū)了。
為什么不直接加密而先形成摘要呢?
? ? ? ??為了減少密文的長(zhǎng)度,加快數(shù)字簽名的速度。
HTTPS的完整流程
?總結(jié):
HTTPS工作一共有三組密鑰。
- 非對(duì)稱(chēng)加密:用于檢驗(yàn)證書(shū)是否被篡改??蛻?hù)端天然持有CA機(jī)構(gòu)的公鑰,服務(wù)器發(fā)送證書(shū)給客戶(hù)端,客戶(hù)端通過(guò)該公鑰驗(yàn)證證書(shū)是否被篡改
- 非對(duì)稱(chēng)加密:用于協(xié)商對(duì)稱(chēng)加密的密鑰。客戶(hù)端在證書(shū)中獲取服務(wù)器的公鑰,用公鑰給密鑰加密,發(fā)送給服務(wù)器
- 對(duì)稱(chēng)加密:服務(wù)器和客戶(hù)端通過(guò)該密鑰進(jìn)行加密解密。
傳輸層
? ? ? ? Http和Https兩個(gè)協(xié)議都是在應(yīng)用層的協(xié)議,而傳輸層則是負(fù)責(zé)將數(shù)據(jù)從發(fā)送端傳輸?shù)浇邮斩?/p>
再談端口號(hào)
? ? ? ? 端口號(hào)是用于標(biāo)示一臺(tái)主機(jī)上進(jìn)行通信的不同程序;
????????在TCP/IP協(xié)議中,用“源IP”,“源端口號(hào)”,“目的IP”,“目的端口號(hào)”,“協(xié)議號(hào)”這五元組來(lái)表示一個(gè)通信。
?端口號(hào)劃分
? ? ? ? 我們平時(shí)使用端口號(hào)時(shí),會(huì)發(fā)現(xiàn)有的端口號(hào)不可以使用。
? ? ? ? 這是因?yàn)槎丝谔?hào)是有范圍的。
- 0~1023:知名端口號(hào),由HTTP,SSH等廣為人知的應(yīng)用層協(xié)議使用
- 1024~65535:操作系統(tǒng)動(dòng)態(tài)分配的端口號(hào)
一些知名端口號(hào)
- SSH服務(wù)器:22端口號(hào)
- ftp服務(wù)器:21端口號(hào)
- telnet服務(wù)器:23端口號(hào)
- HTTP服務(wù)器:80端口號(hào)
- HTTPS服務(wù)器:443端口號(hào)
?平時(shí)我們自己使用端口號(hào)時(shí),需要避開(kāi)這些端口號(hào)。
UDP協(xié)議
UDP協(xié)議格式
? ? ? ? 想要了解UDP協(xié)議,就必須了解它的協(xié)議格式。
? ? ? ? ?所謂協(xié)議實(shí)際上可以看做是結(jié)構(gòu)化的數(shù)據(jù)。
? ? ? ? UDP也不例外,它的報(bào)頭采用的是定長(zhǎng)大小的策略,報(bào)文包含了8字節(jié)大小的報(bào)頭。
? ? ? ? 報(bào)頭中包含了源端口號(hào),目的端口號(hào),報(bào)文長(zhǎng)度等信息,用來(lái)傳遞信息。
- 16位UDP長(zhǎng)度包括報(bào)頭和報(bào)文的長(zhǎng)度
- 若是校驗(yàn)出錯(cuò),則會(huì)直接丟棄
UDP特點(diǎn)
- 無(wú)連接:知道目的端口號(hào)和IP地址即可,不用建立連接
- 不可靠:沒(méi)有確認(rèn)機(jī)制和重傳機(jī)制,若因網(wǎng)絡(luò)故障而無(wú)法發(fā)送信息給對(duì)方,UDP也不會(huì)返回任何錯(cuò)誤信息
- 面向數(shù)據(jù)報(bào):不能夠靈活的控制讀寫(xiě)數(shù)據(jù)的次數(shù)和數(shù)量
面向數(shù)據(jù)報(bào)
? ? ? ? UDP的特點(diǎn)中需要注意的是面向數(shù)據(jù)報(bào)這個(gè)特點(diǎn)。
? ? ? ? 使用UDP協(xié)議傳輸?shù)臄?shù)據(jù)一次傳輸?shù)臄?shù)據(jù)不能拆分也無(wú)法合并,UDP會(huì)原樣發(fā)送。
注意事項(xiàng)
由于UDP的UDP長(zhǎng)度是16位,因此UDP報(bào)文的長(zhǎng)度最長(zhǎng)不過(guò)64K(包括報(bào)頭),因此我們使用UDP傳輸數(shù)據(jù)時(shí),需要先在應(yīng)用層將數(shù)據(jù)分成64K大小后再傳輸,接收端則在接收后手動(dòng)拼裝。
UDP的緩沖區(qū)
- 發(fā)送緩沖區(qū):UDP并沒(méi)有發(fā)送緩沖區(qū),調(diào)用sendto會(huì)直接交給內(nèi)核,由內(nèi)核將數(shù)據(jù)傳給網(wǎng)絡(luò)層協(xié)議進(jìn)行后續(xù)的傳輸操作
- 接收緩沖區(qū):雖然能夠接受報(bào)文,但是無(wú)法保證收到的報(bào)文順序和發(fā)送的報(bào)文順序一致
? ? ? ? UDP客戶(hù)端通過(guò) send/write 將數(shù)據(jù)發(fā)送到網(wǎng)絡(luò)中,然后服務(wù)器把數(shù)據(jù)放到接收緩沖區(qū)中后,服務(wù)器通過(guò)報(bào)頭判斷自己是否為目的地,再?gòu)?strong>接收緩沖區(qū)中獲取信息,否則直接丟棄。
? ? ? ? 而UDP協(xié)議之中,它的socket既可以讀又可以寫(xiě),因此是雙全工的。
基于UDP的應(yīng)用層協(xié)議
- NFS:網(wǎng)絡(luò)文件系統(tǒng)
- TFTP:簡(jiǎn)單文件傳輸協(xié)議
- DHCP:動(dòng)態(tài)主機(jī)配置協(xié)議
- BOOTP:?jiǎn)?dòng)協(xié)議(用于無(wú)盤(pán)設(shè)備啟動(dòng))
- DNS:域名解析協(xié)議
此外還有用戶(hù)自己UDP程序在應(yīng)用層配置的協(xié)議。
TCP協(xié)議
TCP協(xié)議全稱(chēng)為“傳輸控制協(xié)議”,正如它的名字,它需要對(duì)數(shù)據(jù)的傳輸進(jìn)行詳細(xì)的控制。
TCP協(xié)議格式
- 16位校驗(yàn)和:發(fā)送端填充,CRC校驗(yàn),不通過(guò)認(rèn)為數(shù)據(jù)有問(wèn)題,丟棄。檢驗(yàn)部分是整個(gè)報(bào)文
? ? ? ? 而我們都知道TCP協(xié)議的特點(diǎn)是:有連接,可靠,面向字節(jié)流。其三大特點(diǎn)就是由其報(bào)頭造成的。
TCP報(bào)頭
TCP長(zhǎng)度
? ? ? ? TCP的報(bào)頭是一個(gè)自描述的變長(zhǎng)報(bào)頭。
? ? ? ? 首先,它的報(bào)頭固定大小為20字節(jié),其中有一個(gè)變量是4位首部長(zhǎng)度,用來(lái)表示報(bào)頭+選項(xiàng)的總長(zhǎng)度。
報(bào)頭總長(zhǎng)度:4位首部長(zhǎng)度 * 4字節(jié)。
4位首部長(zhǎng)度的單位是4字節(jié),假設(shè)報(bào)頭是40字節(jié),那么4位首部長(zhǎng)度值為10.
? ? ? ? TCP解包就是通過(guò)4位首部長(zhǎng)度確定報(bào)頭長(zhǎng)度,然后再一直讀取到下一個(gè)報(bào)頭的位置,就讀取了一個(gè)完整的報(bào)文了。
16位窗口大小
? ? ? ? 在TCP傳輸中,傳輸數(shù)據(jù)的速度不可過(guò)快過(guò)慢,應(yīng)該根據(jù)對(duì)方的接收緩沖區(qū)的剩余空間大小來(lái)決定發(fā)送多少數(shù)據(jù)。
? ? ? ? 因此使用TCP發(fā)送數(shù)據(jù)時(shí),都會(huì)往16位窗口大小填充自己接收緩沖區(qū)的剩余空間大小來(lái)進(jìn)行流量控制。
六個(gè)標(biāo)記位
? ? ? ? ?我們TCP平時(shí)可能會(huì)傳各種各樣的數(shù)據(jù),有的是普通的數(shù)據(jù)段,有的是確認(rèn)數(shù)據(jù)段(ACK)。
? ? ? ? 因此TCP協(xié)議使用了六個(gè)標(biāo)記位來(lái)表示不同的報(bào)文。
- ACK:確認(rèn)標(biāo)記位,表示是否為確認(rèn)報(bào)文
- PSH:對(duì)方的接收緩沖區(qū)已滿(mǎn)時(shí),告知對(duì)方盡快讀取緩沖區(qū)中的數(shù)據(jù)
- URG:表示緊急指針是否有效
- RST:對(duì)方要求重新建立連接,帶有RST的報(bào)文稱(chēng)為復(fù)位報(bào)文段
- SYN:請(qǐng)求報(bào)文段,攜帶該標(biāo)記位的稱(chēng)為同步報(bào)文段
- FIN:通知對(duì)方,本端要關(guān)閉了,帶有FIN的稱(chēng)為結(jié)束報(bào)文段
? ? ? ? 其中有幾個(gè)標(biāo)記位需要展開(kāi)說(shuō)明。
URG標(biāo)記位
? ? ? ??一般報(bào)文都會(huì)有序號(hào)保證報(bào)文按序到達(dá),但是有時(shí)候也有高優(yōu)先級(jí)的報(bào)文,這時(shí)候就需要插隊(duì)了。
? ? ? ? 帶有URG標(biāo)識(shí)位的報(bào)文就表示該數(shù)據(jù)要盡快讀取。
? ? ? ??這種報(bào)文就需要去16位緊急指針,該指針通過(guò)記錄緊急數(shù)據(jù)在有效載荷的偏移量來(lái)指向緊急數(shù)據(jù)。
? ? ? ??一般緊急數(shù)據(jù)只有一字節(jié)。
RST標(biāo)記位
? ? ? ? 若是三次握手與四次揮手失敗了,或者說(shuō)通信過(guò)程中單方面出錯(cuò)了,出錯(cuò)的一方認(rèn)為連接不存在了,?但是對(duì)方依舊認(rèn)為連接存在,對(duì)方依舊會(huì)發(fā)送報(bào)文,此時(shí)出錯(cuò)的一方收到報(bào)文后就會(huì)返回一個(gè)帶有RST的報(bào)文,來(lái)重新建立連接。
TCP的可靠性
? ? ? ? TCP有一個(gè)最大的特點(diǎn)就是它的可靠性,它能夠保證數(shù)據(jù)能夠成功傳輸給對(duì)方,若是失敗也會(huì)告知用戶(hù),那么它是如何做到的呢?
? ? ? ? 用過(guò)網(wǎng)購(gòu)的童鞋們都知道,我們收到網(wǎng)購(gòu)的東西后,需要在軟件上確認(rèn)收貨商家才能收款,否則商家就無(wú)法確認(rèn)你是否收到了商品。
? ? ? ? 而TCP也是如此,當(dāng)客戶(hù)端發(fā)送請(qǐng)求或者數(shù)據(jù)給服務(wù)器時(shí),服務(wù)器需要返回一個(gè)確認(rèn)數(shù)據(jù)段給客戶(hù)端,這樣客戶(hù)端才能知道服務(wù)器確實(shí)收到了數(shù)據(jù)。
? ? ? ? ?當(dāng)然,這里服務(wù)器并不是單純的返回一個(gè)確認(rèn)數(shù)據(jù)段,而是一段報(bào)文,該報(bào)文的報(bào)頭有一段數(shù)據(jù)就是確認(rèn)數(shù)據(jù)段,在TCP中,這段確認(rèn)數(shù)據(jù)段就是報(bào)頭中的32位確認(rèn)序號(hào)。
確認(rèn)應(yīng)答(ACK)機(jī)制
? ? ? ? 每次TCP的發(fā)送段發(fā)送數(shù)據(jù)的時(shí)候,TCP協(xié)議會(huì)給每一個(gè)字節(jié)的數(shù)據(jù)添加一個(gè)序號(hào),這個(gè)序號(hào)記錄在32位序號(hào)中,當(dāng)接收段接收數(shù)據(jù)的時(shí)候,接收端會(huì)根據(jù)這個(gè)序號(hào)進(jìn)行排序,并判斷是否丟失數(shù)據(jù)。
? ? ? ??而當(dāng)接收端返回一個(gè)ACK時(shí),就會(huì)在32位確認(rèn)序號(hào)中返回最后一個(gè)位序號(hào)的值+1,告知對(duì)方已成功接收確認(rèn)序號(hào)之前的所有數(shù)據(jù),只用從確認(rèn)序號(hào)開(kāi)始發(fā)送數(shù)據(jù)即可。
?
? ? ? ? ?這樣就保證接收端能夠?qū)?bào)文全部接收,并且發(fā)送端能夠知道該從哪里繼續(xù)發(fā)送。
? ? ? ? 此外由于TCP協(xié)議也是全雙工的,雙方都要相互發(fā)送數(shù)據(jù),相互應(yīng)答,因此會(huì)有兩組序號(hào)分別記錄對(duì)方的位序號(hào)。
超時(shí)重傳機(jī)制
? ? ? ? 為了保證可靠性,TCP還有超時(shí)重傳。
? ? ? ? 該機(jī)制分為兩種情況。
- ?數(shù)據(jù)未發(fā)送給對(duì)方,在一定時(shí)間間隔后未收到應(yīng)答就重傳。
- ?數(shù)據(jù)發(fā)送到對(duì)方了,但是對(duì)方的應(yīng)答發(fā)送失敗了。
- 這樣A在一定時(shí)間后就會(huì)重新發(fā)送一次數(shù)據(jù)。
? ? ? ? 第一種情況很簡(jiǎn)單,重點(diǎn)是第二種情況,主機(jī)B重復(fù)收到了相同的數(shù)據(jù),那么它就需要進(jìn)行去重操作。
? ? ? ? 而去重操作也是通過(guò)之前的32位序號(hào)進(jìn)行——通過(guò)對(duì)比數(shù)據(jù)序號(hào)來(lái)去重。
? ? ? ??對(duì)于主機(jī)A來(lái)說(shuō),它需要重新發(fā)送相同的數(shù)據(jù),那就是說(shuō)發(fā)送的數(shù)據(jù)并不直接移出緩沖區(qū),而是維持一段時(shí)間,也許是等到應(yīng)答后,也許是操作系統(tǒng)自己決定。
超時(shí)的時(shí)間如何定?
? ? ? ? 理想情況下就是找到一個(gè)最小的時(shí)間,保證確認(rèn)應(yīng)答會(huì)在這個(gè)時(shí)間內(nèi)返回。
? ? ? ? 但是實(shí)際上由于網(wǎng)速不同,這個(gè)時(shí)間長(zhǎng)短時(shí)變化的,過(guò)長(zhǎng)會(huì)降低效率,過(guò)短會(huì)頻繁重復(fù)傳包
? ? ? ? 因此TCP是動(dòng)態(tài)的計(jì)算這個(gè)時(shí)間間隔。
- 任何操作系統(tǒng)都是以500ms為一個(gè)單位,時(shí)間間隔都是500ms的整數(shù)倍。
- 重發(fā)一次依舊等不到應(yīng)答就等待2*500ms的時(shí)間。
- 依舊等不到應(yīng)答就重發(fā)等待4*500ms,以指數(shù)增長(zhǎng)。
- 重傳一定次數(shù),就認(rèn)為對(duì)方異常,關(guān)閉連接。
連接管理機(jī)制
? ? ? ? TCP作為面向連接的協(xié)議,它具有一套機(jī)制用來(lái)管理連接。
? ? ? ? 一般來(lái)說(shuō),TCP每次連接都需要三次握手的,每次斷開(kāi)連接則需要四次揮手。
?三次握手
????????
三次握手的過(guò)程
- 客戶(hù)端應(yīng)用層調(diào)用connect函數(shù),客戶(hù)端TCP層狀態(tài)變?yōu)?SYN_SENT ,并且向服務(wù)器發(fā)送包含SYN標(biāo)記位的報(bào)文,作為請(qǐng)求連接?
- 服務(wù)器應(yīng)用層時(shí)在accept函數(shù)阻塞等待客戶(hù)端請(qǐng)求,當(dāng)收到包含SYN標(biāo)記位的報(bào)文時(shí),服務(wù)器TCP層狀態(tài)變?yōu)?SYN_RCVD,并返回一個(gè)包含 SYN+ACK 標(biāo)記位的報(bào)文
- 之后客戶(hù)端收到報(bào)文后,TCP層狀態(tài)變?yōu)镋STABLISHED,引用層connect函數(shù)返回,客戶(hù)端認(rèn)為連接已建立,并返回包含ACK標(biāo)記位的報(bào)文
- 服務(wù)器接收到ACK標(biāo)記位的報(bào)文后,也認(rèn)為成功建立連接,狀態(tài)變?yōu)?ESTABLISHED,accept函數(shù)返回
? ? ? ? 正常來(lái)說(shuō),一次成功的建立連接過(guò)程就如上,之后就能夠傳輸數(shù)據(jù)了。
? ? ? ? 但是網(wǎng)絡(luò)通信并不一定都一帆風(fēng)順,數(shù)據(jù)總有丟包風(fēng)險(xiǎn),因此我們的三次握手過(guò)程也有可能失敗。
? ? ? ? 在三次握手過(guò)程中,客戶(hù)端發(fā)送SYN時(shí),確認(rèn)應(yīng)答機(jī)制會(huì)起作用,告知客戶(hù)端服務(wù)器是否收到數(shù)據(jù);而客戶(hù)端一旦收到 SYN+ACK時(shí),它就認(rèn)為已經(jīng)成功建立連接了,因此此時(shí)客戶(hù)端就不會(huì)等待應(yīng)答,而是直接傳輸數(shù)據(jù)給服務(wù)器了。
? ? ? ? 但是從服務(wù)器上來(lái)看,它必須收到 ACK 才會(huì)認(rèn)為成功建立連接,但是ACK是會(huì)丟包的。
? ? ? ? 因此三次握手可能會(huì)出現(xiàn)客戶(hù)端認(rèn)為建立連接,但是服務(wù)器卻不認(rèn)為在建立連接的情況。
? ? ? ??這種情況下,一般就是客戶(hù)端發(fā)送數(shù)據(jù)給服務(wù)器后,服務(wù)器發(fā)現(xiàn)未建立連接,就會(huì)返回一個(gè)帶有RST的報(bào)文用來(lái)重新建立連接,或許也有其他方案,不過(guò)大差不差。
為什么是三次握手?
? ? ? ??三次握手為什么不是一次兩次或者是四次握手呢?首先我們要先連接三次握手的優(yōu)點(diǎn)。
? ? ? ? 對(duì)于TCP協(xié)議來(lái)說(shuō),通信雙方都是對(duì)等的,雙方可以互相讀寫(xiě)信息,也就是所謂的全雙工。
? ? ? ? 而三次握手就是最小成本驗(yàn)證全雙工通信是通暢的。對(duì)于客戶(hù)端來(lái)說(shuō),它不僅需要發(fā)送SYN報(bào)文給服務(wù)器,還需要讀取 SYN+ACK 報(bào)文,對(duì)于服務(wù)器來(lái)說(shuō),它也是要讀取 SYN 和 ACK 兩個(gè)報(bào)文,發(fā)送 SYN+ACK 兩個(gè)報(bào)文,正好雙方都至少讀寫(xiě)了一次。
? ? ? ? 正因?yàn)殡p方都至少讀寫(xiě)了一次,雙方才都能得到對(duì)方的起始序列號(hào),而二次握手可能只有客戶(hù)端能夠得到服務(wù)的的起始序號(hào)。
? ? ? ? 此外,三次握手能夠有效的防止單機(jī)攻擊服務(wù)器。
SYN洪水:一種攻擊手段,通過(guò)給服務(wù)器發(fā)送海量連接請(qǐng)求,使得服務(wù)器需要維護(hù)多個(gè)半連接,導(dǎo)致服務(wù)器資源被占用。
? ? ? ? 若是一次握手就能夠成功建立連接,對(duì)于客戶(hù)端來(lái)說(shuō),它只需要發(fā)送一個(gè)鏈接就好了,也只需要維護(hù)一個(gè)鏈接,但是服務(wù)器是同時(shí)維護(hù)多個(gè)鏈接的,維護(hù)每一個(gè)連接都是需要成本的,若是一次握手就會(huì)使的客戶(hù)端攻擊服務(wù)器的成本降低,二次握手也是一樣。
? ? ? ? 而多次握手則是成本又比三次握手高,因此采用三次握手。
四次揮手
四次揮手過(guò)程
? ? ? ??需要注意,四次揮手并不一定是客戶(hù)端關(guān)閉,服務(wù)器也能主動(dòng)關(guān)閉。
- ?客戶(hù)端在應(yīng)用層調(diào)用 close 函數(shù),TCP層狀態(tài)變?yōu)?FIN_WAIT_1,并且發(fā)送 FIN 報(bào)文給服務(wù)器
- 服務(wù)器接收到后,TCP層狀態(tài)變?yōu)?CLOSE_WAIT,應(yīng)用層 read 函數(shù)返回0,并返回一個(gè)ACK 報(bào)文
- 客戶(hù)端接收到后TCP層狀態(tài)變?yōu)?FIN_WAIT_2,,過(guò)一段時(shí)間后,服務(wù)器調(diào)用close,狀態(tài)變?yōu)?LAST_ACK,并發(fā)送 FIN 報(bào)文給 客戶(hù)端
- 客戶(hù)端收到后狀態(tài)變?yōu)?TIME_WAIT,并返回 ACK 報(bào)文變?yōu)?CLOSED狀態(tài),服務(wù)器接收到 ACK 后狀態(tài)變?yōu)?CLOSED
揮手期間雙方狀態(tài)發(fā)送變化
CLOSED_WAIT狀態(tài)
? ? ? ??TCP層協(xié)議規(guī)定,被動(dòng)關(guān)閉連接的一方需要處于CLOSE_WAIT狀態(tài),這個(gè)狀態(tài)會(huì)一直持續(xù)到服務(wù)器處理完數(shù)據(jù),調(diào)用 close 函數(shù)會(huì)結(jié)束。
? ? ? ? 那么也就是說(shuō)我將 Sever 的 close 函數(shù)給注釋掉,Sever就一直是這個(gè)狀態(tài)。
?
? ? ? ? 此時(shí)客戶(hù)端還在連接中,看下?tīng)顟B(tài)。? ? ? ? ?當(dāng)我們關(guān)閉客戶(hù)端時(shí),再看看狀態(tài)。
? ? ? ? ?發(fā)現(xiàn)TCPSever確實(shí)一直處于CLOSE_WAIT狀態(tài)。
大量出現(xiàn)CLOSE_WAIT原因
- 服務(wù)器沒(méi)有進(jìn)行 close 的動(dòng)作
- 服務(wù)器有壓力,一直在推送消息給客戶(hù)端,無(wú)法進(jìn)行close
?TIME_WAIT狀態(tài)
? ? ? ??當(dāng)我們使用TCP協(xié)議使用一些端口來(lái)啟動(dòng)服務(wù)器時(shí),用這個(gè)端口關(guān)閉的服務(wù)器在一定時(shí)間內(nèi)無(wú)法再次使用這個(gè)端口,就是由于TIME_WAIT狀態(tài)。
????????
- TCP協(xié)議規(guī)定主動(dòng)關(guān)閉連接的一方要處于TIME_WAIT狀態(tài),等待2個(gè) MSL?后才能回到CLOSED狀態(tài)。
- MSL在不同操作系統(tǒng)上的時(shí)間不同,可以通過(guò) "cat /proc/sys/net/ipv4/tcp_find_timeout"來(lái)查看。
- 一般來(lái)說(shuō)MSL就是一個(gè)TCP報(bào)文的最大存活時(shí)間。
那么為什么要處于TIME_WAIT狀態(tài)呢?
- 主動(dòng)關(guān)閉的一方需要返回一個(gè)ACK給被動(dòng)關(guān)閉的一方,但是ACK可能丟包,確認(rèn)應(yīng)答機(jī)制導(dǎo)致主動(dòng)關(guān)閉的一方需要重新接收FIN來(lái)補(bǔ)發(fā)一個(gè)ACK。
- 雙方斷開(kāi)連接時(shí),網(wǎng)絡(luò)中也可能還有滯留的數(shù)據(jù),需要保證這些報(bào)文已經(jīng)消失。
? ? ? ? 而主動(dòng)關(guān)閉連接的一方等待兩個(gè)MSL后,就能夠保證至少補(bǔ)發(fā)一個(gè)ACK報(bào)文,并且保證網(wǎng)絡(luò)中的滯留數(shù)據(jù)消失。
解決辦法
? ? ? ??那么我們?nèi)绾尾拍軌蚩焖僦匦率褂眠@個(gè)端口呢?就需要調(diào)用下面這個(gè)函數(shù)。
使用setsockopt()設(shè)置socket描述符的選項(xiàng)SO_REUSEADDR為1, 表示允許創(chuàng)建端口號(hào)相同但I(xiàn)P地址不同的多個(gè) socket描述符?
? ? ? ? 當(dāng)我們調(diào)用這個(gè)函數(shù)后就能夠重復(fù)使用同一個(gè)端口了。?
滑動(dòng)窗口
? ? ? ? 在確認(rèn)應(yīng)答機(jī)制中,并不是每次發(fā)送數(shù)據(jù)都需要應(yīng)答的,因?yàn)槿羰敲看味紤?yīng)答會(huì)降低性能,因此每次發(fā)送數(shù)據(jù)實(shí)際上是一次發(fā)送多個(gè)數(shù)據(jù)。
- 發(fā)送前四段數(shù)據(jù)不用等待應(yīng)答。
- 返回的應(yīng)答確認(rèn)序號(hào)一定是對(duì)方已經(jīng)接收到的數(shù)據(jù)的序號(hào)+1,就能夠確認(rèn)是否丟包。?
? ? ? ? 在TCP的報(bào)頭中,有一個(gè)16位窗口大小,其值是指不用等待確認(rèn)應(yīng)答,而可以繼續(xù)發(fā)送數(shù)據(jù)的最大值,?其大小根據(jù)對(duì)方的接收緩沖區(qū)的剩余空間的大小而變化。
? ? ? ? 根據(jù)窗口大小,我們能夠一次發(fā)送多個(gè)數(shù)據(jù),但是這些數(shù)據(jù)有可能在網(wǎng)絡(luò)中丟包,根據(jù)確認(rèn)應(yīng)答機(jī)制需要重新發(fā)送數(shù)據(jù),而這些發(fā)送出去而未收到應(yīng)答的數(shù)據(jù)就需要滑動(dòng)窗口來(lái)管理。
滑動(dòng)窗口如何管理的?
????????實(shí)際上滑動(dòng)窗口并不是一個(gè)真正的窗口,它實(shí)際上是兩個(gè)下標(biāo)。
- 收到對(duì)方的應(yīng)答后,win_start會(huì)根據(jù)對(duì)方報(bào)頭的32位確認(rèn)序號(hào)來(lái)向后移動(dòng)。
- win_end則會(huì)根據(jù)對(duì)方的接受緩沖區(qū)的大小來(lái)向后移動(dòng)。
- 滑動(dòng)窗口的大小并不固定,根據(jù)對(duì)方的接收能力有關(guān)。
如果收到的應(yīng)答是滑動(dòng)窗口中間或結(jié)尾的ACK怎么辦?????????
? ? ? ? 也許收到的應(yīng)答并不是2001,而是 4001或者直接是結(jié)尾呢?
? ? ? ? 這樣只有兩種情況。
- 丟包了,數(shù)據(jù)沒(méi)丟,但是應(yīng)答丟了。
- 數(shù)據(jù)丟包了。?
? ? ? ? ?首先是第一種情況,這種情況下窗口是直接滑動(dòng)的,因?yàn)?strong>序號(hào)的定義就是對(duì)方已接收到該序號(hào)之前的所有數(shù)據(jù),因此可以直接滑動(dòng)。
? ? ? ??第二種情況也很簡(jiǎn)單,根據(jù)序號(hào)定義,應(yīng)答的ACK應(yīng)該是對(duì)方所接收到的數(shù)據(jù)的序號(hào)+1,因此接收端就知道哪些數(shù)據(jù)丟包了,就會(huì)補(bǔ)發(fā)一次。
- 當(dāng)發(fā)送端連續(xù)收到重復(fù)的應(yīng)答報(bào)文后,會(huì)補(bǔ)發(fā)一次報(bào)文。
- 比如途中發(fā)送端接收到三次 "1001"的報(bào)文后,它就重新發(fā)送一次 "1001--2000"的報(bào)文。
- 之后接收端返回的應(yīng)答就是 "7001" 了。
- 這個(gè)機(jī)制稱(chēng)為“高速重發(fā)機(jī)制”,也叫快重傳。?
????????????????????????????????????????序號(hào)還支持滑動(dòng)窗口的滑動(dòng)規(guī)則。
一直向右滑動(dòng),空間不夠了怎么辦?
????????從剛剛的說(shuō)法來(lái)說(shuō),發(fā)送緩沖渠的空間不是無(wú)窮的,因此滑動(dòng)窗口一定回到緩沖區(qū)的尾部。
? ? ? ? 實(shí)際上發(fā)送緩沖區(qū)的結(jié)構(gòu)是一個(gè)環(huán)形數(shù)組,因此不會(huì)出現(xiàn)這種情況。
流量控制
? ? ? ? 接收段處理數(shù)據(jù)的速度有限,如果發(fā)的太快,接收端處理不及時(shí),會(huì)出現(xiàn)丟包的情況,因此需要流量控制。
- 接收端將自己的緩沖區(qū)的剩余空間大小放在報(bào)文中的窗口大小字段中,通過(guò)ACK通知發(fā)送端。
- 窗口越大,吞吐量越大。
- 接收端發(fā)現(xiàn)緩沖區(qū)快滿(mǎn)了,就會(huì)減小窗口大小。
- 若是窗口設(shè)置為0,發(fā)送端停止發(fā)送數(shù)據(jù),但是會(huì)定期發(fā)送窗口探測(cè)數(shù)據(jù)。
16位窗口最大為65535,但是TCP窗口不止65535,在報(bào)頭的選項(xiàng)中,有一個(gè)窗口擴(kuò)大因子M,TCP窗口大小為窗口字段的值右移M位。
擁塞控制
? ? ? ? 一般在網(wǎng)絡(luò)上,同時(shí)會(huì)有很多計(jì)算機(jī)互相通信,即使TCP有滑動(dòng)窗口來(lái)可靠的發(fā)送大量數(shù)據(jù),但是如果一口氣就發(fā)送大量數(shù)據(jù)依舊會(huì)造成一些問(wèn)題。
? ? ? ? ?在客戶(hù)端和服務(wù)器互相通信的時(shí)候,網(wǎng)絡(luò)中依舊有很多計(jì)算機(jī)在互相通信,這樣會(huì)造成網(wǎng)絡(luò)阻塞,因此服務(wù)器只應(yīng)答了幾條報(bào)文。
? ? ? ? 像這種大量的丟包,我們就認(rèn)為是網(wǎng)絡(luò)出現(xiàn)了阻塞。
? ? ? ? 為了應(yīng)對(duì)這種情況,TCP引入了慢啟動(dòng)機(jī)制,先發(fā)少量數(shù)據(jù)來(lái)查看網(wǎng)絡(luò)擁堵?tīng)顟B(tài),再來(lái)決定傳輸?shù)乃俣取?/p>
- 此處引入擁塞窗口概念?
- 傳輸開(kāi)始時(shí),擁塞窗口概念為1
- 每收到一個(gè)應(yīng)答,擁塞窗口+1
- 每次發(fā)送數(shù)據(jù)的時(shí)候,將擁塞窗口和接收段主機(jī)的窗口大小比較,取較小值作為實(shí)際發(fā)送的窗口
像上圖中的擁塞窗口大小按指數(shù)級(jí)增長(zhǎng),但是擁塞窗口不能這樣增長(zhǎng),否則后期會(huì)增長(zhǎng)過(guò)快。
因此需要一個(gè)閾值來(lái)控制速度,當(dāng)擁塞窗口大小超過(guò)該閾值時(shí),就需要按線(xiàn)性方式增長(zhǎng)。
- ?TCP剛啟動(dòng)時(shí),慢啟動(dòng)閾值等于窗口最大值
- 超時(shí)重發(fā)時(shí),慢啟動(dòng)閾值會(huì)變成原來(lái)的一半,擁塞窗口大小置1
通過(guò)擁塞控制,TCP能夠盡快的將數(shù)據(jù)傳給對(duì)方,而不對(duì)網(wǎng)絡(luò)造成太大壓力。
延遲應(yīng)答
? ? ? ? 有時(shí)候,接收端主機(jī)若是剛接收到報(bào)文就立馬應(yīng)答,它的接收緩沖區(qū)可能剩余空間很小,返回的窗口也很小,這樣發(fā)送端發(fā)送的數(shù)據(jù)也會(huì)變少。
- 比如接收端接收到數(shù)據(jù)后還剩500k的窗口
- 但是它的處理速度很快,也許200ms后就能夠處理500k的數(shù)據(jù),這樣窗口就有1m了
- 因此接收端有時(shí)候會(huì)等一會(huì)再應(yīng)答,這樣能夠接收更多的數(shù)據(jù)
? ? ? ? 這就是延遲應(yīng)答,但是延遲應(yīng)答也是有條件的。
數(shù)量限制:每隔N個(gè)包應(yīng)答一次
時(shí)間限制:超過(guò)最大延遲時(shí)間就應(yīng)答一次
N一般為2,最大延遲時(shí)間為200ms
?
? ? ? ? 這樣返回的窗口越大,其傳輸?shù)乃俣确炊炝恕?/p>
捎帶應(yīng)答
? ? ? ? 有時(shí)候服務(wù)器和客戶(hù)端之間是 “一發(fā)一收” 的狀態(tài),這個(gè)時(shí)候服務(wù)器就能夠順帶把ACK和回復(fù)的報(bào)文放一起。
? ? ? ? 比如四次揮手的過(guò)程,服務(wù)器能夠?qū)⒆詈蟮?ACK 和 FYN 放一起給客戶(hù)端。?
?面向字節(jié)流
? ? ? ? 創(chuàng)建TCP的socket時(shí),還會(huì)創(chuàng)建對(duì)應(yīng)的接收緩沖區(qū)和發(fā)送緩沖區(qū)。
- 調(diào)用write會(huì)把數(shù)據(jù)先拷貝到發(fā)送緩沖區(qū)中?
- 過(guò)長(zhǎng)則拆分成多個(gè)數(shù)據(jù)包發(fā)送
- 過(guò)短則放在發(fā)送緩沖區(qū)等待合適的時(shí)機(jī)或者長(zhǎng)度夠了再發(fā)
- 接收數(shù)據(jù)的時(shí)候也是先從網(wǎng)卡拷貝到接收緩沖區(qū)
- 然后應(yīng)用層調(diào)用read來(lái)從接收緩沖區(qū)拿數(shù)據(jù)
- 這種一個(gè)鏈接可以寫(xiě)也可以讀的模式稱(chēng)為全雙工
? ? ? ? 由于緩沖區(qū)的存在,TCP的讀寫(xiě)互不影響。
可以一次寫(xiě)100個(gè)字節(jié)的數(shù)據(jù),也可以寫(xiě)100次一個(gè)字節(jié)的數(shù)據(jù),讀取也是。
粘包問(wèn)題
? ? ? ? 對(duì)于TCP來(lái)說(shuō),TCP沒(méi)有報(bào)文長(zhǎng)度的字段,只有一個(gè)序號(hào)的字段。
? ? ? ? 對(duì)于TCP來(lái)說(shuō),它可以按照序號(hào)將數(shù)據(jù)排序,但是從應(yīng)用層來(lái)說(shuō),它只看到了一連串的字符數(shù)據(jù),這樣應(yīng)用層就分辨不了哪個(gè)數(shù)據(jù)是哪個(gè)報(bào)文的。
? ? ? ? 為了避免這個(gè)問(wèn)題,就需要明確包與包之間的邊界。?
- 對(duì)于定長(zhǎng)的包,可以按固定大小讀取。
- 變長(zhǎng)的包,可以在包頭的位置約定一個(gè)包總長(zhǎng)的字段
- 也可以在包與包之間約定一個(gè)特殊的分隔符
? ? ? ? 但是對(duì)于UDP來(lái)說(shuō)就不存在這種問(wèn)題了。
? ? ? ? 一個(gè)是UDP報(bào)頭有一個(gè)報(bào)文長(zhǎng)度的字段,并且UDP是一個(gè)報(bào)文一個(gè)報(bào)文發(fā)給應(yīng)用層的。
TCP異常
-
進(jìn)程終止:這種情況會(huì)釋放文件描述符,依舊可以發(fā)送FYN。
-
機(jī)器重啟:這種情況下類(lèi)似于進(jìn)程終止。
-
機(jī)器斷開(kāi)電源/拔網(wǎng)線(xiàn):這種情況下如果有寫(xiě)入操作,接收端會(huì)發(fā)現(xiàn)連接不在了,就會(huì)reset,并且TCP內(nèi)部也有定時(shí)器,定時(shí)詢(xún)問(wèn)連接是否存在。
TCP小結(jié)
可靠性:
- 校驗(yàn)和
- 序號(hào)
- 確認(rèn)應(yīng)答
- 超時(shí)重傳
- 連接管理
- 流量控制
- 擁塞控制
提高性能
- 滑動(dòng)窗口
- 快速重傳
- 延遲應(yīng)答
- 捎帶應(yīng)答
基于TCP的應(yīng)用層協(xié)議
- HTTP
- HTTPS
- SSH
- Telnet
- FTP
- SMTP
TCP與UDP對(duì)比
? ? ? ? 其實(shí)二者并無(wú)優(yōu)劣之分,只是需要根據(jù)不同的應(yīng)用場(chǎng)景來(lái)使用不同的協(xié)議。
TCP適用于可靠傳輸?shù)膱?chǎng)景,而UDP適用于高速傳輸和對(duì)實(shí)時(shí)性要求高的場(chǎng)景。
Listen函數(shù)的第二個(gè)參數(shù)
????????
? ? ? ? ?第二個(gè)參數(shù)backlog實(shí)際上是為上層維護(hù)的鏈接隊(duì)列的長(zhǎng)度,這個(gè)長(zhǎng)度不可沒(méi)有,也不可太長(zhǎng)。
? ? ? ? 我們將gbacklog設(shè)為2,然后注釋掉accept。
????????然后用四個(gè)客戶(hù)端來(lái)連接這個(gè)服務(wù)器,然后使用netstat命令查看服務(wù)器連接情況。
? ? ? ? ?我們發(fā)現(xiàn)連接隊(duì)列中只有三個(gè)連接是被維護(hù)著的,也就是全連接狀態(tài),還有一個(gè)連接從服務(wù)器角度來(lái)看還在SYN_RECV中,也就是所謂的半連接狀態(tài)。
? ? ? ??這樣backlog的含義就知道了,它是指服務(wù)器維護(hù)的全連接隊(duì)列的長(zhǎng)度,長(zhǎng)度為backlog + 1.
? ? ? ? 如果服務(wù)器一直未accept,或者說(shuō)服務(wù)器內(nèi)部的鏈接已滿(mǎn),還未退出,那么這個(gè)全連接隊(duì)列就無(wú)法accept。
全連接隊(duì)列:已建立連接,但是未accept的鏈接。
總結(jié)
? ? ? ? 以上就是應(yīng)用層的HTTP+HTTPS的細(xì)節(jié),以及傳輸層UDP以及TCP詳解。
? ? ? ? 了解了HTTP的報(bào)頭,協(xié)議格式,以及方法, 狀態(tài)碼,session,cookie,還有HTTPS是如何加密的。
? ? ? ? 了解了UDP報(bào)頭,協(xié)議格式等。
? ? ? ? 了解了TCP報(bào)頭格式,如何連接,實(shí)現(xiàn)可靠性,還了解了超時(shí)重傳機(jī)制,確認(rèn)應(yīng)答機(jī)制,連接管理機(jī)制,序號(hào)的作用,滑動(dòng)窗口,擁塞控制,流量控制,快速重傳,延遲應(yīng)答和捎帶應(yīng)答。文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-639363.html
? ? ? ? 對(duì)于網(wǎng)絡(luò)基礎(chǔ)有了一定的了解,但是對(duì)于網(wǎng)絡(luò)層和數(shù)據(jù)鏈路層我們依舊未知,還是需要繼續(xù)努力。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-639363.html
到了這里,關(guān)于網(wǎng)絡(luò)基礎(chǔ)2(HTTP,HTTPS,傳輸層協(xié)議詳解)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!