四川城鄉(xiāng)住房建設(shè)廳官方網(wǎng)站seo搜索優(yōu)化公司排名
網(wǎng)絡(luò)協(xié)議系列文章
網(wǎng)絡(luò)協(xié)議(一):基本概念、計(jì)算機(jī)之間的連接方式
網(wǎng)絡(luò)協(xié)議(二):MAC地址、IP地址、子網(wǎng)掩碼、子網(wǎng)和超網(wǎng)
網(wǎng)絡(luò)協(xié)議(三):路由器原理及數(shù)據(jù)包傳輸過程
網(wǎng)絡(luò)協(xié)議(四):網(wǎng)絡(luò)分類、ISP、上網(wǎng)方式、公網(wǎng)私網(wǎng)、NAT
網(wǎng)絡(luò)協(xié)議(五):網(wǎng)絡(luò)互聯(lián)模型、物理層、數(shù)據(jù)鏈路層
網(wǎng)絡(luò)協(xié)議(六):網(wǎng)絡(luò)層
網(wǎng)絡(luò)協(xié)議(七):傳輸層-UDP
網(wǎng)絡(luò)協(xié)議(八):傳輸層-TCP(三次握手、四次揮手原理)
目錄
- 一、TCP協(xié)議
- 二、可靠傳輸
- 1、停止等待ARQ協(xié)議
- 2、連續(xù)ARQ協(xié)議+滑動窗口協(xié)議
- 3、SACK(選擇性確定)
- 三、擁塞控制
- 1、慢開始
- 2、擁塞避免
- 3、快重傳
- 4、快恢復(fù)
- 四、序號、確認(rèn)號(詳細(xì)步驟)
- 五、建立連接(三次握手)
- 六、釋放連接(四次揮手)
網(wǎng)絡(luò)分層對應(yīng)的通信協(xié)議和數(shù)據(jù)名稱
一、TCP協(xié)議
TCP的幾個(gè)要點(diǎn)
- 可靠傳輸
- 流量控制
- 擁塞控制
- 連接管理(建立連接、釋放連接)
數(shù)據(jù)偏移
- 占4位,取值范圍是 0b0101 ~ 0b1111(5~15)
- 乘以4:首部長度(Header Length)
- 首部長度是20~60字節(jié)
保留
- 占6位,目前全為0
- 有些資料中,TCP首部的 保留(Reserved)字段 占3位,標(biāo)志(Flags) 字段占9位(Wireshark中也是如此)
- 因?yàn)闃?biāo)志位目前只用到了6位,所以可以說標(biāo)識位空閑的3位和保留位3位合并為保留位6位
TCP的一個(gè)細(xì)節(jié)
- UDP的首部中有個(gè)16位的字段記錄了整個(gè)UDP報(bào)文段的長度(首部+數(shù)據(jù))
- 但是,TCP的首部中僅僅有個(gè)4位的字段記錄了TCP報(bào)文段的首部長度,并沒有字段記錄TCP報(bào)文段的數(shù)據(jù)長度
- UDP首部中占16位的長度字段是冗余的,純粹是為了保證首部是32bit對齊
- TCP\UDP的數(shù)據(jù)長度,完全可以由IP數(shù)據(jù)包的首部推測出來
- 網(wǎng)絡(luò)層首部記錄著網(wǎng)絡(luò)層的總長度
- 傳輸層的數(shù)據(jù)長度 = 網(wǎng)絡(luò)層的總長度 – 網(wǎng)絡(luò)層的首部長度 – 傳輸層的首部長度
檢驗(yàn)和(CheckSum)
- 跟UDP一樣,TCP檢驗(yàn)和的計(jì)算內(nèi)容:偽首部 + 首部 + 數(shù)據(jù)
- 偽首部:占用12字節(jié),僅在計(jì)算檢驗(yàn)和時(shí)起作用,并不會傳遞給網(wǎng)絡(luò)層
標(biāo)志位(Flags)
- URG(Urgent):當(dāng) URG = 1 時(shí),緊急指針字段才有效。表明當(dāng)前報(bào)文段中有緊急數(shù)據(jù),應(yīng)優(yōu)先盡快傳送
- ACK(Acknowledgment):當(dāng) ACK = 1 時(shí),確認(rèn)號字段才有效
- PSH(Push)
- RST(Reset):當(dāng) RST = 1 時(shí),表明連接中出現(xiàn)嚴(yán)重差錯(cuò),必須釋放連接,然后再重新建立連接
- SYN(Synchronization):當(dāng) SYN = 1、ACK = 0 時(shí),表明這是一個(gè)建立連接的請求,若對方同意建立連接,則回復(fù) SYN = 1、ACK = 1
- FIN(Finish):當(dāng) FIN = 1 時(shí),表明數(shù)據(jù)已經(jīng)發(fā)送完畢,要求釋放連接
序號(Sequence Number)
- 占4字節(jié)
- 首先,在傳輸過程的每一個(gè)字節(jié)都會有一個(gè)編號
- 在建立連接后,序號代表:這一次傳給對方的TCP數(shù)據(jù)部分的第一個(gè)字節(jié)的編號
確認(rèn)號(Acknowledgment Number)
- 占4字節(jié)
- 在建立連接后,確認(rèn)號代表:期望對方下一次傳過來的TCP數(shù)據(jù)部分的第一個(gè)字節(jié)的編號
窗口(Window)
- 占2字節(jié)
- 這個(gè)字段有流量控制功能,用以告知對方下一次允許發(fā)送的數(shù)據(jù)大小(字節(jié)為單位)
二、可靠傳輸
- 可靠傳輸是為了保證包的完整性,當(dāng)有丟包、受到三次重復(fù)確認(rèn)等情況,就會重新發(fā)包
1、停止等待ARQ協(xié)議
- ARQ(Automatic Repeat–reQuest),自動重傳請求
疑問:重傳次數(shù)?
- 若有個(gè)包重傳了N次還是失敗,會一直持續(xù)重傳到成功為止么?
- 這個(gè)取決于系統(tǒng)的設(shè)置,比如有些系統(tǒng),重傳5次還未成功就會發(fā)送 reset報(bào)文(RST) 斷開TCP連接
2、連續(xù)ARQ協(xié)議+滑動窗口協(xié)議
- 如果接收窗口最多能接收4個(gè)包,但發(fā)送方只發(fā)了2個(gè)包,接收方如何確定后面還有沒有2個(gè)包?
- 等待一定時(shí)間后沒有第3個(gè)包,就會返回確認(rèn)收到2個(gè)包給發(fā)送方
- A為發(fā)送端,B為接收端
- 滑動窗口相當(dāng)于緩存的窗口
- 建立TCP連接時(shí)B告訴A接收窗口大小
3、SACK(選擇性確定)
- 在TCP通信過程中,如果發(fā)送序列中間某個(gè)數(shù)據(jù)包丟失(比如1、2、3、4、5中3丟失了)
- TCP會通過重傳最后確認(rèn)的分組后續(xù)的分組(最后確認(rèn)的是2,會重傳3、4、5)
- 這樣原先已經(jīng)正確傳輸?shù)姆纸M也可能重復(fù)發(fā)送(比如4、5),降低了TCP性能
- 為改善上述情況,發(fā)展出了 SACK(Selective acknowledgment,選擇性確認(rèn))技術(shù)
- 告訴發(fā)送方哪些數(shù)據(jù)丟失,哪些數(shù)據(jù)已經(jīng)提前收到
- 使TCP只重新發(fā)送丟失的包(比如3),不用發(fā)送后續(xù)所有的分組(比如4、5)
SACK信息會放在TCP首部的選項(xiàng)部分
- Kind:占1字節(jié)。值為5代表這是SACK選項(xiàng)
- Length:占1字節(jié)。表明SACK選項(xiàng)一共占用多少字節(jié)
- Left Edge:占4字節(jié),左邊界
- Right Edge:占4字節(jié),右邊界
- 確認(rèn)號201,期望對方發(fā)送201以后得數(shù)據(jù)段,但是把灰色部分?jǐn)?shù)據(jù)段排除掉
- 一對邊界信息需要占用8字節(jié),由于TCP首部的選項(xiàng)部分最多40字節(jié),所以
- SACK選項(xiàng)最多攜帶4組邊界信息
- SACK選項(xiàng)的最大占用字節(jié)數(shù) = 4 * 8 + 2 = 34
思考:為什么選擇在傳輸層就將數(shù)據(jù)“大卸八塊”分成多個(gè)段,而不是等到網(wǎng)絡(luò)層再分片傳遞給數(shù)據(jù)鏈路層?
- 因?yàn)榭梢蕴岣咧貍鞯男阅?/strong>
- 需要明確的是:可靠傳輸是在傳輸層進(jìn)行控制的
- 如果在傳輸層不分段,一旦出現(xiàn)數(shù)據(jù)丟失,整個(gè)傳輸層的數(shù)據(jù)都得重傳
- 如果在傳輸層分了段,一旦出現(xiàn)數(shù)據(jù)丟失,只需要重傳丟失的那些段即可
三、擁塞控制
- 擁塞控制
- 防止過多的數(shù)據(jù)注入到網(wǎng)絡(luò)中
- 避免網(wǎng)絡(luò)中的路由器或鏈路過載
- 擁塞控制是一個(gè)全局性的過程
- 涉及到所有的主機(jī)、路由器
- 以及與降低網(wǎng)絡(luò)傳輸性能有關(guān)的所有因素
- 是大家共同努力的結(jié)果
- 相比而言,流量控制是點(diǎn)對點(diǎn)通信的控制
擁塞控制方法
- 慢開始(slow start,慢啟動)
- 擁塞避免(congestion avoidance)
- 快速重傳(fast retransmit)
- 快速恢復(fù)(fast recovery)
幾個(gè)概念
- MSS(Maximum Segment Size):每個(gè)段最大的數(shù)據(jù)部分大小(在建立連接時(shí)確定)
- 一般是 MTU(1500) - 20 - 20 = 1460
- cwnd(congestion window):擁塞窗口
- rwnd(receive window):接收窗口
- swnd(send window):發(fā)送窗口
- swnd = min(cwnd, rwnd) 發(fā)送窗口是擁塞窗口和接收窗口取最小的那個(gè)
1、慢開始
- cwnd的初始值比較小,然后隨著數(shù)據(jù)包被接收方確認(rèn)(收到一個(gè)ACK)
- cwnd就成倍增長(指數(shù)級)
2、擁塞避免
- ssthresh (slow start threshold):慢開始閾值,cwnd達(dá)到閾值后,開始擁塞避免(加法增大)
- 擁塞避免(加法增大):擁塞窗口cwind 緩慢增大,以防止網(wǎng)絡(luò)過早出現(xiàn)擁塞
- 乘法減小:只要出現(xiàn)網(wǎng)絡(luò)擁塞,把ssthresh減為擁塞峰值的一半,同時(shí)執(zhí)行慢開始算法(cwnd又恢復(fù)到初始值)
- 當(dāng)網(wǎng)絡(luò)出現(xiàn)頻繁擁塞時(shí),ssthresh值就下降的很快
3、快重傳
- 接收方
- 每收到一個(gè)失序的分組后就立即發(fā)出重復(fù)確認(rèn)
- 使發(fā)送方及時(shí)知道有分組沒有到達(dá)
- 而不要等待自己發(fā)送數(shù)據(jù)時(shí)才進(jìn)行確認(rèn)
- 發(fā)送方
- 只要連續(xù)收到三個(gè)重復(fù)確認(rèn)(總共4個(gè)相同的確認(rèn)),就應(yīng)當(dāng)立即重傳對方尚未收到的報(bào)文段
- 而不必繼續(xù)等待重傳計(jì)時(shí)器到期后再重傳
4、快恢復(fù)
- 當(dāng)發(fā)送方連續(xù)收到三個(gè)重復(fù)確認(rèn),說明網(wǎng)絡(luò)出現(xiàn)擁塞
- 就執(zhí)行“乘法減小”算法,把ssthresh減為擁塞峰值的一半
- 與慢開始不同之處是現(xiàn)在不執(zhí)行慢開始算法,即cwnd現(xiàn)在不恢復(fù)到初始值
- 而是把cwnd值設(shè)置為新的ssthresh值(減小后的值)
- 然后開始執(zhí)行擁塞避免算法(“加法增大”),使擁塞窗口緩慢地線性增大
四、序號、確認(rèn)號(詳細(xì)步驟)
- 左邊紫色A客戶端,右邊藍(lán)色B服務(wù)端
- ①②③:建立連接
- ④:發(fā)送http請求
- ⑤⑥⑦⑧:響應(yīng)http請求
- ⑨:應(yīng)答服務(wù)器
注意: s1是客戶端的初始值(可以理解隨機(jī)數(shù))s2是服務(wù)端的初始值,這兩邊給對方發(fā)送數(shù)據(jù)的序號都是從初始值開始計(jì)算,所以也可以理解原生是s1和s2,相對則都是0
- SYN ACK表示標(biāo)記位是否為1,seq是序號,ack為確認(rèn)號
- ①:客戶端請求與服務(wù)器建立連接,syn=1表示客戶端第一次發(fā)請求,也代表建立連接請求
- 數(shù)據(jù)部分占0字節(jié),這里序號s1其實(shí)給服務(wù)端用的
- 第一次發(fā),所以也沒有應(yīng)答ack=0,而且只有ACK = 1 時(shí),確認(rèn)號字段才有效
- ②:服務(wù)器應(yīng)答客戶端建立連接,syn=1表示服務(wù)器第一次發(fā)請求,也代表建立連接請求==
- 數(shù)據(jù)部分占0字節(jié),這里序號s2也是給客戶端用的
- 這里ack確認(rèn)s1,期望收到s1+1的字節(jié)數(shù)據(jù)
- ③:應(yīng)答②,因?yàn)棰谄谕盏絪1+1數(shù)據(jù),那么③序號為s1+1,期望收到②s2+1數(shù)據(jù),但是這里數(shù)據(jù)部分依然還是0字節(jié)
- ④:建立連接成功后,第一次請求數(shù)據(jù),客戶端從s1+1開始發(fā)數(shù)據(jù),一共k字節(jié),期望服務(wù)器從s2+1開始發(fā)
- ⑤:從④中期待的s2+1數(shù)據(jù)開始發(fā)送,其實(shí)也就是服務(wù)器的第一個(gè)字節(jié)數(shù)
- 期待客戶端從s1+k+1發(fā),因?yàn)棰苤姓埱蟀l(fā)了k個(gè)字節(jié)
- ⑥⑦⑧:序號就是前一個(gè)數(shù)據(jù)的序號+發(fā)送的字節(jié)長度,ack都一樣,都是上次http請求的s1+k+1
- ⑨:應(yīng)答服務(wù)器發(fā)送的⑤⑥⑦⑧,序號則是⑤⑥⑦⑧期望的,但是這里數(shù)據(jù)占用0字節(jié),其實(shí)只是應(yīng)答,沒有發(fā)數(shù)據(jù)了
相對:序號、確認(rèn)號
原生:序號、確認(rèn)號
五、建立連接(三次握手)
- CLOSED:client處于關(guān)閉狀態(tài)
- LISTEN:server處于監(jiān)聽狀態(tài),等待client連接
- SYN-SENT:表示client已發(fā)送SYN報(bào)文,等待server的第2次握手
- SYN-RCVD:表示server接受到了SYN報(bào)文,當(dāng)收到client的ACK報(bào)文后,它會進(jìn)入到 ESTABLISHED 狀態(tài)
- ESTABLISHED:表示連接已經(jīng)建立
前2次握手的特點(diǎn)
- SYN 都設(shè)置為1
- 數(shù)據(jù)部分的長度都為0
- TCP頭部的長度一般是32字節(jié)
- 固定頭部:20字節(jié)
- 選項(xiàng)部分:12字節(jié)
- 雙方會交換確認(rèn)一些信息
- 比如MSS、是否支持SACK、Window scale(窗口縮放系數(shù)) 等
- 這些數(shù)據(jù)都放在了TCP頭部的選項(xiàng)部分中(12字節(jié))
為什么建立連接的時(shí)候,要進(jìn)行3次握手?2次不行么?
- 主要目的:防止server端一直等待,浪費(fèi)資源
- 如果建立連接只需要2次握手,可能會出現(xiàn)的情況:
- 假設(shè)client發(fā)出的第一個(gè)連接請求報(bào)文段,因?yàn)榫W(wǎng)絡(luò)延遲,在連接釋放以后的某個(gè)時(shí)間才到達(dá)server
- 本來這是一個(gè)早已失效的連接請求,但server收到此失效的請求后,誤認(rèn)為是client再次發(fā)出的一個(gè)新的連接請求
- 于是server就向client發(fā)出確認(rèn)報(bào)文段,同意建立連接
- 如果不采用“3次握手”,那么只要server發(fā)出確認(rèn),新的連接就建立了
- 由于現(xiàn)在client并沒有真正想連接服務(wù)器的意愿,因此不會理睬server的確認(rèn),也不會向server發(fā)送數(shù)據(jù)
- 但server卻以為新的連接已經(jīng)建立,并一直等待client發(fā)來數(shù)據(jù),這樣,server的很多資源就白白浪費(fèi)掉了
- 采用 “三次握手” 的辦法可以防止上述現(xiàn)象發(fā)生
如果第3次握手失敗了,會怎么處理?
- 此時(shí)server的狀態(tài)為 SYN-RCVD,若等不到client的 ACK,server會重新發(fā)送 SYN+ACK 包
- 如果server多次重發(fā) SYN+ACK 都等不到client的 ACK,就會發(fā)送 RST包,強(qiáng)制關(guān)閉連接
六、釋放連接(四次揮手)
- FIN-WAIT-1:表示想主動關(guān)閉連接
- 向?qū)Ψ桨l(fā)送了FIN報(bào)文,此時(shí)進(jìn)入到FIN-WAIT-1狀態(tài)
- CLOSE-WAIT:表示在等待關(guān)閉
- 當(dāng)對方發(fā)送FIN給自己,自己會回應(yīng)一個(gè)ACK報(bào)文給對方,此時(shí)則進(jìn)入到CLOSE-WAIT狀態(tài)
- 在此狀態(tài)下,需要考慮自己是否還有數(shù)據(jù)要發(fā)送給對方,如果沒有,發(fā)送FIN報(bào)文給對方
- FIN-WAIT-2:只要對方發(fā)送ACK確認(rèn)后,主動方就會處于FIN-WAIT-2狀態(tài),然后等待對方發(fā)送FIN報(bào)文
- CLOSING:一種比較罕見的例外狀態(tài)
- 表示你發(fā)送FIN報(bào)文后,并沒有收到對方的ACK報(bào)文,反而卻也收到了對方的FIN報(bào)文
- 如果雙方幾乎在同時(shí)準(zhǔn)備關(guān)閉連接的話,那么就出現(xiàn)了雙方同時(shí)發(fā)送FIN報(bào)文的情況,也即會出現(xiàn)CLOSING狀態(tài)
- 表示雙方都正在關(guān)閉連接
- LAST-ACK:被動關(guān)閉一方在發(fā)送FIN報(bào)文后,最后等待對方的ACK報(bào)文
- 當(dāng)收到ACK報(bào)文后,即可進(jìn)入CLOSED狀態(tài)了
- TIME-WAIT:表示收到了對方的FIN報(bào)文,并發(fā)送出了ACK報(bào)文,就等 2MSL 后即可進(jìn)入CLOSED狀態(tài)了
- 如果FIN-WAIT-1狀態(tài)下,收到了對方同時(shí)帶FIN標(biāo)志和ACK標(biāo)志的報(bào)文時(shí)
- 可以直接進(jìn)入到TIME-WAIT狀態(tài),而無須經(jīng)過FIN-WAIT-2狀態(tài)
- CLOSED:關(guān)閉狀態(tài)
- 由于有些狀態(tài)的時(shí)間比較短暫,所以很難用 netstat 命令看到,比如SYN-RCVD、FIN-WAIT-1等
釋放連接的一些細(xì)節(jié)
- TCP/IP協(xié)議棧在設(shè)計(jì)上,允許任何一方先發(fā)起斷開請求
- client發(fā)送ACK后,需要有個(gè)TIME-WAIT階段,等待一段時(shí)間后,再真正關(guān)閉連接
- 一般是等待2倍的 MSL(Maximum Segment Lifetime,最大分段生存期)
- MSL是TCP報(bào)文在Internet上的最長生存時(shí)間
- 每個(gè)具體的TCP實(shí)現(xiàn)都必須選擇一個(gè)確定的MSL值,RFC 1122 建議是2分鐘
- 可以防止發(fā)送ACK對方接收不到,會重新發(fā)送FIN,此時(shí)還需要應(yīng)答
- 如果client發(fā)送ACK后馬上釋放了,然后又因?yàn)榫W(wǎng)絡(luò)原因,server沒有收到client的ACK,server就會重發(fā)FIN,這時(shí)可能出現(xiàn)的情況是
- ① client沒有任何響應(yīng),服務(wù)器那邊會干等,甚至多次重發(fā)FIN,浪費(fèi)資源
- ② client有個(gè)新的應(yīng)用程序剛好分配了同一個(gè)端口號,新的應(yīng)用程序收到FIN后馬上開始執(zhí)行斷開連接的操作,本來它可能是想跟server建立連接的
為什么釋放連接的時(shí)候,要進(jìn)行4次揮手?
- TCP是全雙工模式
- 第1次揮手:當(dāng)主機(jī)1發(fā)出FIN報(bào)文段時(shí)
- 表示主機(jī)1告訴主機(jī)2,主機(jī)1已經(jīng)沒有數(shù)據(jù)要發(fā)送了,但是,此時(shí)主機(jī)1還是可以接受來自主機(jī)2的數(shù)據(jù)
- 第2次揮手:當(dāng)主機(jī)2返回ACK報(bào)文段時(shí)
- 表示主機(jī)2已經(jīng)知道主機(jī)1沒有數(shù)據(jù)發(fā)送了,但是主機(jī)2還是可以發(fā)送數(shù)據(jù)到主機(jī)1的
- 第3次揮手:當(dāng)主機(jī)2也發(fā)送了FIN報(bào)文段時(shí)
- 表示主機(jī)2告訴主機(jī)1,主機(jī)2已經(jīng)沒有數(shù)據(jù)要發(fā)送了
- 第4次揮手:當(dāng)主機(jī)1返回ACK報(bào)文段時(shí)
- 表示主機(jī)1已經(jīng)知道主機(jī)2沒有數(shù)據(jù)發(fā)送了。隨后正式斷開整個(gè)TCP連接
長連接和短鏈接
- 如果建立連接后不需要進(jìn)行數(shù)據(jù)交互就會關(guān)閉,那就是短連接
- 如果建立連接后需要進(jìn)行數(shù)據(jù)交互以后再關(guān)閉,那就是長連接