TCP 可靠傳輸?shù)膶?shí)現(xiàn)(一)TCP的三次握手和四次揮手

1爸黄、介紹TCP

TCP(Transmission Control Protocol 傳輸控制協(xié)議)是一種面向連接、可靠的、基于字節(jié)流的傳輸層通信協(xié)議偏陪。

TCP將通過以下方式來提供可靠性傳輸:

TCP 可靠性傳輸實(shí)現(xiàn)(一)TCP的三次握手和四次揮手酪耳;

TCP 可靠性傳輸實(shí)現(xiàn)(二)TCP的重傳機(jī)制浓恳;

http://www.reibang.com/p/f7f75a0f6384

TCP 可靠性傳輸實(shí)現(xiàn)(三)TCP的流量控制和擁塞機(jī)制;

TCP 可靠性傳輸實(shí)現(xiàn)(四)TCP的蓖氚担活機(jī)制颈将;

TCP面向連接意味著兩個使用TCP的應(yīng)用(通常是一個客戶端和一個服務(wù)器)在彼此交換數(shù)據(jù)之前必須先建立一個TCP連接。這一過程和打電話相似言疗,先撥號振鈴吆鹤,等待對方接通后說“喂”,然后才說明是誰洲守。在本文將介紹TCP是如何建立連接的疑务,以及當(dāng)一方通信結(jié)束后如何斷開連接。

2梗醇、TCP的首部

TCP數(shù)據(jù)被封裝在一個IP數(shù)據(jù)報中知允,如圖:

TCP數(shù)據(jù)在IP數(shù)據(jù)報中的封裝

下圖顯示TCP首部的數(shù)據(jù)格式。如果不計任選字段叙谨,它通常是20個字節(jié)温鸽。

TCP包首部

每個TCP段都包含源端和目的端的端口號,用于尋找發(fā)端和收端應(yīng)用程序手负。這兩個值加上IP首部中的源端IP地址和目的端IP地址唯一確定一個TCP連接涤垫。

一個IP地址和一個端口號也稱為一個插口(socket)插口對(socket pair)(包含客戶IP地址竟终、客戶端端口號蝠猬、服務(wù)器IP地址和服務(wù)器端口號的四元組)可唯一確定互聯(lián)網(wǎng)絡(luò)中每個TCP連接的雙方。

下面介紹下TCP首部字段

序列號:用來標(biāo)識從TCP發(fā)端向TCP收端發(fā)送的數(shù)據(jù)字節(jié)流统捶,它表示在這個報文段中的第一個數(shù)據(jù)字節(jié)榆芦。如果把字節(jié)流看做在兩個應(yīng)用程序間的單向流動,則TCP用序號對每個字節(jié)進(jìn)行計數(shù)喘鸟。序號是32bit的無符號數(shù)匆绣,序號到達(dá)2^32-1后又從0開始。序號用來解決網(wǎng)絡(luò)包亂序問題什黑。接收端根據(jù)這個編號進(jìn)行確認(rèn)崎淳。

確認(rèn)號:是接收確認(rèn)端期望收到的下一個序列號。確認(rèn)號應(yīng)當(dāng)是上次已成功收到的數(shù)據(jù)字節(jié)序號加1愕把,只有當(dāng)標(biāo)志位中的ACK標(biāo)志為1時該確認(rèn)號的字段才有效拣凹。主要用來解決丟包問題茵瘾。

若確認(rèn)號=N,則表明:到序號N-1為止的所有數(shù)據(jù)都已正確收到咐鹤。

首部長度

TCP 首部總長度由該字段決定拗秘。該字段占 4bit,取最大值1111時祈惶,也就是十進(jìn)制的 15雕旨,TCP 首部的偏移單位是 4 byte, 那么TCP 首部最長是 15 * 4 = 60 字節(jié)。?TCP 首部總長度有20個固定字節(jié)捧请,所以該字段最短是 20byte / 4byte =?5凡涩,即 0101。首部長度也叫做數(shù)據(jù)偏移疹蛉,因為首部長度實(shí)際上指示了數(shù)據(jù)區(qū)在報文段的起始偏移值活箕。

