一、TCP包頭的格式
TCP包頭
- 首先是16位的源端口號(hào)和16位的目的端口號(hào)派草。用來(lái)告訴操作系統(tǒng),這是哪個(gè)進(jìn)程的包铛楣。
- 然后是32位的序號(hào)近迁,解決包的亂序問(wèn)題。
- 然后是32位的確認(rèn)序號(hào)簸州,防止在網(wǎng)絡(luò)傳輸過(guò)程中包的丟失鉴竭。
- 然后接下來(lái)有一些狀態(tài)位,例如SYN勿侯,表示發(fā)起一個(gè)鏈接拓瞪;ACK缴罗,表示回復(fù)助琐;RST,表示重新連接面氓;FIN兵钮,表示結(jié)束等蛆橡。因?yàn)門(mén)CP是面向連接的,所以這些狀態(tài)位會(huì)引起雙端狀態(tài)的變更掘譬。
- 接下來(lái)還有占16位的窗口大小泰演,用來(lái)做流量控制和擁塞控制,表明當(dāng)前自己的處理能力和控制發(fā)送速度葱轩。
二睦焕、TCP的三次握手
- TCP的三次握手發(fā)生在TCP連接建立時(shí),
- 第一次握手時(shí)靴拱,客戶(hù)端將SYN狀態(tài)位設(shè)置為1垃喊,隨機(jī)產(chǎn)生一個(gè)初始序號(hào)x發(fā)送給服務(wù)端,進(jìn)入SYN_SENT狀態(tài)袜炕。
- 第二次握手時(shí)本谜,服務(wù)端在收到客戶(hù)端發(fā)來(lái)的SYN=1的包后,就返回一個(gè)SYN偎窘、ACK狀態(tài)位都為1的包乌助,序號(hào)隨機(jī)初始化為y,確認(rèn)序號(hào)為收到的包的序號(hào)加1陌知,也就是x+1他托,然后服務(wù)端進(jìn)入SYN_RCVD狀態(tài)。
- 第三次握手時(shí)仆葡,客戶(hù)端收到服務(wù)端發(fā)來(lái)的確認(rèn)包上祈,檢查確認(rèn)序號(hào)、ACK狀態(tài)位等信息是否準(zhǔn)確浙芙,如果正確登刺,就返回一個(gè)ACK狀態(tài)位為1,序號(hào)為x+1的確認(rèn)包嗡呼,發(fā)給服務(wù)器纸俭,然后進(jìn)入ESTABLISHED狀態(tài);服務(wù)器收到這個(gè)包后南窗,檢查無(wú)誤揍很,則也進(jìn)入ESTABLISHED狀態(tài)。
-
這樣就完成了三次握手万伤。
TCP三次握手
三窒悔、為什么是三次握手,而不是兩次或四次
如果是兩次握手:
- 假如敌买。當(dāng)A發(fā)送給B一個(gè)連接請(qǐng)求包简珠,如果這個(gè)包迷路了,或者堵塞了,沒(méi)有到達(dá)B聋庵,或者晚到B膘融,則A可能會(huì)再次發(fā)送給B多個(gè)連接請(qǐng)求包。
- 當(dāng)B收到了連接請(qǐng)求包祭玉,表示同意連接氧映,會(huì)發(fā)送應(yīng)答包給A。完成了通信脱货,結(jié)束了連接后岛都,這時(shí),A原來(lái)發(fā)送的連接請(qǐng)求包可能又到達(dá)了B振峻。
- B以為是A新發(fā)來(lái)的請(qǐng)求疗绣,所以會(huì)建立連接,這時(shí)B給A的應(yīng)答包如果在網(wǎng)絡(luò)中丟失了铺韧,就會(huì)造成A不知道B有這個(gè)連接多矮,則這個(gè)連接會(huì)一直存在,浪費(fèi)系統(tǒng)的資源哈打。
為什么不是四次塔逃?
- 因?yàn)槿尉湍茏尫?wù)端知道他的應(yīng)答包客戶(hù)端收到了,如果使用4次料仗,就冗余湾盗。
四、為什么序號(hào)不能都從1開(kāi)始呢立轧?
- 因?yàn)榫W(wǎng)絡(luò)中可能還會(huì)存在上一次連接中沒(méi)有達(dá)到的包格粪,如果序號(hào)從1開(kāi)始,則上一次包的數(shù)據(jù)的序號(hào)可能會(huì)與本次連接的沖突氛改,造成錯(cuò)誤帐萎。
- 所以序號(hào)需要隨機(jī)產(chǎn)生,且在包的生存時(shí)間內(nèi)不能重復(fù)胜卤。
五疆导、TCP的四次揮手
- TCP四次揮手發(fā)生在TCP連接斷開(kāi)時(shí),
- 第一次揮手假設(shè)是由客戶(hù)端發(fā)起葛躏,則客戶(hù)端會(huì)發(fā)送一個(gè)FIN=1的包澈段,然后進(jìn)入FIN_WAIT_1的狀態(tài)。
- 第二次揮手時(shí)舰攒,是服務(wù)端收到一個(gè)FIN=1的包败富,則發(fā)送一個(gè)ACK=1的確認(rèn)包,進(jìn)入CLOSED_WAIT狀態(tài)摩窃;客戶(hù)端收到這個(gè)包后兽叮,就進(jìn)入FIN_WAIT_2狀態(tài)。
- 第三次揮手時(shí),是服務(wù)端發(fā)送/處理完了最后的數(shù)據(jù)充择,向客戶(hù)端發(fā)送一個(gè)FIN德玫、ACK狀態(tài)位為1的包匪蟀,進(jìn)入LAST_ACK狀態(tài)椎麦。
- 第四次揮手時(shí),是客戶(hù)端收到了服務(wù)端的FIN材彪、ACK為1的包時(shí)观挎,就發(fā)送一個(gè)ACK=1的包,進(jìn)入TIME_WAIT狀態(tài)段化,在等待兩個(gè)最大報(bào)文生存時(shí)間后嘁捷,就進(jìn)入CLOSED狀態(tài);服務(wù)端收到這個(gè)ACK包時(shí)显熏,也就進(jìn)入CLOSED狀態(tài)雄嚣。
六、在客戶(hù)端是FIN_WAIT_2狀態(tài)時(shí)喘蟆,如果服務(wù)器宕機(jī)缓升,客戶(hù)端此連接會(huì)怎樣
- 在linux里面,可設(shè)置一個(gè)超時(shí)參數(shù)蕴轨,使其超時(shí)后自動(dòng)關(guān)閉連接港谊。
七、等待TIME_WAIT時(shí)間的意義
- 在第四次揮手時(shí)橙弱,發(fā)送的確認(rèn)包可能會(huì)在路上丟失歧寺,如果沒(méi)有這個(gè)等待時(shí)間,客戶(hù)端直接關(guān)閉的話(huà)棘脐,就會(huì)造成服務(wù)端的連接不能正常關(guān)閉斜筐。
- 在有了這個(gè)等待時(shí)間后,如果第四次揮手的確認(rèn)包丟失蛀缝,則客戶(hù)端可以等到服務(wù)端重發(fā)的第三次揮手的包奴艾,從而正確的關(guān)閉連接。
八内斯、等待時(shí)間為什么設(shè)置為2MSL
- MSL表示最大的報(bào)文生存時(shí)間蕴潦,超過(guò)這個(gè)時(shí)間,仍在網(wǎng)絡(luò)上的報(bào)文俘闯,會(huì)被拋棄潭苞。
- 所以2MSL可以大概的表示此連接中所有的報(bào)文在網(wǎng)絡(luò)中都不存在了。
九真朗、過(guò)了2MSL此疹,服務(wù)端還是沒(méi)有收到它FIN的ACK,怎么辦?
- 這個(gè)時(shí)候蝗碎,客戶(hù)端在2MSL后湖笨,已經(jīng)關(guān)閉了連接,收到服務(wù)端發(fā)來(lái)的FIN蹦骑,會(huì)發(fā)送一個(gè)RST慈省,服務(wù)端就會(huì)知道,客戶(hù)端已經(jīng)關(guān)閉了連接眠菇。
十边败、TCP為什么是可靠的?
- TCP每個(gè)包都有一個(gè)序號(hào)捎废,保證包的有序性笑窜。
- TCP對(duì)每個(gè)收到的包都作出應(yīng)答,保證包不丟失登疗。用的是累計(jì)應(yīng)答的方式排截,表示這個(gè)序號(hào)前的所有包都收到了。
- TCP有重傳機(jī)制辐益,對(duì)每一個(gè)發(fā)出去的包都設(shè)置了一個(gè)定時(shí)器断傲,如果超過(guò)了一定的時(shí)間,就重新發(fā)送這個(gè)包荷腊。這個(gè)時(shí)間必須大于往返時(shí)間RTT艳悔,否則會(huì)引起不必要的重傳,但是也不能太大女仰,不然會(huì)導(dǎo)致訪(fǎng)問(wèn)變慢猜年。所以采用的是對(duì)當(dāng)前網(wǎng)絡(luò)進(jìn)行數(shù)據(jù)包往返時(shí)間采樣的方法,計(jì)算出一個(gè)平均值疾忍。當(dāng)一個(gè)數(shù)據(jù)包重傳兩次時(shí)乔外,表示當(dāng)前的網(wǎng)絡(luò)環(huán)境較差,TCP的策略是一罩,重傳時(shí)間間隔加倍杨幼,減少頻繁的發(fā)送。
- TCP還擁有一個(gè)快速重傳機(jī)制聂渊,當(dāng)接收方收到的包的序號(hào)大于所期望的包的序號(hào)時(shí)差购,會(huì)繼續(xù)發(fā)送冗余ACK,比如說(shuō)收到了6汉嗽、8序號(hào)的兩個(gè)包欲逃,7沒(méi)來(lái),就發(fā)送6的ACK饼暑,接下來(lái)稳析,后續(xù)收到的包洗做,都發(fā)送6的ACK。當(dāng)發(fā)送方收到3個(gè)重復(fù)的ACK時(shí)彰居,就不用等待超時(shí)诚纸,會(huì)馬上重發(fā)。
- TCP還會(huì)對(duì)數(shù)據(jù)包進(jìn)行校驗(yàn)陈惰。
十一畦徘、TCP如何流量控制
- TCP包中,會(huì)攜帶16位的窗口大小數(shù)據(jù)奴潘,表示自己接下來(lái)還能接收多少個(gè)包旧烧。
- 假設(shè)接收方的應(yīng)用一直不讀取緩存里的數(shù)據(jù)影钉,則窗口的大小會(huì)越來(lái)越小画髓,直至為0。
- 如果這樣平委,發(fā)送方就會(huì)定時(shí)發(fā)送窗口探測(cè)包奈虾,查看是否有機(jī)會(huì)調(diào)整窗口的大小。
十二廉赔、TCP擁塞問(wèn)題
- 擁塞問(wèn)題也是通過(guò)窗口大小來(lái)控制的肉微。
- 流量控制中的窗口,是怕發(fā)送方把接收方的緩存塞滿(mǎn)蜡塌,而擁塞窗口則是怕把網(wǎng)絡(luò)塞滿(mǎn)碉纳,因?yàn)榫W(wǎng)絡(luò)中的設(shè)備其緩存大小都是有限的,如果網(wǎng)絡(luò)中的包過(guò)多馏艾,占滿(mǎn)了設(shè)備的緩存劳曹,則后續(xù)到達(dá)的包,就會(huì)被丟棄琅摩。如果網(wǎng)絡(luò)設(shè)備的處理能力不行铁孵,則在設(shè)備緩存中保存的包,會(huì)超時(shí)重傳房资。
- 所以TCP擁塞控制就是在不堵塞蜕劝、不丟包的情況下,盡量發(fā)揮帶寬轰异,避免包丟失和超時(shí)重傳岖沛。
- 在TCP的擁塞控制中,一開(kāi)始是不知道網(wǎng)絡(luò)的擁塞情況的搭独,所以要慢開(kāi)始婴削,一開(kāi)始的窗口大小設(shè)為1,所以只能發(fā)送一個(gè)包戳稽。當(dāng)收到這個(gè)發(fā)送包的ACK時(shí)馆蠕,窗口大小加1期升,在后續(xù)中,每收到一個(gè)確認(rèn)包互躬,窗口大小就加1播赁。呈指數(shù)增長(zhǎng)。
- 當(dāng)窗口大小到達(dá)設(shè)定的閾值時(shí)吼渡,就變?yōu)榫€(xiàn)性增長(zhǎng)容为,當(dāng)窗口的所有包都收到確認(rèn),窗口大小才加1寺酪。
- 這時(shí)坎背,如果出現(xiàn)了網(wǎng)絡(luò)擁塞,比如說(shuō)丟包了寄雀,需要超時(shí)重傳得滤,則將窗口大小的閾值變成現(xiàn)在窗口大小的一半,窗口大小設(shè)為1盒犹,重新開(kāi)始慢啟動(dòng)懂更。
- 如果是快速重傳,TCP會(huì)認(rèn)為這時(shí)急膀,網(wǎng)絡(luò)只是部分丟包沮协,情況不嚴(yán)重,所以窗口大小僅變?yōu)樵瓉?lái)的一半卓嫂,窗口大小的閾值也為原來(lái)的一半慷暂。繼續(xù)線(xiàn)性增長(zhǎng)。
十三晨雳、TCP和UDP的區(qū)別
- TCP是有序行瑞、有確認(rèn)機(jī)制、有狀態(tài)的可靠連接協(xié)議悍募;UDP是無(wú)序蘑辑、不需要確認(rèn)、沒(méi)有狀態(tài)的不可靠的協(xié)議坠宴。
- TCP是面向字節(jié)流的洋魂,而UDP是面向報(bào)文的。
面向流指的是沒(méi)有保護(hù)消息邊界喜鼓,如果發(fā)送端連續(xù)發(fā)送消息副砍,則接收端有可能在一次接收動(dòng)作中,會(huì)接收兩個(gè)或更多數(shù)據(jù)包庄岖。
例如豁翎,我們連續(xù)發(fā)送三個(gè)數(shù)據(jù)包,大小分別是2k隅忿,4k心剥,8k這三個(gè)數(shù)據(jù)包邦尊,都已經(jīng)到達(dá)了接收端的網(wǎng)絡(luò)堆棧(就是網(wǎng)絡(luò)協(xié)議棧)中,如果使用UDP協(xié)議优烧,不管我們使用多大的接收緩沖區(qū)去接收數(shù)據(jù)蝉揍,我們必須有三次接收動(dòng)作,才能夠把所有的數(shù)據(jù)包接收完畦娄。而使用TCP協(xié)議又沾,我們只要把接收的緩沖區(qū)大小設(shè)置在14k以上,我們就能夠一次把所有的數(shù)據(jù)包接收下來(lái)熙卡,只需要有一次接收動(dòng)作杖刷。
面向流的傳輸,可以減少發(fā)送包的數(shù)量驳癌,從而減少TCP機(jī)制造成的額外開(kāi)銷(xiāo)滑燃。 - TCP有擁塞控制,而UDP沒(méi)有喂柒。
- TCP的首部(20 字節(jié))開(kāi)銷(xiāo)比UDP的(8字節(jié))大不瓶。
十四禾嫉、UDP包頭的格式
- 主要是有16位的源端口號(hào)和16位的目的端口號(hào)灾杰。
十五、UDP的特點(diǎn)
- 包頭的格式簡(jiǎn)單熙参,只有源端口號(hào)和目的端口號(hào)
- UDP是無(wú)連接的艳吠,其端口號(hào)可以同時(shí)給多個(gè)人傳輸數(shù)據(jù),也可以接收任何人的數(shù)據(jù)孽椰,意思是可以多對(duì)多昭娩。
- UDP沒(méi)有擁塞控制,不管丟不丟包黍匾,都會(huì)發(fā)送栏渺。
十六、UDP的使用場(chǎng)景
- 在網(wǎng)絡(luò)環(huán)境比較好的內(nèi)網(wǎng)或?qū)τ趤G包不敏感的應(yīng)用锐涯,可以使用UDP磕诊,比如說(shuō)是DHCP,就是基于UDP的纹腌。
- 對(duì)于不需要一對(duì)一溝通霎终、建立連接,可以廣播的應(yīng)用升薯。
- 需要處理速度快莱褒、時(shí)延小,容許少量丟包的應(yīng)用涎劈。