wordpress簡潔seo是什么工作內(nèi)容
一:應(yīng)用層重點(diǎn)協(xié)議
1.1: DNS
DNS,即Domain Name System,域名系統(tǒng)。DNS是一整套從域名映射到IP的系統(tǒng)。
TCP/IP中使用IP地址來確定網(wǎng)絡(luò)上的一臺(tái)主機(jī),但是IP地址不方便記憶,且不能表達(dá)地址組織信息,于是人們發(fā)明了域名,并通過域名系統(tǒng)來映射域名和IP地址。
域名是一個(gè)字符串,如 www.baidu.com , hr.nowcoder.com
域名系統(tǒng)為一個(gè)樹形結(jié)構(gòu)的系統(tǒng),包含多個(gè)根節(jié)點(diǎn)。其中:
- 根節(jié)點(diǎn)即為根域名服務(wù)器,最早IPv4的根域名服務(wù)器全球只有13臺(tái),IPv6在此基礎(chǔ)上擴(kuò)充了
數(shù)量。 - 子節(jié)點(diǎn)主要由各級DNS服務(wù)器,或DNS緩存構(gòu)成。
DNS域名服務(wù)器,即提供域名轉(zhuǎn)換為IP地址的服務(wù)器,瀏覽器、主機(jī)系統(tǒng)、路由器中都保存有DNS緩存,Windows系統(tǒng)的DNS緩存在C:\Windows\System32\drivers\etc\hosts 文件中,Mac/Linux系統(tǒng)的DNS緩存在 /etc/hosts 文件中。
網(wǎng)絡(luò)通信發(fā)送數(shù)據(jù)時(shí),如果使用目的主機(jī)的域名,需要先通過域名解析查找到對應(yīng)的IP地址:
- 域名解析的過程,可以簡單的理解為:發(fā)送端主機(jī)作為域名系統(tǒng)樹形結(jié)構(gòu)的一個(gè)子節(jié)點(diǎn),通過域名信息,從下到上查找對應(yīng)IP地址的過程。如果到根節(jié)點(diǎn)(根域名服務(wù)器)還找不到,即找不到該主機(jī)。
- 域名解析使用DNS協(xié)議來傳輸數(shù)據(jù)。DNS協(xié)議是應(yīng)用層協(xié)議,基于傳輸層UDP或TCP協(xié)議來實(shí)現(xiàn)。
1.2:NAT
之前我們討論了,IPv4協(xié)議中,IP地址數(shù)量不充足的問題,NAT技術(shù)是當(dāng)前解決IP地址不夠用的主要手段,是路由器的一個(gè)重要功能;
-
NAT能夠?qū)⑺接蠭P對外通信時(shí)轉(zhuǎn)為全局IP。也就是就是一種將私有IP和全局IP相互轉(zhuǎn)化的技術(shù)方法:
-
很多學(xué)校,家庭,公司內(nèi)部采用每個(gè)終端設(shè)置私有IP,而在路由器或必要的服務(wù)器上設(shè)置全局IP;
-
全局IP要求唯一,但是私有IP不需要;在不同的局域網(wǎng)中出現(xiàn)相同的私有IP是完全不影響的;
NAT IP轉(zhuǎn)換過程:
- NAT路由器將源地址從10.0.0.10替換成全局的IP 202.244.174.37;
- NAT路由器收到外部的數(shù)據(jù)時(shí),又會(huì)把目標(biāo)IP從202.244.174.37替換回10.0.0.10;
- 在NAT路由器內(nèi)部,有一張自動(dòng)生成的,用于地址轉(zhuǎn)換的表;
- 當(dāng) 10.0.0.10 第一次向 163.221.120.9 發(fā)送數(shù)據(jù)時(shí)就會(huì)生成表中的映射關(guān)系;
1.3:NAPT
那么問題來了,如果局域網(wǎng)內(nèi),有多個(gè)主機(jī)都訪問同一個(gè)外網(wǎng)服務(wù)器,那么對于服務(wù)器返回的數(shù)據(jù)中,目的IP都是相同的。那么NAT路由器如何判定將這個(gè)數(shù)據(jù)包轉(zhuǎn)發(fā)給哪個(gè)局域網(wǎng)的主機(jī)?
這時(shí)候NAPT來解決這個(gè)問題了。使用IP+port來建立這個(gè)關(guān)聯(lián)關(guān)系
這種關(guān)聯(lián)關(guān)系也是由NAT路由器自動(dòng)維護(hù)的。例如在TCP的情況下,建立連接時(shí),就會(huì)生成這個(gè)表項(xiàng);在斷開連接后,就會(huì)刪除這個(gè)表項(xiàng)
由于NAT依賴這個(gè)轉(zhuǎn)換表,所以有諸多限制:
- 無法從NAT外部向內(nèi)部服務(wù)器建立連接;
- 轉(zhuǎn)換表的生成和銷毀都需要額外開銷;
- 通信過程中一旦NAT設(shè)備異常,即使存在熱備,所有的TCP連接也都會(huì)斷開;
二:傳輸層重要協(xié)議
2.1 TCP協(xié)議
TCP,即Transmission Control Protocol,傳輸控制協(xié)議。人如其名,要對數(shù)據(jù)的傳輸進(jìn)行一個(gè)詳細(xì)的控制。
TCP協(xié)議段格式
- 源/目的端口號:表示數(shù)據(jù)是從哪個(gè)進(jìn)程來,到哪個(gè)進(jìn)程去;
- 32位序號/32位確認(rèn)號:后面詳細(xì)講;
- 4位TCP報(bào)頭長度:表示該TCP頭部有多少個(gè)32位bit(有多少個(gè)4字節(jié));所以TCP頭部最大長度是15 * 4 = 60
6位標(biāo)志位:
- URG:緊急指針是否有效
- ACK:確認(rèn)號是否有效
- PSH:提示接收端應(yīng)用程序立刻從TCP緩沖區(qū)把數(shù)據(jù)讀走
- RST:對方要求重新建立連接;我們把攜帶RST標(biāo)識的稱為復(fù)位報(bào)文段
- SYN:請求建立連接;我們把攜帶SYN標(biāo)識的稱為同步報(bào)文段
- FIN:通知對方,本端要關(guān)閉了,我們稱攜帶FIN標(biāo)識的為結(jié)束報(bào)文段
- 16位窗口大小:后面再說
- 16位校驗(yàn)和:發(fā)送端填充,CRC校驗(yàn)。接收端校驗(yàn)不通過,則認(rèn)為數(shù)據(jù)有問題。此處的檢驗(yàn)和不光包含TCP首部,也包含TCP數(shù)據(jù)部分。
- 16位緊急指針:標(biāo)識哪部分?jǐn)?shù)據(jù)是緊急數(shù)據(jù);
- 40字節(jié)頭部選項(xiàng):暫時(shí)忽略;
2.2 TCP管控
TCP對數(shù)據(jù)傳輸提供的管控機(jī)制,主要體現(xiàn)在兩個(gè)方面:安全和效率。
這些機(jī)制和多線程的設(shè)計(jì)原則類似:保證數(shù)據(jù)傳輸安全的前提下,盡可能的提高傳輸效率。
2.2.1 確認(rèn)應(yīng)答機(jī)制(安全機(jī)制)
TCP將每個(gè)字節(jié)的數(shù)據(jù)都進(jìn)行了編號。即為序列號。
每一個(gè)ACK都帶有對應(yīng)的確認(rèn)序列號,意思是告訴發(fā)送者,我已經(jīng)收到了哪些數(shù)據(jù);下一次你從哪里開始發(fā)。
例如確認(rèn)序號1001 的含義:
- <1001 的數(shù)據(jù),我已經(jīng)收到
- 我接下來想向發(fā)送方索要從1001 開始的數(shù)據(jù)
注意:確認(rèn)序號取的是發(fā)送方送過來的所有數(shù)據(jù)的最后一個(gè)字節(jié)序號 + 1,并且接收方的序號和發(fā)送方的序號無關(guān)。
2.2.2 超時(shí)重傳機(jī)制(安全機(jī)制)
- 主機(jī)A發(fā)送數(shù)據(jù)給B之后,可能因?yàn)榫W(wǎng)絡(luò)擁堵等原因,數(shù)據(jù)無法到達(dá)主機(jī)B;
- 如果主機(jī)A在一個(gè)特定時(shí)間間隔內(nèi)沒有收到B發(fā)來的確認(rèn)應(yīng)答,就會(huì)進(jìn)行重發(fā);
超時(shí)的時(shí)間如何確定呢?
- 最理想的情況下,找到一個(gè)最小的時(shí)間,保證 “確認(rèn)應(yīng)答一定能在這個(gè)時(shí)間內(nèi)返回”。
- 但是這個(gè)時(shí)間的長短,隨著網(wǎng)絡(luò)環(huán)境的不同,是有差異的。
- 如果超時(shí)時(shí)間設(shè)的太長,會(huì)影響整體的重傳效率;
- 如果超時(shí)時(shí)間設(shè)的太短,有可能會(huì)頻繁發(fā)送重復(fù)的包;
TCP為了保證無論在任何環(huán)境下都能比較高性能的通信,因此會(huì)動(dòng)態(tài)計(jì)算這個(gè)最大超時(shí)時(shí)間。
- Linux中(BSD Unix和Windows也是如此),超時(shí)以500ms為一個(gè)單位進(jìn)行控制,每次判定超時(shí)重發(fā)的超時(shí)時(shí)間都是500ms的整數(shù)倍。
- 如果重發(fā)一次之后,仍然得不到應(yīng)答,等待 2*500ms 后再進(jìn)行重傳。
- 如果仍然得不到應(yīng)答,等待 4*500ms 進(jìn)行重傳。依次類推,以指數(shù)形式遞增。
- 累計(jì)到一定的重傳次數(shù),TCP認(rèn)為網(wǎng)絡(luò)或者對端主機(jī)出現(xiàn)異常,強(qiáng)制關(guān)閉連接。
但是,主機(jī)A未收到B發(fā)來的確認(rèn)應(yīng)答,也可能是因?yàn)锳CK丟失了;
因此主機(jī)B會(huì)收到很多重復(fù)數(shù)據(jù)。那么TCP協(xié)議需要能夠識別出那些包是重復(fù)的包,并且把重復(fù)的丟棄掉。
這時(shí)候我們可以利用前面提到的序列號,就可以很容易做到去重的效果。
2.2.3 連接管理機(jī)制(安全機(jī)制)
在正常情況下,TCP要經(jīng)過三次握手建立連接,四次揮手?jǐn)嚅_連接
2.2.3.1 三次握手 — 建立連接
三次握手是指在建立 TCP 連接時(shí),客戶端和服務(wù)器之間進(jìn)行的三次通信過程。
第一次握手:客戶端向服務(wù)器發(fā)送一個(gè) SYN(同步)包,告訴服務(wù)器自己要建立連接。
第二次握手:服務(wù)器收到客戶端的 SYN 包后,會(huì)回復(fù)一個(gè) SYN-ACK(同步-確認(rèn))包,表示同意建立連接。
第三次握手:客戶端收到服務(wù)器的 SYN-ACK 包后,會(huì)再發(fā)送一個(gè) ACK(確認(rèn))包給服務(wù)器,表示客戶端也同意建立連接。
通過這三次握手,建立了客戶端和服務(wù)器之間的 TCP 連接。
什么樣的報(bào)文算是syn報(bào)文呢?觀察TCP報(bào)頭結(jié)構(gòu):
三次握手這個(gè)過程,本質(zhì)上是投石問路~驗(yàn)證了客戶端和服務(wù)器,各自的發(fā)送能力和接收能力是否正常!!!
這就好比每天地鐵的第一趟是空車,不載客人的,這就是為了確認(rèn)地鐵路線是否通暢安全,這空車跑一趟就說投石問路
當(dāng)兩個(gè)設(shè)備(客戶端和服務(wù)器)希望建立一個(gè)TCP連接時(shí),需要進(jìn)行三次握手來驗(yàn)證彼此的發(fā)送和接收能力是否正常。
現(xiàn)在,讓我們來解釋一下為什么這個(gè)過程可以驗(yàn)證發(fā)送和接收能力是否正常:
- 第一次握手:客戶端發(fā)送給服務(wù)器一個(gè)SYN包,如果服務(wù)器能正常接收到并響應(yīng),說明服務(wù)器的接收能力正常。
- 第二次握手:服務(wù)器收到客戶端發(fā)送的SYN包后,發(fā)送一個(gè)SYN-ACK包回客戶端,如果客戶端能正常收到并響應(yīng),說明客戶端的接收能力和發(fā)送能力正常。
- 第三次握手:客戶端收到服務(wù)器發(fā)送的SYN-ACK包后,發(fā)送一個(gè)ACK包給服務(wù)器,如果服務(wù)器能正常接收到并響應(yīng),說明服務(wù)器的發(fā)送能力正常。而客戶端收到服務(wù)器的響應(yīng)后,驗(yàn)證連接建立成功,可以開始正常的數(shù)據(jù)傳輸。
通過三次握手的過程,客戶端和服務(wù)器可以互相驗(yàn)證彼此的發(fā)送和接收能力,確保雙方都能正常通信。
2.2.3.2 四次揮手 — 斷開連接
四次揮手是指TCP連接的主動(dòng)關(guān)閉過程,用于終止TCP連接。它是建立在三次握手的基礎(chǔ)上的,確保數(shù)據(jù)完整可靠地傳輸。下面是四次揮手的詳細(xì)步驟:
-
客戶端發(fā)起關(guān)閉連接請求:客戶端首先發(fā)送一個(gè)FIN(Finish)報(bào)文段給服務(wù)器,用來請求關(guān)閉連接。
-
服務(wù)器確認(rèn)關(guān)閉請求:服務(wù)器收到客戶端發(fā)送的FIN報(bào)文段后,會(huì)向客戶端發(fā)送一個(gè)ACK(Acknowledgment)報(bào)文段,用來確認(rèn)收到了關(guān)閉請求。
-
服務(wù)器發(fā)送關(guān)閉請求:服務(wù)器在確認(rèn)客戶端的關(guān)閉請求后,會(huì)發(fā)送一個(gè)FIN報(bào)文段給客戶端,表示服務(wù)器也希望關(guān)閉連接。
-
客戶端確認(rèn)關(guān)閉:客戶端收到服務(wù)器發(fā)送的FIN報(bào)文段后,會(huì)向服務(wù)器發(fā)送一個(gè)ACK報(bào)文段,表示客戶端已經(jīng)確認(rèn)關(guān)閉請求,然后等待一段時(shí)間,確保服務(wù)器收到了該確認(rèn)。
注意:關(guān)閉連接的一方在發(fā)送完最后的ACK報(bào)文段后,并不立即關(guān)閉連接,而是等待一段時(shí)間(即等待2倍的最大報(bào)文段生存時(shí)間,也就是2MSL),以確保雙方都能收到對方的確認(rèn)。這樣可以避免在網(wǎng)絡(luò)中產(chǎn)生的延遲導(dǎo)致的數(shù)據(jù)包重傳。
四次揮手的過程保證了雙方在關(guān)閉連接時(shí)的可靠性和完整性。通過這個(gè)過程,雙方能夠停止數(shù)據(jù)的傳輸,并釋放TCP連接所占用的資源。
四次揮手僅在雙方均希望關(guān)閉連接時(shí)才發(fā)生。如果其中一方不希望關(guān)閉連接,可以不發(fā)送FIN報(bào)文段或不回復(fù)ACK報(bào)文段,從而保持連接的持續(xù)性。
為啥 三次握手 能 100%合并四次揮手 就不能合并??這是因?yàn)?#xff1a;
- 三次握手,ack 和 syn 是同一個(gè)時(shí)機(jī)觸發(fā)的(都是內(nèi)核來完成的)
- 四次揮手,ack 和 fin 則是不同時(shí)機(jī)觸發(fā)的.
- ack 是內(nèi)核完成的.會(huì)在收到 fin 的時(shí)候第一時(shí)間返回
- fin 則是應(yīng)用程序代碼控制的.在調(diào)用到 socket 的close 方法的時(shí)候才會(huì)觸發(fā)fin !!!
2.2.4 滑動(dòng)窗口(效率機(jī)制)
剛才我們討論了確認(rèn)應(yīng)答策略,對每一個(gè)發(fā)送的數(shù)據(jù)段,都要給一個(gè)ACK確認(rèn)應(yīng)答。收到ACK后再發(fā)送下一個(gè)數(shù)據(jù)段。這樣做有一個(gè)比較大的缺點(diǎn),就是性能較差。尤其是數(shù)據(jù)往返的時(shí)間較長的時(shí)候。
既然這樣一發(fā)一收的方式性能較低,那么我們一次發(fā)送多條數(shù)據(jù),就可以大大的提高性能(其實(shí)是將多個(gè)段的等待時(shí)間重疊在一起了)。
- 窗口大小指的是無需等待確認(rèn)應(yīng)答而可以繼續(xù)發(fā)送數(shù)據(jù)的最大值。上圖的窗口大小就是4000個(gè)字節(jié)(四個(gè)段)。
- 發(fā)送前四個(gè)段的時(shí)候,不需要等待任何ACK,直接發(fā)送;
- 收到第一個(gè)ACK后,滑動(dòng)窗口向后移動(dòng),繼續(xù)發(fā)送第五個(gè)段的數(shù)據(jù);依次類推.
- 操作系統(tǒng)內(nèi)核為了維護(hù)這個(gè)滑動(dòng)窗口,需要開辟 發(fā)送緩沖區(qū) 來記錄當(dāng)前還有哪些數(shù)據(jù)沒有應(yīng)答;只有確認(rèn)應(yīng)答過的數(shù)據(jù),才能從緩沖區(qū)刪掉;
- 窗口越大,則網(wǎng)絡(luò)的吞吐率就越高;
當(dāng)收到 2001 這個(gè) ack 意味著 1001-2000 這個(gè)數(shù)據(jù)得到了確認(rèn),此時(shí)就會(huì)立即發(fā)下一個(gè)5001-6000 這個(gè)數(shù)據(jù)
此時(shí)看到的效果,就好像,窗口還是這么大,但是往后挪了一個(gè)格子.如果收到的 ack 非常快,此時(shí)這個(gè)窗口就在快速的往后滑動(dòng)~~
但是如果在傳輸過程中出現(xiàn)了丟包,如何進(jìn)行重傳?這里分兩種情況討論。
情況一:數(shù)據(jù)包已經(jīng)抵達(dá),ACK被丟了。
這種情況下,部分ACK丟了并不要緊,因?yàn)榭梢酝ㄟ^后續(xù)的ACK進(jìn)行確認(rèn),如果是最后一個(gè)包丟了,就照常超時(shí)重傳。
情況二:數(shù)據(jù)包就直接丟了。
- 當(dāng)某一段報(bào)文段丟失之后,發(fā)送端會(huì)一直收到 1001 這樣的ACK,就像是在提醒發(fā)送端 “我想要的是 1001” 一樣;
- 如果發(fā)送端主機(jī)連續(xù)三次收到了同樣一個(gè) “1001” 這樣的應(yīng)答,就會(huì)將對應(yīng)的數(shù)據(jù) 1001 -2000 重新發(fā)送;
- 這個(gè)時(shí)候接收端收到了 1001 之后,再次返回的ACK就是7001了(因?yàn)?001 - 7000)接收端其實(shí)之前就已經(jīng)收到了,被放到了接收端操作系統(tǒng)內(nèi)核的接收緩沖區(qū)中;
這種機(jī)制被稱為 “高速重發(fā)控制”(也叫 “快重傳”)。
2.2.5 流量控制(安全機(jī)制)
接收端處理數(shù)據(jù)的速度是有限的。如果發(fā)送端發(fā)的太快,導(dǎo)致接收端的緩沖區(qū)被打滿,這個(gè)時(shí)候如果發(fā)送端繼續(xù)發(fā)送,就會(huì)造成丟包,繼而引起丟包重傳等等一系列連鎖反應(yīng)。因此TCP支持根據(jù)接收端的處理能力,來決定發(fā)送端的發(fā)送速度。這個(gè)機(jī)制就叫做流量控制(FlowControl);
- 接收端將自己可以接收的緩沖區(qū)大小放入 TCP 首部中的 “窗口大小” 字段,通過ACK端通知發(fā)送端;
- 窗口大小字段越大,說明網(wǎng)絡(luò)的吞吐量越高;
- 接收端一旦發(fā)現(xiàn)自己的緩沖區(qū)快滿了,就會(huì)將窗口大小設(shè)置成一個(gè)更小的值通知給發(fā)送端;
- 發(fā)送端接受到這個(gè)窗口之后,就會(huì)減慢自己的發(fā)送速度;
- 如果接收端緩沖區(qū)滿了,就會(huì)將窗口置為0;這時(shí)發(fā)送方不再發(fā)送數(shù)據(jù),但是需要定期發(fā)送一個(gè)窗口探測數(shù)據(jù)段,使接收端把窗口大小告訴發(fā)送端。
接收端如何把窗口大小告訴發(fā)送端呢?回憶我們的TCP首部中,有一個(gè)16位窗口字段,就是存放了窗口大小信息;
那么問題來了,16位數(shù)字最大表示65535,那么TCP窗口最大就是65535字節(jié)么?
實(shí)際上,TCP首部40字節(jié)選項(xiàng)中還包含了一個(gè)窗口擴(kuò)大因子M,實(shí)際窗口大小是 窗口字段的值左移 M位;
2.2.6 擁塞控制(安全機(jī)制)
雖然TCP有了滑動(dòng)窗口這個(gè)大殺器,能夠高效可靠的發(fā)送大量的數(shù)據(jù)。但是如果在剛開始階段就發(fā)送大量的數(shù)據(jù),仍然可能引發(fā)問題。
因?yàn)榫W(wǎng)絡(luò)上有很多的計(jì)算機(jī),可能當(dāng)前的網(wǎng)絡(luò)狀態(tài)就已經(jīng)比較擁堵。在不清楚當(dāng)前網(wǎng)絡(luò)狀態(tài)下,貿(mào)然發(fā)送大量的數(shù)據(jù),是很有可能引起雪上加霜的。
TCP引入 慢啟動(dòng) 機(jī)制,先發(fā)少量的數(shù)據(jù),探探路,摸清當(dāng)前的網(wǎng)絡(luò)擁堵狀態(tài),再?zèng)Q定按照多大的速度傳輸數(shù)據(jù);
- 此處引入一個(gè)概念程為擁塞窗口
- 發(fā)送開始的時(shí)候,定義擁塞窗口大小為1;
- 每次收到一個(gè)ACK應(yīng)答,擁塞窗口加1;
- 每次發(fā)送數(shù)據(jù)包的時(shí)候,將擁塞窗口和接收端主機(jī)反饋的窗口大小做比較,取較小的值作為實(shí)際發(fā)送的窗口;
像上面這樣的擁塞窗口增長速度,是指數(shù)級別的?!奥龁?dòng)” 只是指初使時(shí)慢,但是增長速度非???。
- 為了不增長的那么快,因此不能使擁塞窗口單純的加倍。
- 此處引入一個(gè)叫做慢啟動(dòng)的閾值
- 當(dāng)擁塞窗口超過這個(gè)閾值的時(shí)候,不再按照指數(shù)方式增長,而是按照線性方式增長
- 當(dāng)TCP開始啟動(dòng)的時(shí)候,慢啟動(dòng)閾值等于窗口最大值;
- 在每次超時(shí)重發(fā)的時(shí)候,慢啟動(dòng)閾值會(huì)變成原來的一半,同時(shí)擁塞窗口置回1;
少量的丟包,我們僅僅是觸發(fā)超時(shí)重傳;大量的丟包,我們就認(rèn)為網(wǎng)絡(luò)擁塞,當(dāng)TCP通信開始后,網(wǎng)絡(luò)吞吐量會(huì)逐漸上升;隨著網(wǎng)絡(luò)發(fā)生擁堵,吞吐量會(huì)立刻下降;
擁塞控制,歸根結(jié)底是TCP協(xié)議想盡可能快的把數(shù)據(jù)傳輸給對方,但是又要避免給網(wǎng)絡(luò)造成太大壓力的折中方案。
2.2.7 延遲應(yīng)答(效率機(jī)制)
如果接收數(shù)據(jù)的主機(jī)立刻返回ACK應(yīng)答,這時(shí)候返回的窗口可能比較小。
- 假設(shè)接收端緩沖區(qū)為1M。一次收到了500K的數(shù)據(jù);如果立刻應(yīng)答,返回的窗口就是500K;
- 但實(shí)際上可能處理端處理的速度很快,10ms之內(nèi)就把500K數(shù)據(jù)從緩沖區(qū)消費(fèi)掉了;
- 在這種情況下,接收端處理還遠(yuǎn)沒有達(dá)到自己的極限,即使窗口再放大一些,也能處理過來;
- 如果接收端稍微等一會(huì)再應(yīng)答,比如等待200ms再應(yīng)答,那么這個(gè)時(shí)候返回的窗口大小就是1M;
一定要記得,窗口越大,網(wǎng)絡(luò)吞吐量就越大,傳輸效率就越高。我們的目標(biāo)是在保證網(wǎng)絡(luò)不擁塞的情況下盡量提高傳輸效率;
那么所有的包都可以延遲應(yīng)答么?肯定也不是;
- 數(shù)量限制:每隔N個(gè)包就應(yīng)答一次;
- 時(shí)間限制:超過最大延遲時(shí)間就應(yīng)答一次
具體的數(shù)量和超時(shí)時(shí)間,依操作系統(tǒng)不同也有差異;一般N取2,超時(shí)時(shí)間取200ms;
2.2.8 捎帶應(yīng)答(效率機(jī)制)
在延遲應(yīng)答的基礎(chǔ)上,我們發(fā)現(xiàn),很多情況下,客戶端服務(wù)器在應(yīng)用層也是 “一發(fā)一收” 的。意味著客戶端給服務(wù)器說了 “How are you”,服務(wù)器也會(huì)給客戶端回一個(gè) “Fine, thank you”;
那么這個(gè)時(shí)候ACK就可以搭順風(fēng)車,和服務(wù)器回應(yīng)的 “Fine,thank you” 一起回給客戶端
2.2.9 TCP其他特性
當(dāng)我們創(chuàng)建一個(gè)TCP的socket,同時(shí)在內(nèi)核中創(chuàng)建一個(gè) 發(fā)送緩沖區(qū) 和一個(gè) 接收緩沖區(qū);
- 調(diào)用write時(shí),數(shù)據(jù)會(huì)先寫入發(fā)送緩沖區(qū)中;
- 如果發(fā)送的字節(jié)數(shù)太長,會(huì)被拆分成多個(gè)TCP的數(shù)據(jù)包發(fā)出;
- 如果發(fā)送的字節(jié)數(shù)太短,就會(huì)先在緩沖區(qū)里等待,等到緩沖區(qū)長度差不多了,或者其他合適的時(shí)機(jī)發(fā)送出去;
- 接收數(shù)據(jù)的時(shí)候,數(shù)據(jù)也是從網(wǎng)卡驅(qū)動(dòng)程序到達(dá)內(nèi)核的接收緩沖區(qū);
- 然后應(yīng)用程序可以調(diào)用read從接收緩沖區(qū)拿數(shù)據(jù);
- 另一方面,TCP的一個(gè)連接,既有發(fā)送緩沖區(qū),也有接收緩沖區(qū),那么對于這一個(gè)連接,既可以讀數(shù)據(jù),也可以寫數(shù)據(jù)。這個(gè)概念叫做 全雙工
由于緩沖區(qū)的存在,TCP程序的讀和寫不需要一一匹配,例如:
- 寫100個(gè)字節(jié)數(shù)據(jù)時(shí),可以調(diào)用一次write寫100個(gè)字節(jié),也可以調(diào)用100次write,每次寫一個(gè)字節(jié);
- 讀100個(gè)字節(jié)數(shù)據(jù)時(shí),也完全不需要考慮寫的時(shí)候是怎么寫的,既可以一次read 100個(gè)字節(jié),也可以一次read一個(gè)字節(jié),重復(fù)100次;
2.2.10 粘包問題
- 首先要明確,粘包問題中的 “包” ,是指的應(yīng)用層的數(shù)據(jù)包。
- 在TCP的協(xié)議頭中,沒有如同UDP一樣的 “報(bào)文長度” 這樣的字段,但是有一個(gè)序號這樣的字段。
- 站在傳輸層的角度,TCP是一個(gè)一個(gè)報(bào)文過來的。按照序號排好序放在緩沖區(qū)中。
- 站在應(yīng)用層的角度,看到的只是一串連續(xù)的字節(jié)數(shù)據(jù)。
- 那么應(yīng)用程序看到了這么一連串的字節(jié)數(shù)據(jù),就不知道從哪個(gè)部分開始到哪個(gè)部分,是一個(gè)完整的應(yīng)用層數(shù)據(jù)包。
那么如何避免粘包問題呢?歸根結(jié)底就是一句話,明確兩個(gè)包之間的邊界。
- 對于定長的包,保證每次都按固定大小讀取即可;例如上面的Request結(jié)構(gòu),是固定大小的,那么就從緩沖區(qū)從頭開始按sizeof(Request)依次讀取即可;
- 對于變長的包,可以在包頭的位置,約定一個(gè)包總長度的字段,從而就知道了包的結(jié)束位置;
- 對于變長的包,還可以在包和包之間使用明確的分隔符(應(yīng)用層協(xié)議,是程序猿自己來定的,只要保證分隔符不和正文沖突即可);
對于UDP協(xié)議來說,并不會(huì)像TCP協(xié)議那樣存在嚴(yán)格意義上的粘包問題。
因?yàn)閷τ赨DP,如果還沒有上層交付數(shù)據(jù),UDP的報(bào)文長度仍然在。同時(shí),UDP是一個(gè)一個(gè)把數(shù)據(jù)交付給應(yīng)用層。就有很明確的數(shù)據(jù)邊界。站在應(yīng)用層的站在應(yīng)用層的角度,使用UDP的時(shí)候,要么收到完整的UDP報(bào)文,要么不收。不會(huì)出現(xiàn)"半個(gè)"的情況。
2.2.11 TCP異常情況
進(jìn)程終止:進(jìn)程終止會(huì)釋放文件描述符,仍然可以發(fā)送FIN。和正常關(guān)閉沒有什么區(qū)別。
機(jī)器重啟:和進(jìn)程終止的情況相同。
機(jī)器掉電/網(wǎng)線斷開:接收端認(rèn)為連接還在,一旦接收端有寫入操作,接收端發(fā)現(xiàn)連接已經(jīng)不在了,就會(huì)進(jìn)行reset。即使沒有寫入操作,TCP自己也內(nèi)置了一個(gè)?;疃〞r(shí)器,會(huì)定期詢問對方是否還在。如果對方不在,也會(huì)把連接釋放。
另外,應(yīng)用層的某些協(xié)議,也有一些這樣的檢測機(jī)制。例如HTTP長連接中,也會(huì)定期檢測對方的狀態(tài)。例如QQ,在QQ斷線之后,也會(huì)定期嘗試重新連接。
2.3 UDP協(xié)議
UDP協(xié)議端格式:
- 16位UDP長度,表示整個(gè)數(shù)據(jù)報(bào)(UDP首部+UDP數(shù)據(jù))的最大長度;
- 如果校驗(yàn)和出錯(cuò),就會(huì)直接丟棄;
2.3.1 UDP特點(diǎn)
UDP傳輸?shù)倪^程類似于寄信。
- 無連接
知道對端的IP和端口號就直接進(jìn)行傳輸,不需要建立連接;
- 不可靠
沒有任何安全機(jī)制,發(fā)送端發(fā)送數(shù)據(jù)報(bào)以后,如果因?yàn)榫W(wǎng)絡(luò)故障該段無法發(fā)到對方,UDP協(xié)議層也不會(huì)給應(yīng)用層返回任何錯(cuò)誤信息;
- 面向數(shù)據(jù)報(bào)
應(yīng)用層交給UDP多長的報(bào)文,UDP原樣發(fā)送,既不會(huì)拆分,也不會(huì)合并;用UDP傳輸100個(gè)字節(jié)的數(shù)據(jù):如果發(fā)送端一次發(fā)送100個(gè)字節(jié),那么接收端也必須一次接收100個(gè)字節(jié);而不能循環(huán)接收10次,每次接收10個(gè)字節(jié)。
- 緩沖區(qū)
UDP只有接收緩沖區(qū),沒有發(fā)送緩沖區(qū):
UDP沒有真正意義上的 發(fā)送緩沖區(qū)。發(fā)送的數(shù)據(jù)會(huì)直接交給內(nèi)核,由內(nèi)核將數(shù)據(jù)傳給網(wǎng)絡(luò)層協(xié)議進(jìn)行后續(xù)的傳輸動(dòng)作;
UDP具有接收緩沖區(qū),但是這個(gè)接收緩沖區(qū)不能保證收到的UDP報(bào)的順序和發(fā)送UDP報(bào)的順序一致;如果緩沖區(qū)滿了,再到達(dá)的UDP數(shù)據(jù)就會(huì)被丟棄;
UDP的socket既能讀,也能寫,這個(gè)概念叫做 全雙工
- 大小受限
UDP協(xié)議首部中有一個(gè)16位的最大長度。也就是說一個(gè)UDP能傳輸?shù)臄?shù)據(jù)最大長度是64K(包含UDP首部)。
基于UDP的應(yīng)用層協(xié)議:
- NFS:網(wǎng)絡(luò)文件系統(tǒng)
- TFTP:簡單文件傳輸協(xié)議
- DHCP:動(dòng)態(tài)主機(jī)配置協(xié)議
- BOOTP:啟動(dòng)協(xié)議(用于無盤設(shè)備啟動(dòng))
- DNS:域名解析協(xié)議
當(dāng)然,也包括自己寫UDP程序時(shí)自定義的應(yīng)用層協(xié)議。
三:網(wǎng)絡(luò)層重點(diǎn)協(xié)議
在復(fù)雜的網(wǎng)絡(luò)環(huán)境中確定一個(gè)合適的路徑。
3.1 IP協(xié)議
協(xié)議頭格式如下:
-
4位版本號(version):指定IP協(xié)議的版本,對于IPv4來說,就是4。
-
4位頭部長度(header length):IP頭部的長度是多少個(gè)32bit,也就是 length * 4
的字節(jié)數(shù)。4bit表示最大的數(shù)字是15,因此IP頭部最大長度是60字節(jié)。 -
8位服務(wù)類型(Type Of Service):3位優(yōu)先權(quán)字段(已經(jīng)棄用),4位TOS字段,和1位保留字段(必須置為0)。4位TOS分別表示:最小延時(shí),最大吞吐量,最高可靠性,最小成本。這四者相互沖突,只能選擇一個(gè)。對于ssh/telnet這樣的應(yīng)用程序,最小延時(shí)比較重要;對于ftp這樣的程序,最大吞吐量比較重要。
-
16位總長度(total length):IP數(shù)據(jù)報(bào)整體占多少個(gè)字節(jié)。
-
16位標(biāo)識(id):唯一的標(biāo)識主機(jī)發(fā)送的報(bào)文。如果IP報(bào)文在數(shù)據(jù)鏈路層被分片了,那么每一個(gè)片里面的這個(gè)id都是相同的。
-
3位標(biāo)志字段:第一位保留(保留的意思是現(xiàn)在不用,但是還沒想好說不定以后要用到)。第二位置為1表示禁止分片,這時(shí)候如果報(bào)文長度超過MTU,IP模塊就會(huì)丟棄報(bào)文。第三位表示"更多分片",如果分片了的話,最后一個(gè)分片置為1,其他是0。類似于一個(gè)結(jié)束標(biāo)記。
-
13位分片偏移(framegament offset):是分片相對于原始IP報(bào)文開始處的偏移。其實(shí)就是在表示當(dāng)前分片在原報(bào)文中處在哪個(gè)位置。實(shí)際偏移的字節(jié)數(shù)是這個(gè)值 * 8 得到的。因此,除了最后一個(gè)報(bào)文之外,其他報(bào)文的長度必須是8的整數(shù)倍(否則報(bào)文就不連續(xù)了)。
-
8位生存時(shí)間(Time To Live,TTL):數(shù)據(jù)報(bào)到達(dá)目的地的最大報(bào)文跳數(shù)。一般是64。每次經(jīng)過一個(gè)路由,TTL -= 1,一直減到0還沒到達(dá),那么就丟棄了。這個(gè)字段主要是用來防止出現(xiàn)路由循環(huán)。
-
8位協(xié)議:表示上層協(xié)議的類型。
-
16位頭部校驗(yàn)和:使用CRC進(jìn)行校驗(yàn),來鑒別頭部是否損壞。
-
32位源地址和32位目標(biāo)地址:表示發(fā)送端和接收端。
-
選項(xiàng)字段(不定長,最多40字節(jié)):略。
四:數(shù)據(jù)鏈路層重點(diǎn)協(xié)議
4.1 以太網(wǎng)
- “以太網(wǎng)” 不是一種具體的網(wǎng)絡(luò),而是一種技術(shù)標(biāo)準(zhǔn);既包含了數(shù)據(jù)鏈路層的內(nèi)容,也包含了一些物理層的內(nèi)容。例如:規(guī)定了網(wǎng)絡(luò)拓?fù)浣Y(jié)構(gòu),訪問控制方式,傳輸速率等;
- 例如以太網(wǎng)中的網(wǎng)線必須使用雙絞線;傳輸速率有10M,100M,1000M等;
- 以太網(wǎng)是當(dāng)前應(yīng)用最廣泛的局域網(wǎng)技術(shù);和以太網(wǎng)并列的還有令牌環(huán)網(wǎng),無線LAN等;
以太網(wǎng)幀格式:
- 源地址和目的地址是指網(wǎng)卡的硬件地址(也叫MAC地址),長度是48位,是在網(wǎng)卡出廠時(shí)固化的;
- 幀協(xié)議類型字段有三種值,分別對應(yīng)IP、ARP、RARP;
- 幀末尾是CRC校驗(yàn)碼。
4.2 認(rèn)識MTU
MTU相當(dāng)于發(fā)快遞時(shí)對包裹尺寸的限制。這個(gè)限制是不同的數(shù)據(jù)鏈路對應(yīng)的物理層,產(chǎn)生的限制。
- 以太網(wǎng)幀中的數(shù)據(jù)長度規(guī)定最小46字節(jié),最大1500字節(jié),ARP數(shù)據(jù)包的長度不夠46字節(jié),要在后面補(bǔ)填充位;
- 最大值1500稱為以太網(wǎng)的最大傳輸單元(MTU),不同的網(wǎng)絡(luò)類型有不同的MTU;
- 如果一個(gè)數(shù)據(jù)包從以太網(wǎng)路由到撥號鏈路上,數(shù)據(jù)包長度大于撥號鏈路的MTU了,則需要對數(shù)據(jù)包進(jìn)行分(fragmentation);
- 不同的數(shù)據(jù)鏈路層標(biāo)準(zhǔn)的MTU是不同的;
MTU對IP協(xié)議的影響:
由于數(shù)據(jù)鏈路層MTU的限制,對于較大的IP數(shù)據(jù)包要進(jìn)行分包。
- 將較大的IP包分成多個(gè)小包,并給每個(gè)小包打上標(biāo)簽;
- 每個(gè)小包IP協(xié)議頭的 16位標(biāo)識(id) 都是相同的;
- 每個(gè)小包的IP協(xié)議頭的3位標(biāo)志字段中,第2位置為0,表示允許分片,第3位來表示結(jié)束標(biāo)記(當(dāng)前是否是最后一個(gè)小包,是的話置為1,否則置為0);
- 到達(dá)對端時(shí)再將這些小包,會(huì)按順序重組,拼裝到一起返回給傳輸層;
- 一旦這些小包中任意一個(gè)小包丟失,接收端的重組就會(huì)失敗。但是IP層不會(huì)負(fù)責(zé)重新傳輸數(shù)據(jù);
4.2.1 MTU對UDP協(xié)議的影響
讓我們回顧一下UDP協(xié)議:
- 一旦UDP攜帶的數(shù)據(jù)超過1472(1500 - 20(IP首部) - 8(UDP首部)),那么就會(huì)在網(wǎng)絡(luò)層分成多個(gè)IP數(shù)據(jù)報(bào)。
- 這多個(gè)IP數(shù)據(jù)報(bào)有任意一個(gè)丟失,都會(huì)引起接收端網(wǎng)絡(luò)層重組失敗。那么這就意味著,如果UDP數(shù)據(jù)報(bào)在網(wǎng)絡(luò)層被分片,整個(gè)數(shù)據(jù)被丟失的概率就大大增加了。
4.2.2 MTU對于TCP協(xié)議的影響
讓我們再回顧一下TCP協(xié)議:
-
TCP的一個(gè)數(shù)據(jù)報(bào)也不能無限大,還是受制于MTU。TCP的單個(gè)數(shù)據(jù)報(bào)的最大消息長度,稱為MSS(Max Segment Size);
-
TCP在建立連接的過程中,通信雙方會(huì)進(jìn)行MSS協(xié)商。
-
最理想的情況下,MSS的值正好是在IP不會(huì)被分片處理的最大長度(這個(gè)長度仍然是受制于數(shù)據(jù)鏈路層的MTU)。
-
雙方在發(fā)送SYN的時(shí)候會(huì)在TCP頭部寫入自己能支持的MSS值。
-
然后雙方得知對方的MSS值之后,選擇較小的作為最終MSS。
-
MSS的值就是在TCP首部的40字節(jié)變長選項(xiàng)中(kind=2);
MSS和MTU的關(guān)系:
4.3 ARP協(xié)議
雖然我們在這里介紹ARP協(xié)議,但是需要強(qiáng)調(diào),ARP不是一個(gè)單純的數(shù)據(jù)鏈路層的協(xié)議,而是一個(gè)介于數(shù)據(jù)鏈路層和網(wǎng)絡(luò)層之間的協(xié)議;
ARP協(xié)議建立了主機(jī) IP地址 和 MAC地址 的映射關(guān)系。
- 在網(wǎng)絡(luò)通訊時(shí),源主機(jī)的應(yīng)用程序知道目的主機(jī)的IP地址和端口號,卻不知道目的主機(jī)的硬件地址;
- 數(shù)據(jù)包首先是被網(wǎng)卡接收到再去處理上層協(xié)議的,如果接收到的數(shù)據(jù)包的硬件地址與本機(jī)不符,則直接丟棄;
- 因此在通訊前必須獲得目的主機(jī)的硬件地址;
ARP協(xié)議的工作流程:
-
源主機(jī)發(fā)出ARP請求,詢問“IP地址是192.168.0.1的主機(jī)的硬件地址是多少”,并將這個(gè)請求廣播到本地網(wǎng)段(以太網(wǎng)幀首部的硬件地址填FF:FF:FF:FF:FF:FF表示廣播);
-
目的主機(jī)接收到廣播的ARP請求,發(fā)現(xiàn)其中的IP地址與本機(jī)相符,則發(fā)送一個(gè)ARP應(yīng)答數(shù)據(jù)包給源主機(jī),將自己的硬件地址填寫在應(yīng)答包中;
-
每臺(tái)主機(jī)都維護(hù)一個(gè)ARP緩存表,可以用arp
-a命令查看。緩存表中的表項(xiàng)有過期時(shí)間(一般為20分鐘),如果20分鐘內(nèi)沒有再次使用某個(gè)表項(xiàng),則該表項(xiàng)失效,下次還要發(fā)ARP請求來獲得目的主機(jī)的硬件地址