保留位

為將來定義新的用途保留,現(xiàn)在一般置 0可款。

控制位:TCP首部中有6個標(biāo)志比特育韩,它們中的多個可同時被設(shè)置為1,主要是用于操控TCP的狀態(tài)機(jī)的闺鲸,依次為URG 筋讨、 ACK、? PSH摸恍、 RST悉罕、 SYN、 FIN立镶。

\bullet ?URG:緊急指針有效壁袄,是發(fā)送端向接收端發(fā)送緊急數(shù)據(jù)的一種方式。

\bullet ?ACK:該位為1時表示【確認(rèn)應(yīng)答號】有效媚媒,TCP規(guī)定除了最初建立連接時的 SYN 號之外嗜逻,該位必須設(shè)置為1。

\bullet ?PSH:接收方應(yīng)該盡快將這個報文段交給應(yīng)用層欣范。

\bullet ?SYN:該位為1時表示希望建立連接变泄,同步序號用來發(fā)起一個連接令哟。

\bullet ?RST:該位為1時表示TCP連接出現(xiàn)異常恼琼,必須強(qiáng)制斷開連接。

\bullet ?FIN:該位為1時表示希望斷開連接屏富。

窗口大小

TCP的流量控制由連接的每一端通過聲明的窗口大小來提供晴竞。

校驗和

是一個強(qiáng)制性的字段,一定是由發(fā)送端計算和存儲狠半,并由接收端進(jìn)行驗證噩死。

緊急指針

當(dāng)URG標(biāo)志置1時緊急指針才有效颤难。緊急指針是一個正的偏移量,和序號字段中的值相加表示緊急數(shù)據(jù)最后一個字節(jié)的序號已维。

選項字段

選項字段的長度 = TCP 首部總長度 - 20 字節(jié)固定長度行嗤。 由于 TCP?首部總長度最大為 60字節(jié), 那么選項字段的長度最大為 40 字節(jié)垛耳;

一個選項字段占 4個字節(jié)


最常見的可選字段是最長報文大小栅屏,又稱為MSS(Maximum Segment Size)。每個連接方通常都在通信的第一個報文段(為建立連接而設(shè)置SYN標(biāo)志的那個段)中指明這個選項堂鲜。它表明本端所能接收的最大長度的報文段栈雳。

數(shù)據(jù)

數(shù)據(jù)部分是可選的,在連接建立和終止時缔莲,雙方交換的報文段僅有TCP首部哥纫,如果一方?jīng)]有數(shù)據(jù)要發(fā)送,也使用沒有任何數(shù)據(jù)的首部來確認(rèn)收到的數(shù)據(jù)痴奏。

3蛀骇、TCP連接的建立

TCP連接的建立與關(guān)閉

第一次握手:客戶端發(fā)送請求報文將 SYN = J 的初始序列號發(fā)送給服務(wù)端,發(fā)送完之后客戶端處于SYN_SENT狀態(tài)读拆。

第二次握手:服務(wù)端收到SYN請求報文后松靡,如果同意連接,會以自己的SYN(服務(wù)端) = K? 的初始序列號和 ack = SYN(客戶端) + 1 報文作為應(yīng)答建椰,服務(wù)端處于SYN_RECEIVE狀態(tài)雕欺。

第三次握手:客戶端接收到服務(wù)端的SYN+ack, 發(fā)送 ack = SYN(服務(wù)端) + 1確認(rèn)包作為應(yīng)答棉姐,客戶端轉(zhuǎn)為ESTABLISHED狀態(tài)屠列。

為什么是三次握手?不是兩次伞矩、四次笛洛?

這個問題需要回到TCP的概念上:

TCP連接是為了得到 保證連接可靠性和流量控制所需維護(hù)的某些狀態(tài)信息,這些信息的組合包括 Socket乃坤、序列號苛让、窗口大小。 所以問題就是湿诊,為什么三次握手才可以初始化Socket狱杰、序列號、窗口大小并建立TCP連接厅须。原因有三:

