TCP協(xié)議簡介
TCP全稱Transmission Control Protocol静盅,數(shù)據(jù)傳輸控制協(xié)議。它是一種面向連接的寝殴、可靠的蒿叠、基于字節(jié)流的傳輸層通信協(xié)議。
互聯(lián)網(wǎng)上的數(shù)據(jù)通過應(yīng)用層到物理層 層層封裝(添加頭部信息)杯矩,由物理層傳輸?shù)綌?shù)據(jù)接收端栈虚,再層層解封裝,最后到到達(dá)數(shù)據(jù)接收端——應(yīng)用層史隆。
常用的熟知端口號
應(yīng)用程序 | FTP | TFTP | TELNET | SMTP | DNS | HTTP | SSH | MYSQL |
---|---|---|---|---|---|---|---|---|
熟知端口 | 21,20 | 69 | 23 | 25 | 53 | 80 | 22 | 3306 |
傳輸層協(xié)議 | TCP | UDP | TCP | TCP | UDP | TCP | TCP | TCP |
TCB是啥?
Socket包含兩部分曼验,一個(gè)是IP地址泌射,一個(gè)是端口號。同一個(gè)設(shè)備可以對應(yīng)一個(gè)IP地址鬓照,但不同的管道用不同的端口號區(qū)分熔酷,于是同一個(gè)設(shè)備發(fā)送給其他不同設(shè)備的信息就不會產(chǎn)生混亂。在同一時(shí)刻豺裆,設(shè)備可能會產(chǎn)生多種數(shù)據(jù)需要分發(fā)給不同的設(shè)備拒秘,為了確保數(shù)據(jù)能夠正確分發(fā),TCP協(xié)議用一種叫做TCB(Transmission Control Block臭猜,傳輸控制塊)的數(shù)據(jù)結(jié)構(gòu)把發(fā)給不同設(shè)備的數(shù)據(jù)封裝起來躺酒。
一個(gè)TCB數(shù)據(jù)塊包含了數(shù)據(jù)發(fā)送雙方對應(yīng)的socket信息以及擁有裝載數(shù)據(jù)的緩沖區(qū)。在兩個(gè)設(shè)備要建立連接發(fā)送數(shù)據(jù)之前蔑歌,雙方都必須要做一些準(zhǔn)備工作羹应,分配內(nèi)存建立起TCB數(shù)據(jù)塊就是連接建立前必須要做的準(zhǔn)備工作。我們還需要了解的一點(diǎn)是TCP連接的建立方式次屠,由于TCP協(xié)議建立在服務(wù)器–客戶端的模式之上园匹,因此對于兩種不同角色的設(shè)備,他們發(fā)起連接的方式不一樣劫灶。
客戶端發(fā)起連接的方式叫主動(dòng)打開(Active Open)裸违。也就是客戶端需要主動(dòng)向服務(wù)器發(fā)送消息,表達(dá)自己想建立數(shù)據(jù)連接的請求本昏。服務(wù)器發(fā)起連接的方式叫被動(dòng)打開(Passive Open)供汛,通常服務(wù)器在沒有客戶端主動(dòng)請求的時(shí)候不知道當(dāng)前有哪個(gè)設(shè)備想向它發(fā)起連接,因此它只能構(gòu)建一個(gè)端口并監(jiān)聽該端口,等待客戶端從該端口向它發(fā)起連接請求紊馏。在OPEN(打開)階段無論是客戶端還是服務(wù)器都需要準(zhǔn)備好TCB數(shù)據(jù)結(jié)構(gòu)料饥,但由于服務(wù)器不知道要連接它的客戶端的地址信息,因此在構(gòu)建TCB模塊時(shí)會默認(rèn)將客戶端對應(yīng)的Socket數(shù)據(jù)初始化為0朱监。
當(dāng)客戶端和服務(wù)器端雙方都把自己的Socket和TCB數(shù)據(jù)結(jié)構(gòu)準(zhǔn)備好后岸啡,雙方就可以進(jìn)入所謂的“三次握手”TCP連接建立過程。
- 更詳細(xì)的TCB數(shù)據(jù)結(jié)構(gòu)源碼可到此處查看:https://blog.csdn.net/sunshineywz/article/details/101867600
TCP的頭部信息
TCP頭部包含20個(gè)字節(jié)的固定首部和長度可變的最多40個(gè)字節(jié)的填充信息部分(可沒有)赫编。
最開頭的四個(gè)字節(jié)為
源端口
和目的端口
巡蘸,記錄端口信息,再加上位于網(wǎng)絡(luò)層的IP信息頭部中包含的源地址和目標(biāo)地址信息擂送,可唯一確定一個(gè)TCP連接悦荒。再往后的四個(gè)字節(jié)為
序號
(SYNchronize sequence numbers),值范圍為0到2的32次方減1嘹吨,標(biāo)示TCP數(shù)據(jù)包中第一個(gè)字節(jié)所存儲內(nèi)容的序號搬味,SYN超過最大值則回到0重新開始,做的是一個(gè)取余(mod)運(yùn)算蟀拷。確認(rèn)號
(Acknowledgment number)包含發(fā)送確認(rèn)的一端所期望收到的下一個(gè)序號碰纬,因此,確認(rèn)序號應(yīng)當(dāng)是上次已成功收到數(shù)據(jù)字節(jié)序號加1问芬。不過悦析,只有當(dāng)標(biāo)志位中的ACK標(biāo)志為1時(shí)該確認(rèn)序列號的字段才有效。主要用來解決不丟包的問題此衅;數(shù)據(jù)偏移
(offset)表示TCP頭部的32bit字的數(shù)目强戴,offset占四個(gè)bit位,故其最大值為15挡鞍,這也表示TCP頭部的最大字節(jié)數(shù)為4*15=60個(gè)字節(jié)骑歹。你看到的豎排文字(URG ACK PSH RST SYN FIN)這些都是
TCP flags
,用于操控TCP狀態(tài)機(jī)匕累,表示當(dāng)前的狀態(tài)陵刹。
URG
:此標(biāo)志表示TCP包的緊急指針域有效,用來保證TCP連接不被中斷欢嘿,并且督促中間層設(shè)備要盡快處理這些數(shù)據(jù)衰琐;
ACK
:此標(biāo)志表示應(yīng)答域有效,就是說前面所說的TCP確認(rèn)號將會包含在TCP數(shù)據(jù)包中炼蹦;ACK這個(gè)Flag有兩個(gè)取值:0和1羡宙,為1的時(shí)候表示應(yīng)答域有效,反之無效掐隐;
PSH
:這個(gè)標(biāo)志位表示Push操作狗热。所謂Push操作就是指在數(shù)據(jù)包到達(dá)接收端以后钞馁,立即傳送給應(yīng)用程序,而不是在緩沖區(qū)中排隊(duì)匿刮;
RST
:這個(gè)標(biāo)志表示連接復(fù)位請求僧凰。用來復(fù)位那些產(chǎn)生錯(cuò)誤的連接,也被用來拒絕錯(cuò)誤和非法的數(shù)據(jù)包熟丸;
SYN
:表示同步序號训措,用來建立連接。SYN標(biāo)志位和ACK標(biāo)志位搭配使用光羞,當(dāng)連接請求的時(shí)候绩鸣,SYN=1,ACK=0纱兑;連接被響應(yīng)的時(shí)候呀闻,SYN=1,ACK=1潜慎;這個(gè)標(biāo)志的數(shù)據(jù)包經(jīng)常被用來進(jìn)行端口掃描捡多。掃描者發(fā)送一個(gè)SYN=1,ACK=0的數(shù)據(jù)包铐炫,如果對方主機(jī)響應(yīng)了一個(gè)SYN+ACK數(shù)據(jù)包回來 局服,就表明這臺主機(jī)存在這個(gè)端口。
FIN
: 表示雙方的數(shù)據(jù)傳送完成驳遵,沒有數(shù)據(jù)可以傳送了,四次揮手山涡,發(fā)送FIN標(biāo)志位的TCP數(shù)據(jù)包后堤结,連接將被斷開。這個(gè)標(biāo)志的數(shù)據(jù)包也經(jīng)常被用于進(jìn)行端口掃描鸭丛。
再后面兩個(gè)字節(jié)為
窗口
大芯呵睢(window),也就是TCP中的滑動(dòng)窗口——應(yīng)用于TCP的流量控制鳞溉。比較復(fù)雜瘾带,以后再補(bǔ)充。校驗(yàn)和
提高了TCP數(shù)據(jù)傳輸?shù)目煽啃裕?code>緊急指針和URG標(biāo)志位配合使用熟菲;再往后就是可選區(qū)域
看政,非必須。
TCP三次握手與四次揮手
TCP為什么要進(jìn)行三次握手抄罕,而不是兩次握手允蚣?
這個(gè)問題在計(jì)算機(jī)網(wǎng)絡(luò)的教材中可以找到答案。在謝希仁著《計(jì)算機(jī)網(wǎng)絡(luò)》第四版中講“三次握手”的目的是呆贿,為了防止已失效的連接請求突然又傳送到了服務(wù)器端嚷兔,不進(jìn)行第三次握手可能會產(chǎn)生服務(wù)器資源不必要的消耗森渐。
試想,如果只經(jīng)過兩次握手即建立TCP連接會怎樣冒晰?
栗子:一個(gè)已失去時(shí)間有效期的TCP連接請求報(bào)文被發(fā)送到服務(wù)器端同衣,服務(wù)器此時(shí)并不知道這個(gè)報(bào)文在它的發(fā)送者——客戶端那里已失效,服務(wù)器對這個(gè)請求報(bào)文做出回應(yīng)壶运,并切換到SYN_RCVD
狀態(tài)耐齐,建立TCP連接,而這個(gè)回應(yīng)報(bào)文發(fā)送到客戶端時(shí)前弯,客戶端并不會處理此請求蚪缀,因?yàn)樗l(fā)出去的請求報(bào)文早已過期,它沒有處于SYN_SEND
狀態(tài)恕出,而服務(wù)器誤以為客戶端已經(jīng)處于此狀態(tài)询枚,這樣就會造成服務(wù)器資源的不必要損耗,由此得出了“三次握手”建立TCP連接的方法浙巫。
通過三次握手金蜀,服務(wù)器在接收到失效請求時(shí)也是做出了回應(yīng),但這個(gè)回應(yīng)(SYN/ACK包)如果在一定時(shí)間內(nèi)沒有收到回應(yīng)的畴,則不會建立TCP連接渊抄,資源被釋放;如果服務(wù)器收到了來自客戶端的回應(yīng)丧裁,則建立TCP連接护桦。
TCP的三次握手
“三次握手”的作用就是保證客戶端、服務(wù)器端雙方都能明確自己和對方的收煎娇、發(fā)能力是正常的二庵。
最開始的時(shí)候客戶端和服務(wù)器都是處于CLOSED可用狀態(tài)。開始建立TCP連接之前缓呛,服務(wù)器端的一個(gè)端口已經(jīng)被動(dòng)打開(passive open)催享,用于監(jiān)聽來自客戶端的請求,這樣哟绊,客戶端的端口可以主動(dòng)打開(active open)因妙,發(fā)送請求到服務(wù)器端,尋求建立連接票髓。
第一次握手:客戶端向服務(wù)器端發(fā)送SYN包攀涵,SYN標(biāo)志位(Flag)置1,包的序號為客戶端的ISN(Initial Sequence Number)炬称,包發(fā)出后汁果,客戶端進(jìn)入
SYN_SEND
狀態(tài),客戶端知曉客戶端的發(fā)包能力正常玲躯;第二次握手:服務(wù)端接收客戶端發(fā)來的連接請求据德,以SYN+ACK包做出回應(yīng)鳄乏,包的SYN標(biāo)志位置1,ACK標(biāo)志位置1棘利,序號為服務(wù)端的ISN(與客戶端的ISN不同)橱野,確認(rèn)碼為客戶端的ISN加1,包發(fā)出后善玫,服務(wù)端進(jìn)入
SYN_RCVD
狀態(tài)水援,服務(wù)端知曉客戶端的發(fā)包能力正常、服務(wù)端的發(fā)包能力正常茅郎,服務(wù)器的收包能力正常蜗元;第三次握手:客戶端接收服務(wù)端發(fā)來的響應(yīng),以ACK包做出回應(yīng)系冗,包的ACK置1奕扣,序號為客戶端的ISN+1,確認(rèn)碼為服務(wù)端的ISN+1掌敬,此包發(fā)出后惯豆,客戶端轉(zhuǎn)為
ESTABLISHED
狀態(tài),客戶端知曉服務(wù)端的發(fā)包能力正常奔害,服務(wù)端的收包能力正常楷兽、客戶端的收包能力正常。服務(wù)器接收到這個(gè)包后华临,也進(jìn)入ESTABLISHED
狀態(tài)芯杀,服務(wù)端知曉客戶端的收包能力正常,至此TCP連接被成功建立雅潭,可以進(jìn)行數(shù)據(jù)傳輸瘪匿。
三次握手中的數(shù)據(jù)包只有TCP頭部信息,沒有主體信息寻馏。
TCP協(xié)議規(guī)定,ACK報(bào)文段(ACK標(biāo)志位置1的報(bào)文)可以攜帶數(shù)據(jù)核偿,但是如果不攜帶數(shù)據(jù)則不消耗序號诚欠,即下一個(gè)報(bào)文的序號仍為ACK報(bào)文的序號。
TCP協(xié)議規(guī)定漾岳,SYN報(bào)文段(SYN標(biāo)志位置1的報(bào)文轰绵,SYN+ACK報(bào)文也屬于這種情況)不能攜帶數(shù)據(jù),但需要消耗掉一個(gè)序號尼荆,下一個(gè)發(fā)送的報(bào)文序號需要+1左腔。
為什么TCP要四次揮手才能互相斷開TCP連接?
簡單來說捅儒,處于傳輸層的TCP協(xié)議是一個(gè)可靠的協(xié)議液样,而在它下面振亮,處于網(wǎng)絡(luò)層的IP(Internet Protocol,網(wǎng)絡(luò)協(xié)議)協(xié)議是不可靠的鞭莽,TCP可靠性的具體體現(xiàn)之一就是四次揮手坊秸,不會出現(xiàn)不必要的錯(cuò)誤和資源損耗。
那四次分手又是為何呢澎怒?TCP協(xié)議是一種面向連接的褒搔、可靠的、基于字節(jié)流的運(yùn)輸層通信協(xié)議喷面,全雙工模式星瘾。
單工(Simplex)通信是指消息只能單方向傳輸?shù)墓ぷ鞣绞健@邕b控惧辈、遙測琳状。
半雙工(Half Duplex)數(shù)據(jù)傳輸指數(shù)據(jù)可以在一個(gè)信號載體的兩個(gè)方向上傳輸,但是不能同時(shí)傳輸咬像。
全雙工(Full Duplex)通信允許數(shù)據(jù)在兩個(gè)方向上同時(shí)傳輸算撮,它在能力上相當(dāng)于兩個(gè)單工通信方式的結(jié)合。
這就意味著县昂,當(dāng)主機(jī)1發(fā)出FIN報(bào)文段時(shí)肮柜,只是表示主機(jī)1已經(jīng)沒有數(shù)據(jù)要發(fā)送了,主機(jī)1告訴主機(jī)2倒彰,它的數(shù)據(jù)已經(jīng)全部發(fā)送完畢了审洞;但這時(shí)主機(jī)1還是可以接受來自主機(jī)2的數(shù)據(jù);當(dāng)主機(jī)2返回ACK報(bào)文段時(shí)待讳,表示它已經(jīng)知道主機(jī)1沒有數(shù)據(jù)發(fā)送了芒澜,但是主機(jī)2還是可以發(fā)送數(shù)據(jù)到主機(jī)1的;當(dāng)主機(jī)2也發(fā)送了FIN報(bào)文段時(shí)创淡,這個(gè)時(shí)候就表示主機(jī)2也沒有數(shù)據(jù)要發(fā)送了痴晦,就會告訴主機(jī)1,我也沒有數(shù)據(jù)要發(fā)送了琳彩,之后彼此就會愉快地?cái)嚅_這次TCP連接誊酌。
可以看到,如果不經(jīng)過四次揮手露乏,是不能斷開連接的碧浊,因?yàn)閷Ψ侥抢锟赡苓€有數(shù)據(jù)沒發(fā)送。只有雙方互相確認(rèn)(ACK)了彼此的FIN報(bào)文,TCP連接才能斷開,TCP才靠得住躏尉。
TCP四次揮手
客戶端和服務(wù)器端均可以發(fā)出FIN報(bào)文,即發(fā)出斷開連接的請求——表示自己沒有數(shù)據(jù)要發(fā)送給對方了驹止,誰先發(fā)的誰即為主動(dòng)方浩聋。
[圖片上傳失敗...(image-308658-1606361336319)]
第一次揮手:主動(dòng)方 向 被動(dòng)方 發(fā)出FIN報(bào)文,序號為u(等于前面已經(jīng)傳送過來的數(shù)據(jù)的最后一個(gè)字節(jié)的序號加1)幢哨,確認(rèn)碼為被動(dòng)方的ISN+1赡勘,此時(shí)主動(dòng)方進(jìn)入
FIN_WAIT_1
狀態(tài),等待被動(dòng)方確認(rèn)捞镰。第二次揮手:被動(dòng)方發(fā)送ACK報(bào)文給主動(dòng)方闸与,確認(rèn)主動(dòng)方可以關(guān)閉連接,這個(gè)報(bào)文中序號為v(由之前已發(fā)出的數(shù)據(jù)序列決定)岸售,確認(rèn)碼為u+1践樱,被動(dòng)方發(fā)出ACK報(bào)文后進(jìn)入
CLOSE_WAIT
狀態(tài),檢查自身是否還有數(shù)據(jù)發(fā)送給對方——這時(shí)候被動(dòng)方處于半關(guān)閉狀態(tài)凸丸,即主動(dòng)方已經(jīng)沒有數(shù)據(jù)要發(fā)送了拷邢,但是被動(dòng)方若發(fā)送數(shù)據(jù),主動(dòng)方依然要接收屎慢。這個(gè)狀態(tài)還要持續(xù)一段時(shí)間瞭稼,也就是整個(gè)CLOSE_WAIT
狀態(tài)持續(xù)的時(shí)間。主動(dòng)方接收到ACK消息即轉(zhuǎn)入FIN_WAIT_2
狀態(tài)腻惠,繼續(xù)等待被動(dòng)方發(fā)來的FIN報(bào)文环肘。第三次揮手:還是被動(dòng)方,被動(dòng)方檢查自身沒有數(shù)據(jù)要發(fā)給主動(dòng)方了集灌,而在這之前被動(dòng)方很可能又發(fā)送了一些數(shù)據(jù)給主動(dòng)方悔雹,假定此時(shí)的序號為w。被動(dòng)方發(fā)送FIN+ACK報(bào)文給主動(dòng)方欣喧,序號為w腌零,確認(rèn)碼為u+1,發(fā)出后唆阿,被動(dòng)方轉(zhuǎn)入
LAST_ACK
狀態(tài)益涧,等待主動(dòng)方關(guān)于斷開連接的確認(rèn)。第四次揮手:主動(dòng)方收到被動(dòng)方發(fā)來的FIN報(bào)文驯鳖,回應(yīng)一個(gè)ACK報(bào)文饰躲,序號為u+1,確認(rèn)碼為w+1臼隔。發(fā)出后,主動(dòng)方轉(zhuǎn)入
TIME_WAIT
狀態(tài)妄壶,將在2?MSL( Maximum Segment Lifetime摔握,最長報(bào)文段壽命)后斷開連接,隨后進(jìn)入CLOSED
可用狀態(tài)丁寄;被動(dòng)方接收到最后的ACK報(bào)文后氨淌,隨即斷開連接泊愧,進(jìn)入CLOSED
可用狀態(tài)。
TCP規(guī)定盛正,F(xiàn)IN報(bào)文段要消耗一個(gè)序號删咱,即下一個(gè)把報(bào)文的序號需+1。
服務(wù)器結(jié)束TCP連接的時(shí)間要比客戶端早一些豪筝。
①
FIN_WAIT_1
(主動(dòng)方):FIN_WAIT_1
和FIN_WAIT_2
狀態(tài)都表示等待對方的FIN報(bào)文痰滋。這兩種狀態(tài)的區(qū)別是:
FIN_WAIT_1
狀態(tài)實(shí)際上是當(dāng)SOCKET在ESTABLISHED
狀態(tài)時(shí),它想主動(dòng)關(guān)閉連接续崖,向?qū)Ψ桨l(fā)送了FIN報(bào)文敲街,此時(shí)該SOCKET即進(jìn)入到FIN_WAIT_1
狀態(tài)。而當(dāng)對方回應(yīng)ACK報(bào)文后严望,SOCKET方進(jìn)入到FIN_WAIT_2
狀態(tài)多艇。在實(shí)際情況下,無論對方何種狀況像吻,都會馬上回應(yīng)這個(gè)FIN一個(gè)ACK報(bào)文峻黍,所以
FIN_WAIT_1
狀態(tài)一般是比較難捕捉到的,而FIN_WAIT_2
狀態(tài)巢Υ遥可以用netstat命令查看姆涩。②
FIN_WAIT_2
(主動(dòng)方):FIN_WAIT_2
狀態(tài)下的SOCKET,表示半連接涮雷,也即主動(dòng)方要求斷開TCP連接阵面,但主動(dòng)方仍需要接收對方發(fā)來的FIN報(bào)文,并回應(yīng)一個(gè)ACK報(bào)文洪鸭。③
CLOSE_WAIT
(被動(dòng)方):這種狀態(tài)的含義其實(shí)是表示在等待關(guān)閉样刷。怎么理解呢?當(dāng)對方close一個(gè)SOCKET后發(fā)送FIN報(bào)文給自己览爵,你系統(tǒng)毫無疑問地會回應(yīng)一個(gè)ACK報(bào)文給對方置鼻,此時(shí)則進(jìn)入到CLOSE_WAIT
狀態(tài)。接下來你真正需要考慮的蜓竹,是查看你是否還有數(shù)據(jù)發(fā)送給主動(dòng)方箕母,如果沒有的話,那么你也就可以 close這個(gè)SOCKET俱济,發(fā)送FIN報(bào)文給對方嘶是,也即關(guān)閉連接。所以你在
CLOSE_WAIT
狀態(tài)下蛛碌,需要完成的事情是檢查你還有沒有數(shù)據(jù)要發(fā)給對方聂喇,沒有就關(guān)閉連接,發(fā)送FIN報(bào)文告知主動(dòng)方。④
LAST_ACK
(被動(dòng)方): 是被動(dòng)方在發(fā)送FIN報(bào)文后處于的一個(gè)狀態(tài)希太,即被動(dòng)方已確認(rèn)無數(shù)據(jù)需要發(fā)送給主動(dòng)方克饶,可以關(guān)閉連接。被動(dòng)方最后等待主動(dòng)方的ACK報(bào)文誊辉。當(dāng)收到ACK報(bào)文后矾湃,被動(dòng)方即進(jìn)入
CLOSED
可用狀態(tài)了。⑤
TIME_WAIT
(主動(dòng)方): 表示收到了對方的FIN報(bào)文堕澄,并發(fā)送出了ACK報(bào)文邀跃,就等2MSL后主動(dòng)方即可回到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
: 表示連接已斷開丽涩。