簡介
TCP連接是面向連接的、可靠的用爪、基于字節(jié)流的傳輸層通信協(xié)議原押。在傳輸數(shù)據(jù)之前,通信雙方必須建立一條連接偎血。所謂的‘連接’诸衔,其實就是客戶端和服務端保存的一份對方的信息,如:ip地址颇玷、端口號等笨农。在連接的建立過程中,雙方需要交換一些連接的參數(shù)帖渠。這些參數(shù)可以放在TCP頭部谒亦。一個TCP連接由一個4元組構成,分別是兩個ip地址和兩個端口號空郊。一個TCP連接通常分為三個階段:連接诊霹、數(shù)據(jù)傳輸、退出(關閉)渣淳。通過三次握手來創(chuàng)建一個連接脾还,通過四次揮手來關閉一個連接。當一個連接被建立或被終止時入愧,交換的保溫只包含TCP頭部鄙漏,而沒有數(shù)據(jù)。
1.TCP報文的頭部結構
上圖幾個字段重點介紹下:
(1)序號:seq序號棺蛛,占32位
(2)確認序號:ack序號怔蚌,占32位,只有ACK標志位為1時旁赊,確認序號字段才有效桦踊,ack=seq+1。
(3)標志位:共6個,即URG终畅、ACK籍胯、PSH、RST离福、SYN杖狼、FIN等,具體含義如下:
ACK:確認序號有效妖爷。
FIN:釋放一個連接蝶涩。
PSH:接收方應該盡快將這個報文交給應用層。
RST:重置連接。SYN:發(fā)起一個新連接绿聘。
URG:緊急指針(urgent pointer)有效嗽上。需要注意的是:不要將確認序號ack與標志位中的ACK搞混了。確認方ack=發(fā)起方seq+1熄攘,兩端配對兽愤。
<meta charset="utf-8">
2. 三次握手
三次握手的本質是確認通信雙方收發(fā)數(shù)據(jù)的能力首先,我讓信使運輸一份信件給對方鲜屏,對方收到了烹看,那么他就知道了我的發(fā)件能力和他的收件能力是可以的国拇。于是他給我回信洛史,我若收到了,我便知我的發(fā)件能力和他的收件能力是可以的酱吝,并且他的發(fā)件能力和我的收件能力是可以也殖。然而此時他還不知道他的發(fā)件能力和我的收件能力到底可不可以,于是我最后回饋一次务热,他若收到了忆嗜,他便清楚了他的發(fā)件能力和我的收件能力是可以的。這崎岂,就是三次握手捆毫。
- 第一次握手:客戶端要向服務端發(fā)起連接請求,首先客戶端隨機生成一個起始序列號ISN(比如是100)冲甘,那客戶端向服務端發(fā)送的報文段包含SYN標志位(也就是SYN=1)绩卤,序列號seq=100。
- 第二次握手:服務端收到客戶端發(fā)過來的報文后江醇,發(fā)現(xiàn)SYN=1濒憋,知道這是一個連接請求,于是將客戶端的起始序列號100存起來陶夜,并且隨機生成一個服務端的起始序列號(比如是300)凛驮。然后給客戶端回復一段報文,回復報文包含SYN和ACK標志(也就是SYN=1,ACK=1)条辟、序列號seq=300黔夭、確認號ack=101(客戶端發(fā)過來的序列號+1)。
- 第三次握手:客戶端收到服務端的回復后發(fā)現(xiàn)ACK=1并且ack=101,于是知道服務端已經收到了序列號為100的那段報文羽嫡;同時發(fā)現(xiàn)SYN=1纠修,知道了服務端同意了這次連接,于是就將服務端的序列號300給存下來厂僧。然后客戶端再回復一段報文給服務端扣草,報文包含ACK標志位(ACK=1)、ack=301(服務端序列號+1)、seq=101(第一次握手時發(fā)送報文是占據(jù)一個序列號的辰妙,所以這次seq就從101開始鹰祸,需要注意的是不攜帶數(shù)據(jù)的ACK報文是不占據(jù)序列號的,所以后面第一次正式發(fā)送數(shù)據(jù)時seq還是101)密浑。當服務端收到報文后發(fā)現(xiàn)ACK=1并且ack=301蛙婴,就知道客戶端收到序列號為300的報文了,就這樣客戶端和服務端通過TCP建立了連接尔破。
3. 四次揮手
四次揮手的目的是關閉一個連接
比如客戶端初始化的序列號ISA=100街图,服務端初始化的序列號ISA=300。TCP連接成功后客戶端總共發(fā)送了1000個字節(jié)的數(shù)據(jù)懒构,服務端在客戶端發(fā)FIN報文前總共回復了2000個字節(jié)的數(shù)據(jù)餐济。
- 第一次揮手:當客戶端的數(shù)據(jù)都傳輸完成后,客戶端向服務端發(fā)出連接釋放報文(當然數(shù)據(jù)沒發(fā)完時也可以發(fā)送連接釋放報文并停止發(fā)送數(shù)據(jù))胆剧,釋放連接報文包含F(xiàn)IN標志位(FIN=1)絮姆、序列號seq=1101(100+1+1000,其中的1是建立連接時占的一個序列號)秩霍。需要注意的是客戶端發(fā)出FIN報文段后只是不能發(fā)數(shù)據(jù)了篙悯,但是還可以正常收數(shù)據(jù);另外FIN報文段即使不攜帶數(shù)據(jù)也要占據(jù)一個序列號铃绒。
- 第二次揮手:服務端收到客戶端發(fā)的FIN報文后給客戶端回復確認報文鸽照,確認報文包含ACK標志位(ACK=1)、確認號ack=1102(客戶端FIN報文序列號1101+1)颠悬、序列號seq=2300(300+2000)矮燎。此時服務端處于關閉等待狀態(tài),而不是立馬給客戶端發(fā)FIN報文椿疗,這個狀態(tài)還要持續(xù)一段時間漏峰,因為服務端可能還有數(shù)據(jù)沒發(fā)完。
- 第三次揮手:服務端將最后數(shù)據(jù)(比如50個字節(jié))發(fā)送完畢后就向客戶端發(fā)出連接釋放報文届榄,報文包含F(xiàn)IN和ACK標志位(FIN=1,ACK=1)浅乔、確認號和第二次揮手一樣ack=1102、序列號seq=2350(2300+50)铝条。
- 第四次揮手:客戶端收到服務端發(fā)的FIN報文后靖苇,向服務端發(fā)出確認報文,確認報文包含ACK標志位(ACK=1)班缰、確認號ack=2351贤壁、序列號seq=1102。注意客戶端發(fā)出確認報文后不是立馬釋放TCP連接埠忘,而是要經過2MSL(最長報文段壽命的2倍時長)后才釋放TCP連接脾拆。而服務端一旦收到客戶端發(fā)出的確認報文就會立馬釋放TCP連接馒索,所以服務端結束TCP連接的時間要比客戶端早一些。
4. 常見面試題
- 為什么TCP連接的時候是3次名船?2次不可以嗎绰上?
- 因為需要考慮連接時丟包的問題,如果只握手2次渠驼,第二次握手時如果服務端發(fā)給客戶端的確認報文段丟失蜈块,此時服務端已經準備好了收發(fā)數(shù)(可以理解服務端已經連接成功)據(jù),而客戶端一直沒收到服務端的確認報文迷扇,所以客戶端就不知道服務端是否已經準備好了(可以理解為客戶端未連接成功)百揭,這種情況下客戶端不會給服務端發(fā)數(shù)據(jù),也會忽略服務端發(fā)過來的數(shù)據(jù)蜓席。如果是三次握手器一,即便發(fā)生丟包也不會有問題,比如如果第三次握手客戶端發(fā)的確認ack報文丟失瓮床,服務端在一段時間內沒有收到確認ack報文的話就會重新進行第二次握手盹舞,也就是服務端會重發(fā)SYN報文段产镐,客戶端收到重發(fā)的報文段后會再次給服務端發(fā)送確認ack報文隘庄。
- 為什么TCP連接的時候是3次,關閉的時候卻是4次癣亚?
- 因為只有在客戶端和服務端都沒有數(shù)據(jù)要發(fā)送的時候才能斷開TCP丑掺。而客戶端發(fā)出FIN報文時只能保證客戶端沒有數(shù)據(jù)發(fā)了,服務端還有沒有數(shù)據(jù)發(fā)客戶端是不知道的述雾。而服務端收到客戶端的FIN報文后只能先回復客戶端一個確認報文來告訴客戶端我服務端已經收到你的FIN報文了街州,但我服務端還有一些數(shù)據(jù)沒發(fā)完,等這些數(shù)據(jù)發(fā)完了服務端才能給客戶端發(fā)FIN報文(所以不能一次性將確認報文和FIN報文發(fā)給客戶端玻孟,就是這里多出來了一次)唆缴。
- 為什么客戶端發(fā)出第四次揮手的確認報文后要等2MSL的時間才能釋放TCP連接?
- 這里同樣是要考慮丟包的問題黍翎,如果第四次揮手的報文丟失面徽,服務端沒收到確認ack報文就會重發(fā)第三次揮手的報文,這樣報文一去一回最長時間就是2MSL匣掸,所以需要等這么長時間來確認服務端確實已經收到了趟紊。
作者:InsaneLoafer
鏈接:http://www.reibang.com/p/0ad0b864b949
來源:簡書
著作權歸作者所有。商業(yè)轉載請聯(lián)系作者獲得授權碰酝,非商業(yè)轉載請注明出處霎匈。