客戶端連續(xù)發(fā)送多次SYN建立連接的報文仿畸,在網(wǎng)絡(luò)擁堵等情況下出現(xiàn):

\bullet ?一個【舊的SYN報文】比【最新的SYN】報文更早到了服務(wù)端,那么此時,服務(wù)端就會回一個SYN + ACK 報文給客戶端错沽;

\bullet ?客戶端收到后根據(jù)自身的上下文簿晓,判斷這是一個歷史連接(序列號過期或超時),那么客戶端就會發(fā)送 RST 報文給服務(wù)端千埃,表示終止這一次的連接憔儿;

如果是兩次握手連接,就不能判斷此次連接是否是歷史連接放可,三次握手可以讓客戶端準(zhǔn)備發(fā)送第三次報文時皿曲,客戶端有足夠的上下文來判斷當(dāng)前的連接是否是歷史連接。

(2)三次握手才可以同步雙方的初始序列號吴侦;

TCP的通信雙方都必須維護(hù)一個【序列號】屋休,序列號是可靠傳輸?shù)囊粋€關(guān)鍵因素,它的作用:

\bullet ?接收方可以丟棄重復(fù)的數(shù)據(jù)备韧;

\bullet ?接收方可以根據(jù)數(shù)據(jù)包的序列號按序接收劫樟;

\bullet ?發(fā)送方可以標(biāo)識哪些數(shù)據(jù)包是已被對方接收到的;

因此在三次握手中织堂,當(dāng)客戶端方法攜帶【初始序列號】的 SYN 報文的時候叠艳,需要服務(wù)端回一個 ACK 應(yīng)答報文,表示客戶端的 SYN報文已被服務(wù)端成功接收易阳, 那當(dāng)服務(wù)端發(fā)送【初始序列號】給客戶端的時候附较,也需要得到客戶端的應(yīng)答回應(yīng),這樣才能保證雙方的初始序列號能被可靠的同步潦俺。

四次握手是把 服務(wù)端回應(yīng)客戶端的 ACK 請求和服務(wù)端發(fā)送給服務(wù)端的初始序列號(第二步拒课、第三步)合并成了一步,因此就成了【三次握手】事示。

(3)三次握手才可以避免資源的浪費(fèi)早像;

如果只有【兩次握手】,當(dāng)客戶端的 SYN 請求連接在網(wǎng)絡(luò)中阻塞肖爵,客戶端超時沒有收到 ACK 應(yīng)答報文就會重新發(fā)送 SYN卢鹦,由于沒有三次握手,服務(wù)端直接就分配資源并建立連接會導(dǎo)致:

建立了多個冗余的無效連接劝堪,造成不必要的浪費(fèi)冀自。

兩次握手會導(dǎo)致資源浪費(fèi)

4、TCP連接的斷開

四次揮手

第一次揮手:首先進(jìn)行關(guān)閉的一方(即發(fā)送第一個 FIN)將執(zhí)行主動關(guān)閉秒啦,而另一方(收到這個 FIN)執(zhí)行被動關(guān)閉熬粗。客戶端發(fā)送完 FIN 報文后帝蒿,就進(jìn)入了 FIN_WAIT_1 狀態(tài)荐糜;

第二次揮手:服務(wù)器收到這個 FIN ,它發(fā)回一個確認(rèn)應(yīng)答 ACK葛超,ack = M + 1 (即暴氏,收到的序號+1)? 表示收到了,接著服務(wù)端進(jìn)入CLOSE_WAIT 狀態(tài)绣张〈鹩妫客戶端收到服務(wù)端的 ACK 應(yīng)答報文后,進(jìn)入 FIN_WAIT_2 狀態(tài)侥涵。

第三次揮手:等待服務(wù)端處理完數(shù)據(jù)后沼撕,也向客戶端發(fā)送 FIN 報文,之后服務(wù)端進(jìn)入 LAST_ACK 狀態(tài)芜飘。

第四次揮手:服務(wù)端收到了 ACK 應(yīng)答報文后务豺,就進(jìn)入了 CLOSE 狀態(tài),至此服務(wù)端完成了連接的關(guān)閉嗦明。

為什么揮手需要四次笼沥?

\bullet ?關(guān)閉連接時,客戶端向服務(wù)端發(fā)送 FIN 時娶牌,僅僅表示客戶端不再發(fā)送數(shù)據(jù)了奔浅,但還是能接收數(shù)據(jù)。

\bullet ?服務(wù)端收到客戶端的 FIN 報文時诗良,先回一個 ACK 應(yīng)答報文汹桦,而服務(wù)端可能還有數(shù)據(jù)需要處理和發(fā)送,等服務(wù)端不再發(fā)送數(shù)據(jù)時鉴裹,才發(fā)送 FIN 報文給客戶端表示同意關(guān)閉連接舞骆。

服務(wù)端的 ACK 和 FIN 一般都會分開發(fā)送,從而比三次握手多了一次径荔。

5葛作、Socket編程

應(yīng)用在使用 TCP 或 UDP 時,會用到操作系統(tǒng)提供的類庫猖凛。這種類庫一般被稱為API(Application Programming Interface 應(yīng)用編程接口)赂蠢,使用 TCP 或 UDP 通信時,又會廣泛使用到套接字(Socket)的API辨泳。

Socket

那么TCP如何利用Socket編程

基于TCP的Socket通信

\bullet ?服務(wù)端和客戶端初始化 socket虱岂,得到文件描述符;

\bullet ?服務(wù)端調(diào)用 bind 菠红,將綁定 IP 地址和端口號第岖;

\bullet ?服務(wù)端調(diào)用 listen ,進(jìn)行監(jiān)聽试溯;

\bullet ?服務(wù)端調(diào)用 accept蔑滓,等待客戶端連接;

\bullet ?客戶端調(diào)用 connect,向服務(wù)端的地址和端口發(fā)起連接請求键袱;

\bullet ?服務(wù)端 accept 返回用于傳輸?shù)?socket 的文件描述符燎窘;

\bullet ?客戶端調(diào)用 write 寫入數(shù)據(jù); 服務(wù)端調(diào)用 read 讀取數(shù)據(jù)蹄咖;

\bullet ?客戶端斷開連接時褐健,會調(diào)用 close , 服務(wù)端 read 讀取數(shù)據(jù)的時候澜汤,就會讀取到 EOF蚜迅,待處理完數(shù)據(jù)后,服務(wù)端調(diào)用 close 表示連接關(guān)閉俊抵。

注意:服務(wù)端調(diào)用 accept 時谁不,連接成功了會返回一個已完成連接的socket,后續(xù)用來傳輸數(shù)據(jù)徽诲。所以刹帕,監(jiān)聽的 socket 和 用來傳輸數(shù)據(jù)的 socket,是兩個 socket馏段,一個是 監(jiān)聽 socket轩拨,一個是 已完成連接 socket。

重點(diǎn)講下三次握手連接請求的實(shí)現(xiàn):

通過隊列實(shí)現(xiàn)

處于 listen 狀態(tài)的 TCP socket院喜,有兩個獨(dú)立的隊列:

\bullet ?SYN 隊列(SYN Queue)

存儲了收到了 SYN 包的連接亡蓉,它的職責(zé)是回復(fù) SYN + ACK 包,并且在客戶端沒有收到 ACK包時執(zhí)行重傳喷舀。 發(fā)送完 SYN + ACK 之后砍濒, SYN 隊列等待從客戶端發(fā)出的 Ack 包(三次握手的最后一個包)。當(dāng)收到 ACK 包時硫麻,首先找到對應(yīng)的 SYN 隊列爸邢,再在對應(yīng)的 SYN隊列中檢查相關(guān)的數(shù)據(jù)是否匹配,如果匹配拿愧,則將連接相關(guān)的數(shù)據(jù)從 SYN 隊列中移除杠河,創(chuàng)建一個完整的連接(用于傳輸數(shù)據(jù)的),并將這個連接加入到 Accept 隊列浇辜。

\bullet ?Accept 隊列(Accept Queue)

存放的是已建立好的連接券敌,等待被應(yīng)用程序取走。 當(dāng)進(jìn)程調(diào)用 accept() 時柳洋, 將 socket 從隊列中取出待诅,傳遞給上層應(yīng)用程序。


參考文檔:
1熊镣、TCP/IP 詳解

2卑雁、圖解tcpip

3募书、https://mp.weixin.qq.com/s/tH8RFmjrveOmgLvk9hmrkw

4、https://mp.weixin.qq.com/s/5VXhL0dTFcWNyfQ7-7NBEg

5测蹲、https://mp.weixin.qq.com/s?src=11&timestamp=1592656050&ver=2412&signature=8YnNG5TR2QrxJK4CPHAknP8I4ujYG2voPwedWyH1EJXVSQUKDS5IaHvbMd3S7kpL7GrCaZkQbvgbh5OoX9IZ777abi2e3Ze-Cu1DCoLk9cexKOng3oXRfgt60fOU2gNF&new=1

6莹捡、https://blog.csdn.net/mary19920410/article/details/58030147

7、https://blog.csdn.net/Mary19920410/article/details/72857764

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末弛房,一起剝皮案震驚了整個濱河市道盏,隨后出現(xiàn)的幾起案子而柑,更是在濱河造成了極大的恐慌文捶,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,865評論 6 518
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件媒咳,死亡現(xiàn)場離奇詭異粹排,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)涩澡,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,296評論 3 399
  • 文/潘曉璐 我一進(jìn)店門顽耳,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人妙同,你說我怎么就攤上這事射富。” “怎么了粥帚?”我有些...
    開封第一講書人閱讀 169,631評論 0 364
  • 文/不壞的土叔 我叫張陵胰耗,是天一觀的道長。 經(jīng)常有香客問我芒涡,道長柴灯,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 60,199評論 1 300
  • 正文 為了忘掉前任费尽,我火速辦了婚禮赠群,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘旱幼。我一直安慰自己查描,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,196評論 6 398
  • 文/花漫 我一把揭開白布柏卤。 她就那樣靜靜地躺著冬三,像睡著了一般。 火紅的嫁衣襯著肌膚如雪闷旧。 梳的紋絲不亂的頭發(fā)上长豁,一...
    開封第一講書人閱讀 52,793評論 1 314
  • 那天,我揣著相機(jī)與錄音忙灼,去河邊找鬼匠襟。 笑死钝侠,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的酸舍。 我是一名探鬼主播帅韧,決...
    沈念sama閱讀 41,221評論 3 423
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼啃勉!你這毒婦竟也來了忽舟?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 40,174評論 0 277
  • 序言:老撾萬榮一對情侶失蹤淮阐,失蹤者是張志新(化名)和其女友劉穎叮阅,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體泣特,經(jīng)...
    沈念sama閱讀 46,699評論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡浩姥,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,770評論 3 343
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了状您。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片勒叠。...
    茶點(diǎn)故事閱讀 40,918評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖膏孟,靈堂內(nèi)的尸體忽然破棺而出眯分,到底是詐尸還是另有隱情,我是刑警寧澤柒桑,帶...
    沈念sama閱讀 36,573評論 5 351
  • 正文 年R本政府宣布弊决,位于F島的核電站,受9級特大地震影響幕垦,放射性物質(zhì)發(fā)生泄漏丢氢。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,255評論 3 336
  • 文/蒙蒙 一先改、第九天 我趴在偏房一處隱蔽的房頂上張望疚察。 院中可真熱鬧,春花似錦仇奶、人聲如沸貌嫡。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,749評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽岛抄。三九已至,卻和暖如春狈茉,著一層夾襖步出監(jiān)牢的瞬間夫椭,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,862評論 1 274
  • 我被黑心中介騙來泰國打工氯庆, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留蹭秋,地道東北人扰付。 一個月前我還...
    沈念sama閱讀 49,364評論 3 379
  • 正文 我出身青樓,卻偏偏與公主長得像仁讨,于是被迫代替她去往敵國和親羽莺。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,926評論 2 361