最近在惡補(bǔ)計(jì)算機(jī)網(wǎng)絡(luò)方面的知識(shí),之前對(duì)于TCP的三次握手和四次分手也是模模糊糊,對(duì)于其中的細(xì)節(jié)更是渾然不知,最近看了很多這方面的知識(shí)组去,也在系統(tǒng)的學(xué)習(xí)計(jì)算機(jī)網(wǎng)絡(luò),加深自己的CS功底步淹,就把看過(guò)的一些比較好的東西和自己的一些理解二次加工組織一下然后交流分享从隆,一起學(xué)習(xí)進(jìn)步,對(duì)了這個(gè)面試好像經(jīng)常問(wèn)到缭裆。
原文收錄在我的 GitHub博客 (https://github.com/jawil/blog) 键闺,喜歡的可以關(guān)注最新動(dòng)態(tài),大家一起多交流學(xué)習(xí)澈驼,共同進(jìn)步艾杏,以學(xué)習(xí)者的身份寫(xiě)博客,記錄點(diǎn)滴盅藻。
通俗理解:
但是為什么一定要進(jìn)行三次握手來(lái)保證連接是雙工的呢,一次不行么畅铭??jī)纱尾恍忻词鲜纾课覀兣e一個(gè)現(xiàn)實(shí)生活中兩個(gè)人進(jìn)行語(yǔ)言溝通的例子來(lái)模擬三次握手。
引用網(wǎng)上的一些通俗易懂的例子硕噩,雖然不太正確假残,后面會(huì)指出,但是不妨礙我們理解炉擅,大體就是這么個(gè)理解法辉懒。
第一次對(duì)話(huà):
老婆讓甲出去打醬油,半路碰到一個(gè)朋友乙谍失,甲問(wèn)了一句:哥們你吃飯了么眶俩?
結(jié)果乙?guī)е鷻C(jī)聽(tīng)歌呢,根本沒(méi)聽(tīng)到快鱼,沒(méi)反應(yīng)颠印。甲心里想:跟你說(shuō)話(huà)也沒(méi)個(gè)音,不跟你說(shuō)了抹竹,溝通失敗线罕。說(shuō)明乙接受不到甲傳過(guò)來(lái)的信息的情況下溝通肯定是失敗的。
如果乙聽(tīng)到了甲說(shuō)的話(huà)窃判,那么第一次對(duì)話(huà)成功钞楼,接下來(lái)進(jìn)行第二次對(duì)話(huà)。
第二次對(duì)話(huà):
乙聽(tīng)到了甲說(shuō)的話(huà)袄琳,但是他是老外询件,中文不好燃乍,不知道甲說(shuō)的啥意思也不知道怎樣回答,于是隨便回答了一句學(xué)過(guò)的中文 :我去廁所了雳殊。甲一聽(tīng)立刻笑噴了橘沥,“去廁所吃飯”?道不同不相為謀,離你遠(yuǎn)點(diǎn)吧夯秃,溝通失敗座咆。說(shuō)明乙無(wú)法做出正確應(yīng)答的情況下溝通失敗。
如果乙聽(tīng)到了甲的話(huà)仓洼,做出了正確的應(yīng)答介陶,并且還進(jìn)行了反問(wèn):我吃飯了,你呢色建?那么第二次握手成功哺呜。
通過(guò)前兩次對(duì)話(huà)證明了乙能夠聽(tīng)懂甲說(shuō)的話(huà),并且能做出正確的應(yīng)答箕戳。 接下來(lái)進(jìn)行第三次對(duì)話(huà)某残。
第三次對(duì)話(huà):
甲剛和乙打了個(gè)招呼,突然老婆喊他陵吸,“你個(gè)死鬼玻墅,打個(gè)醬油咋這么半天,看我回家咋收拾你”壮虫,甲是個(gè)妻管?chē)?yán)澳厢,聽(tīng)完嚇得二話(huà)不說(shuō)就跑回家了,把乙自己晾那了囚似。乙心想:這什么人啊剩拢,得,我也回家吧饶唤,溝通失敗徐伐。說(shuō)明甲無(wú)法做出應(yīng)答的情況下溝通失敗。
如果甲也做出了正確的應(yīng)答:我也吃了募狂。那么第三次對(duì)話(huà)成功呵晨,兩人已經(jīng)建立起了順暢的溝通渠道,接下來(lái)開(kāi)始持續(xù)的聊天熬尺。
通過(guò)第二次和第三次的對(duì)話(huà)證明了甲能夠聽(tīng)懂乙說(shuō)的話(huà)摸屠,并且能做出正確的應(yīng)答。
可見(jiàn)粱哼,兩個(gè)人進(jìn)行有效的語(yǔ)言溝通季二,這三次對(duì)話(huà)的過(guò)程是必須的。
為了保證服務(wù)端能收接受到客戶(hù)端的信息并能做出正確的應(yīng)答而進(jìn)行前兩次(第一次和第二次)握手,為了保證客戶(hù)端能夠接收到服務(wù)端的信息并能做出正確的應(yīng)答而進(jìn)行后兩次(第二次和第三次)握手胯舷。
這個(gè)例子舉得挺好的刻蚯。不過(guò)個(gè)人感覺(jué)為什么是三次而不是二次,不是因?yàn)闉榱俗C明甲能聽(tīng)懂乙并回應(yīng)(第二次乙能正確的響應(yīng)甲說(shuō)明倆人之間溝通已無(wú)障礙了)桑嘶,而是怕出現(xiàn)以下情況而浪費(fèi)感情炊汹。這個(gè)情景是這樣的(例子有點(diǎn)不實(shí)際意會(huì)就好):甲在路上跟乙打招呼,由于刮風(fēng)什么的這句活被吹跑了逃顶,然后甲又跟打了個(gè)招呼讨便,乙聽(tīng)到了并作出了回應(yīng)。此時(shí)不管是三次握手還是兩次握手兩個(gè)人都能愉快的溝通以政。0.1秒后倆人四次揮手告別了霸褒。此時(shí)被風(fēng)刮跑的那句話(huà)又傳到了乙的耳朵里,乙認(rèn)為甲又要跟他溝通盈蛮,所以做出了響應(yīng)的回應(yīng)废菱。(問(wèn)題出現(xiàn)了)假如采用2次握手,乙就認(rèn)定了甲要跟他溝通抖誉,于是就不停的等殊轴,浪費(fèi)感情√宦可如果是采用3次握手梳凛,乙等了一會(huì)后發(fā)現(xiàn)甲沒(méi)有回應(yīng)他就認(rèn)為甲走了然后自己也就走了!
這就很明白了梳杏,其實(shí)第三步是防止了乙的一直等待而浪費(fèi)自己的時(shí)間,而不是為了保證甲能夠正確回應(yīng)乙的信息淹接。十性。。后面的也會(huì)講到塑悼。
引用知乎上的別人引用的一個(gè)回答劲适,從另外一個(gè)角度闡釋?zhuān)?/p>
在Google Groups的TopLanguage中看到一帖討論TCP“三次握手”覺(jué)得很有意思。貼主提出“TCP建立連接為什么是三次握手厢蒜?”的問(wèn)題霞势,在眾多回復(fù)中,有一條回復(fù)寫(xiě)道:“這個(gè)問(wèn)題的本質(zhì)是, 信道不可靠, 但是通信雙發(fā)需要就某個(gè)問(wèn)題達(dá)成一致. 而要解決這個(gè)問(wèn)題, 無(wú)論你在消息中包含什么信息, 三次通信是理論上的最小值. 所以三次握手不是TCP本身的要求, 而是為了滿(mǎn)足"在不可靠信道上可靠地傳輸信息"這一需求所導(dǎo)致的. 請(qǐng)注意這里的本質(zhì)需求,信道不可靠, 數(shù)據(jù)傳輸要可靠. 三次達(dá)到了, 那后面你想接著握手也好, 發(fā)數(shù)據(jù)也好, 跟進(jìn)行可靠信息傳輸?shù)男枨缶蜎](méi)關(guān)系了. 因此,如果信道是可靠的, 即無(wú)論什么時(shí)候發(fā)出消息, 對(duì)方一定能收到, 或者你不關(guān)心是否要保證對(duì)方收到你的消息, 那就能像UDP那樣直接發(fā)送消息就可以了.”斑鸦。這可視為對(duì)“三次握手”目的的另一種解答思路愕贡。
上面的純屬大白話(huà)娛樂(lè)講解,可能還有偏差巷屿,例子可能有點(diǎn)不得體固以。在我們真正了解TCP的三次握手和四次分手之前,必須了解一些基本的概念,最后和這大白話(huà)例子對(duì)比結(jié)合一下理解憨琳,說(shuō)不定就會(huì)頓時(shí)融會(huì)貫通诫钓。
HTTP連接
HTTP協(xié)議即超文本傳送協(xié)議(Hypertext Transfer Protocol ),是Web聯(lián)網(wǎng)的基礎(chǔ)篙螟,也是手機(jī)聯(lián)網(wǎng)常用的協(xié)議之一菌湃,HTTP協(xié)議是建立在TCP協(xié)議之上的一種應(yīng)用劲蜻。
HTTP連接最顯著的特點(diǎn)是客戶(hù)端發(fā)送的每次請(qǐng)求都需要服務(wù)器回送響應(yīng)蒸矛,在請(qǐng)求結(jié)束后,會(huì)主動(dòng)釋放連接盔几。從建立連接到關(guān)閉連接的過(guò)程稱(chēng)為“一次連接”墅冷。
1)在HTTP 1.0中纯路,客戶(hù)端的每次請(qǐng)求都要求建立一次單獨(dú)的連接,在處理完本次請(qǐng)求后寞忿,就自動(dòng)釋放連接驰唬。
2)在HTTP 1.1中則可以在一次連接中處理多個(gè)請(qǐng)求,并且多個(gè)請(qǐng)求可以重疊進(jìn)行腔彰,不需要等待一個(gè)請(qǐng)求結(jié)束后再發(fā)送下一個(gè)請(qǐng)求叫编。
由于HTTP在每次請(qǐng)求結(jié)束后都會(huì)主動(dòng)釋放連接,因此HTTP連接是一種“短連接”霹抛,要保持客戶(hù)端程序的在線(xiàn)狀態(tài)搓逾,需要不斷地向服務(wù)器發(fā)起連接請(qǐng)求。通常 的做法是即時(shí)不需要獲得任何數(shù)據(jù)杯拐,客戶(hù)端也保持每隔一段固定的時(shí)間向服務(wù)器發(fā)送一次“保持連接”的請(qǐng)求霞篡,服務(wù)器在收到該請(qǐng)求后對(duì)客戶(hù)端進(jìn)行回復(fù),表明知道 客戶(hù)端“在線(xiàn)”端逼。若服務(wù)器長(zhǎng)時(shí)間無(wú)法收到客戶(hù)端的請(qǐng)求朗兵,則認(rèn)為客戶(hù)端“下線(xiàn)”,若客戶(hù)端長(zhǎng)時(shí)間無(wú)法收到服務(wù)器的回復(fù)顶滩,則認(rèn)為網(wǎng)絡(luò)已經(jīng)斷開(kāi)余掖。
SOCKET原理
套接字(socket)概念
套接字(socket)是通信的基石,是支持TCP/IP協(xié)議的網(wǎng)絡(luò)通信的基本操作單元礁鲁。它是網(wǎng)絡(luò)通信過(guò)程中端點(diǎn)的抽象表示盐欺,包含進(jìn)行網(wǎng)絡(luò)通信必須的五種信息:連接使用的協(xié)議,本地主機(jī)的IP地址仅醇,本地進(jìn)程的協(xié)議端口冗美,遠(yuǎn)地主機(jī)的IP地址,遠(yuǎn)地進(jìn)程的協(xié)議端口析二。
應(yīng)用層通過(guò)傳輸層進(jìn)行數(shù)據(jù)通信時(shí)墩衙,TCP會(huì)遇到同時(shí)為多個(gè)應(yīng)用程序進(jìn)程提供并發(fā)服務(wù)的問(wèn)題。多個(gè)TCP連接或多個(gè)應(yīng)用程序進(jìn)程可能需要通過(guò)同一個(gè) TCP協(xié)議端口傳輸數(shù)據(jù)。為了區(qū)別不同的應(yīng)用程序進(jìn)程和連接漆改,許多計(jì)算機(jī)操作系統(tǒng)為應(yīng)用程序與TCP/IP協(xié)議交互提供了套接字(Socket)接口心铃。應(yīng) 用層可以和傳輸層通過(guò)Socket接口,區(qū)分來(lái)自不同應(yīng)用程序進(jìn)程或網(wǎng)絡(luò)連接的通信挫剑,實(shí)現(xiàn)數(shù)據(jù)傳輸?shù)牟l(fā)服務(wù)去扣。
建立socket連接
建立Socket連接至少需要一對(duì)套接字,其中一個(gè)運(yùn)行于客戶(hù)端樊破,稱(chēng)為ClientSocket 愉棱,另一個(gè)運(yùn)行于服務(wù)器端,稱(chēng)為ServerSocket 哲戚。
套接字之間的連接過(guò)程分為三個(gè)步驟:服務(wù)器監(jiān)聽(tīng)奔滑,客戶(hù)端請(qǐng)求,連接確認(rèn)顺少。
服務(wù)器監(jiān)聽(tīng):服務(wù)器端套接字并不定位具體的客戶(hù)端套接字朋其,而是處于等待連接的狀態(tài),實(shí)時(shí)監(jiān)控網(wǎng)絡(luò)狀態(tài)脆炎,等待客戶(hù)端的連接請(qǐng)求梅猿。
客戶(hù)端請(qǐng)求:指客戶(hù)端的套接字提出連接請(qǐng)求,要連接的目標(biāo)是服務(wù)器端的套接字秒裕。為此袱蚓,客戶(hù)端的套接字必須首先描述它要連接的服務(wù)器的套接字,指出服務(wù)器端套接字的地址和端口號(hào)几蜻,然后就向服務(wù)器端套接字提出連接請(qǐng)求喇潘。
連接確認(rèn):當(dāng)服務(wù)器端套接字監(jiān)聽(tīng)到或者說(shuō)接收到客戶(hù)端套接字的連接請(qǐng)求時(shí),就響應(yīng)客戶(hù)端套接字的請(qǐng)求梭稚,建立一個(gè)新的線(xiàn)程颖低,把服務(wù)器端套接字的描述發(fā) 給客戶(hù)端,一旦客戶(hù)端確認(rèn)了此描述哨毁,雙方就正式建立連接。而服務(wù)器端套接字繼續(xù)處于監(jiān)聽(tīng)狀態(tài)源武,繼續(xù)接收其他客戶(hù)端套接字的連接請(qǐng)求扼褪。
SOCKET連接與TCP連接
創(chuàng)建Socket連接時(shí),可以指定使用的傳輸層協(xié)議粱栖,Socket可以支持不同的傳輸層協(xié)議(TCP或UDP)话浇,當(dāng)使用TCP協(xié)議進(jìn)行連接時(shí),該Socket連接就是一個(gè)TCP連接闹究。
Socket連接與HTTP連接
由于通常情況下Socket連接就是TCP連接幔崖,因此Socket連接一旦建立,通信雙方即可開(kāi)始相互發(fā)送數(shù)據(jù)內(nèi)容,直到雙方連接斷開(kāi)赏寇。但在實(shí)際網(wǎng) 絡(luò)應(yīng)用中吉嫩,客戶(hù)端到服務(wù)器之間的通信往往需要穿越多個(gè)中間節(jié)點(diǎn),例如路由器嗅定、網(wǎng)關(guān)自娩、防火墻等,大部分防火墻默認(rèn)會(huì)關(guān)閉長(zhǎng)時(shí)間處于非活躍狀態(tài)的連接而導(dǎo)致 Socket 連接斷連渠退,因此需要通過(guò)輪詢(xún)告訴網(wǎng)絡(luò)忙迁,該連接處于活躍狀態(tài)。
而HTTP連接使用的是“請(qǐng)求—響應(yīng)”的方式碎乃,不僅在請(qǐng)求時(shí)需要先建立連接姊扔,而且需要客戶(hù)端向服務(wù)器發(fā)出請(qǐng)求后,服務(wù)器端才能回復(fù)數(shù)據(jù)梅誓。
很多情況下恰梢,需要服務(wù)器端主動(dòng)向客戶(hù)端推送數(shù)據(jù),保持客戶(hù)端與服務(wù)器數(shù)據(jù)的實(shí)時(shí)與同步证九。此時(shí)若雙方建立的是Socket連接删豺,服務(wù)器就可以直接將數(shù) 據(jù)傳送給客戶(hù)端;若雙方建立的是HTTP連接愧怜,則服務(wù)器需要等到客戶(hù)端發(fā)送一次請(qǐng)求后才能將數(shù)據(jù)傳回給客戶(hù)端呀页,因此,客戶(hù)端定時(shí)向服務(wù)器端發(fā)送連接請(qǐng)求拥坛, 不僅可以保持在線(xiàn)蓬蝶,同時(shí)也是在“詢(xún)問(wèn)”服務(wù)器是否有新的數(shù)據(jù),如果有就將數(shù)據(jù)傳給客戶(hù)端猜惋。TCP(Transmission Control Protocol) 傳輸控制協(xié)議
TCP是主機(jī)對(duì)主機(jī)層的傳輸控制協(xié)議丸氛,提供可靠的連接服務(wù),采用三次握手確認(rèn)建立一個(gè)連接:
位碼即tcp標(biāo)志位,有6種標(biāo)示:SYN(synchronous建立聯(lián)機(jī)) ACK(acknowledgement 確認(rèn)) PSH(push傳送) FIN(finish結(jié)束) RST(reset重置) URG(urgent緊急)
Sequence number(順序號(hào)碼) Acknowledge number(確認(rèn)號(hào)碼)
TCP是什么著摔?
TCP(Transmission Control Protocol 傳輸控制協(xié)議)是一種面向連接的缓窜、可靠的、基于字節(jié)流的傳輸層通信協(xié)議谍咆。
具體的關(guān)于TCP是什么禾锤,我不打算詳細(xì)的說(shuō)了;當(dāng)你看到這篇文章時(shí)摹察,我想你也知道TCP的概念了恩掷,想要更深入的了解TCP的工作,我們就繼續(xù)供嚎。它只是一個(gè)超級(jí)麻煩的協(xié)議黄娘,而它又是互聯(lián)網(wǎng)的基礎(chǔ)峭状,也是每個(gè)程序員必備的基本功。首先來(lái)看看OSI的七層模型:
我們需要知道TCP工作在網(wǎng)絡(luò)OSI的七層模型中的第四層——Transport層逼争,IP在第三層——Network層优床,ARP在第二層——Data Link層;在第二層上的數(shù)據(jù)氮凝,我們把它叫Frame羔巢,在第三層上的數(shù)據(jù)叫Packet,第四層的數(shù)據(jù)叫Segment罩阵。 同時(shí)竿秆,我們需要簡(jiǎn)單的知道,數(shù)據(jù)從應(yīng)用層發(fā)下來(lái)稿壁,會(huì)在每一層都會(huì)加上頭部信息幽钢,進(jìn)行封裝,然后再發(fā)送到數(shù)據(jù)接收端傅是。這個(gè)基本的流程你需要知道匪燕,就是每個(gè)數(shù)據(jù)都會(huì)經(jīng)過(guò)數(shù)據(jù)的封裝和解封裝的過(guò)程。 在OSI七層模型中喧笔,每一層的作用和對(duì)應(yīng)的協(xié)議如下:
TCP是一個(gè)協(xié)議帽驯,那這個(gè)協(xié)議是如何定義的,它的數(shù)據(jù)格式是什么樣子的呢书闸?要進(jìn)行更深層次的剖析尼变,就需要了解,甚至是熟記TCP協(xié)議中每個(gè)字段的含義浆劲。哦嫌术,來(lái)吧。
TCP頭部
其中 ACK SYN 序號(hào) 這三個(gè)部分在以下會(huì)用到牌借,它們的介紹也在下面度气。
上面就是TCP協(xié)議頭部的格式,由于它太重要了膨报,是理解其它內(nèi)容的基礎(chǔ)磷籍,下面就將每個(gè)字段的信息都詳細(xì)的說(shuō)明一下。
Source Port和Destination Port:分別占用16位现柠,表示源端口號(hào)和目的端口號(hào)院领;用于區(qū)別主機(jī)中的不同進(jìn)程,而IP地址是用來(lái)區(qū)分不同的主機(jī)的晒旅,源端口號(hào)和目的端口號(hào)配合上IP首部中的源IP地址和目的IP地址就能唯一的確定一個(gè)TCP連接栅盲;
Sequence Number:用來(lái)標(biāo)識(shí)從TCP發(fā)端向TCP收端發(fā)送的數(shù)據(jù)字節(jié)流汪诉,它表示在這個(gè)報(bào)文段中的的第一個(gè)數(shù)據(jù)字節(jié)在數(shù)據(jù)流中的序號(hào)废恋;主要用來(lái)解決網(wǎng)絡(luò)報(bào)亂序的問(wèn)題谈秫;
Acknowledgment Number:32位確認(rèn)序列號(hào)包含發(fā)送確認(rèn)的一端所期望收到的下一個(gè)序號(hào),因此鱼鼓,確認(rèn)序號(hào)應(yīng)當(dāng)是上次已成功收到數(shù)據(jù)字節(jié)序號(hào)加1拟烫。不過(guò),只有當(dāng)標(biāo)志位中的ACK標(biāo)志(下面介紹)為1時(shí)該確認(rèn)序列號(hào)的字段才有效迄本。主要用來(lái)解決不丟包的問(wèn)題硕淑;
Offset:給出首部中32 bit字的數(shù)目,需要這個(gè)值是因?yàn)槿芜x字段的長(zhǎng)度是可變的嘉赎。這個(gè)字段占4bit(最多能表示15個(gè)32bit的的字置媳,即4*15=60個(gè)字節(jié)的首部長(zhǎng)度),因此TCP最多有60字節(jié)的首部公条。然而拇囊,沒(méi)有任選字段,正常的長(zhǎng)度是20字節(jié)靶橱;
TCP Flags:TCP首部中有6個(gè)標(biāo)志比特寥袭,它們中的多個(gè)可同時(shí)被設(shè)置為1,主要是用于操控TCP的狀態(tài)機(jī)的关霸,依次為URG传黄,ACK,PSH队寇,RST膘掰,SYN,F(xiàn)IN英上。每個(gè)標(biāo)志位的意思如下:
URG:此標(biāo)志表示TCP包的緊急指針域(后面馬上就要說(shuō)到)有效炭序,用來(lái)保證TCP連接不被中斷,并且督促中間層設(shè)備要盡快處理這些數(shù)據(jù)苍日;
ACK:此標(biāo)志表示應(yīng)答域有效惭聂,就是說(shuō)前面所說(shuō)的TCP應(yīng)答號(hào)將會(huì)包含在TCP數(shù)據(jù)包中;有兩個(gè)取值:0和1相恃,為1的時(shí)候表示應(yīng)答域有效辜纲,反之為0;
PSH:這個(gè)標(biāo)志位表示Push操作拦耐。所謂Push操作就是指在數(shù)據(jù)包到達(dá)接收端以后耕腾,立即傳送給應(yīng)用程序,而不是在緩沖區(qū)中排隊(duì)杀糯;
RST:這個(gè)標(biāo)志表示連接復(fù)位請(qǐng)求扫俺。用來(lái)復(fù)位那些產(chǎn)生錯(cuò)誤的連接,也被用來(lái)拒絕錯(cuò)誤和非法的數(shù)據(jù)包固翰;
SYN:表示同步序號(hào)狼纬,用來(lái)建立連接羹呵。SYN標(biāo)志位和ACK標(biāo)志位搭配使用,當(dāng)連接請(qǐng)求的時(shí)候疗琉,SYN=1冈欢,ACK=0;連接被響應(yīng)的時(shí)候盈简,SYN=1凑耻,ACK=1;這個(gè)標(biāo)志的數(shù)據(jù)包經(jīng)常被用來(lái)進(jìn)行端口掃描柠贤。掃描者發(fā)送一個(gè)只有SYN的數(shù)據(jù)包香浩,如果對(duì)方主機(jī)響應(yīng)了一個(gè)數(shù)據(jù)包回來(lái) ,就表明這臺(tái)主機(jī)存在這個(gè)端口臼勉;但是由于這種掃描方式只是進(jìn)行TCP三次握手的第一次握手弃衍,因此這種掃描的成功表示被掃描的機(jī)器不很安全,一臺(tái)安全的主機(jī)將會(huì)強(qiáng)制要求一個(gè)連接嚴(yán)格的進(jìn)行TCP的三次握手坚俗;
FIN: 表示發(fā)送端已經(jīng)達(dá)到數(shù)據(jù)末尾镜盯,也就是說(shuō)雙方的數(shù)據(jù)傳送完成,沒(méi)有數(shù)據(jù)可以傳送了猖败,發(fā)送FIN標(biāo)志位的TCP數(shù)據(jù)包后速缆,連接將被斷開(kāi)。這個(gè)標(biāo)志的數(shù)據(jù)包也經(jīng)常被用于進(jìn)行端口掃描恩闻。
- Window:窗口大小艺糜,也就是有名的滑動(dòng)窗口,用來(lái)進(jìn)行流量控制幢尚;這是一個(gè)復(fù)雜的問(wèn)題破停,這篇博文中并不會(huì)進(jìn)行總結(jié)的;
暫時(shí)需要的信息有:
ACK : TCP協(xié)議規(guī)定尉剩,只有ACK=1時(shí)有效真慢,也規(guī)定連接建立后所有發(fā)送的報(bào)文的ACK必須為1
SYN(SYNchronization) : 在連接建立時(shí)用來(lái)同步序號(hào)。當(dāng)SYN=1而ACK=0時(shí)理茎,表明這是一個(gè)連接請(qǐng)求報(bào)文黑界。對(duì)方若同意建立連接,則應(yīng)在響應(yīng)報(bào)文中使SYN=1和ACK=1. 因此, SYN置1就表示這是一個(gè)連接請(qǐng)求或連接接受報(bào)文皂林。
FIN (finis)即完朗鸠,終結(jié)的意思, 用來(lái)釋放一個(gè)連接础倍。當(dāng) FIN = 1 時(shí)烛占,表明此報(bào)文段的發(fā)送方的數(shù)據(jù)已經(jīng)發(fā)送完畢,并要求釋放連接沟启。
三次握手的過(guò)程:
多么清晰的一張圖忆家,當(dāng)然了呀癣,也不是我畫(huà)的,我也只是引用過(guò)來(lái)說(shuō)明問(wèn)題了弦赖。
- 第一次握手:建立連接∑直妫客戶(hù)端發(fā)送連接請(qǐng)求報(bào)文段蹬竖,將SYN位置為1,Sequence Number為x流酬;然后币厕,客戶(hù)端進(jìn)入SYN_SEND狀態(tài),等待服務(wù)器的確認(rèn)芽腾;
- 第二次握手:服務(wù)器收到SYN報(bào)文段旦装。服務(wù)器收到客戶(hù)端的SYN報(bào)文段,需要對(duì)這個(gè)SYN報(bào)文段進(jìn)行確認(rèn)摊滔,設(shè)置Acknowledgment Number為x+1(Sequence Number+1)阴绢;同時(shí),自己自己還要發(fā)送SYN請(qǐng)求信息艰躺,將SYN位置為1呻袭,Sequence Number為y;服務(wù)器端將上述所有信息放到一個(gè)報(bào)文段(即SYN+ACK報(bào)文段)中腺兴,一并發(fā)送給客戶(hù)端左电,此時(shí)服務(wù)器進(jìn)入SYN_RECV狀態(tài);
- 第三次握手:客戶(hù)端收到服務(wù)器的SYN+ACK報(bào)文段页响。然后將Acknowledgment Number設(shè)置為y+1篓足,向服務(wù)器發(fā)送ACK報(bào)文段,這個(gè)報(bào)文段發(fā)送完畢以后闰蚕,客戶(hù)端和服務(wù)器端都進(jìn)入ESTABLISHED狀態(tài)栈拖,完成TCP三次握手。
完成了三次握手没陡,客戶(hù)端和服務(wù)器端就可以開(kāi)始傳送數(shù)據(jù)辱魁。以上就是TCP三次握手的總體介紹。
那四次分手呢诗鸭?
當(dāng)客戶(hù)端和服務(wù)器通過(guò)三次握手建立了TCP連接以后染簇,當(dāng)數(shù)據(jù)傳送完畢,肯定是要斷開(kāi)TCP連接的啊强岸。那對(duì)于TCP的斷開(kāi)連接锻弓,這里就有了神秘的“四次分手”。
- 第一次分手:主機(jī)1(可以使客戶(hù)端蝌箍,也可以是服務(wù)器端)青灼,設(shè)置Sequence Number和Acknowledgment Number暴心,向主機(jī)2發(fā)送一個(gè)FIN報(bào)文段;此時(shí)杂拨,主機(jī)1進(jìn)入FIN_WAIT_1狀態(tài)专普;這表示主機(jī)1沒(méi)有數(shù)據(jù)要發(fā)送給主機(jī)2了;
- 第二次分手:主機(jī)2收到了主機(jī)1發(fā)送的FIN報(bào)文段弹沽,向主機(jī)1回一個(gè)ACK報(bào)文段檀夹,Acknowledgment Number為Sequence Number加1;主機(jī)1進(jìn)入FIN_WAIT_2狀態(tài)策橘;主機(jī)2告訴主機(jī)1炸渡,我“同意”你的關(guān)閉請(qǐng)求;
- 第三次分手:主機(jī)2向主機(jī)1發(fā)送FIN報(bào)文段丽已,請(qǐng)求關(guān)閉連接蚌堵,同時(shí)主機(jī)2進(jìn)入LAST_ACK狀態(tài);
- 第四次分手:主機(jī)1收到主機(jī)2發(fā)送的FIN報(bào)文段沛婴,向主機(jī)2發(fā)送ACK報(bào)文段吼畏,然后主機(jī)1進(jìn)入TIME_WAIT狀態(tài);主機(jī)2收到主機(jī)1的ACK報(bào)文段以后嘁灯,就關(guān)閉連接宫仗;此時(shí),主機(jī)1等待2MSL后依然沒(méi)有收到回復(fù)旁仿,則證明Server端已正常關(guān)閉藕夫,那好,主機(jī)1也可以關(guān)閉連接了枯冈。
至此毅贮,TCP的四次分手就這么愉快的完成了。當(dāng)你看到這里尘奏,你的腦子里會(huì)有很多的疑問(wèn)滩褥,很多的不懂,感覺(jué)很凌亂炫加;沒(méi)事瑰煎,我們繼續(xù)總結(jié)。
為什么要三次握手
在謝希仁著《計(jì)算機(jī)網(wǎng)絡(luò)》第四版中講“三次握手”的目的是“為了防止已失效的連接請(qǐng)求報(bào)文段突然又傳送到了服務(wù)端俗孝,因而產(chǎn)生錯(cuò)誤”酒甸。在另一部經(jīng)典的《計(jì)算機(jī)網(wǎng)絡(luò)》一書(shū)中講“三次握手”的目的是為了解決“網(wǎng)絡(luò)中存在延遲的重復(fù)分組”的問(wèn)題。
在謝希仁著《計(jì)算機(jī)網(wǎng)絡(luò)》書(shū)中同時(shí)舉了一個(gè)例子赋铝,如下:
“已失效的連接請(qǐng)求報(bào)文段”的產(chǎn)生在這樣一種情況下:client發(fā)出的第一個(gè)連接請(qǐng)求報(bào)文段并沒(méi)有丟失插勤,而是在某個(gè)網(wǎng)絡(luò)結(jié)點(diǎn)長(zhǎng)時(shí)間的滯留了,以致延誤到連接釋放以后的某個(gè)時(shí)間才到達(dá)server。本來(lái)這是一個(gè)早已失效的報(bào)文段农尖。但server收到此失效的連接請(qǐng)求報(bào)文段后析恋,就誤認(rèn)為是client再次發(fā)出的一個(gè)新的連接請(qǐng)求。于是就向client發(fā)出確認(rèn)報(bào)文段盛卡,同意建立連接助隧。假設(shè)不采用“三次握手”,那么只要server發(fā)出確認(rèn)滑沧,新的連接就建立了并村。由于現(xiàn)在client并沒(méi)有發(fā)出建立連接的請(qǐng)求,因此不會(huì)理睬server的確認(rèn)嚎货,也不會(huì)向server發(fā)送數(shù)據(jù)。但server卻以為新的運(yùn)輸連接已經(jīng)建立蔫浆,并一直等待client發(fā)來(lái)數(shù)據(jù)殖属。這樣,server的很多資源就白白浪費(fèi)掉了瓦盛。采用“三次握手”的辦法可以防止上述現(xiàn)象發(fā)生洗显。例如剛才那種情況,client不會(huì)向server的確認(rèn)發(fā)出確認(rèn)原环。server由于收不到確認(rèn)挠唆,就知道client并沒(méi)有要求建立連接≈雎穑”
這就很明白了玄组,防止了服務(wù)器端的一直等待而浪費(fèi)資源。
為什么要四次分手
那四次分手又是為何呢谒麦?TCP協(xié)議是一種面向連接的俄讹、可靠的、基于字節(jié)流的運(yùn)輸層通信協(xié)議绕德。TCP是全雙工模式患膛,這就意味著,當(dāng)主機(jī)1發(fā)出FIN報(bào)文段時(shí)耻蛇,只是表示主機(jī)1已經(jīng)沒(méi)有數(shù)據(jù)要發(fā)送了踪蹬,主機(jī)1告訴主機(jī)2,它的數(shù)據(jù)已經(jīng)全部發(fā)送完畢了臣咖;但是跃捣,這個(gè)時(shí)候主機(jī)1還是可以接受來(lái)自主機(jī)2的數(shù)據(jù);當(dāng)主機(jī)2返回ACK報(bào)文段時(shí)夺蛇,表示它已經(jīng)知道主機(jī)1沒(méi)有數(shù)據(jù)發(fā)送了枝缔,但是主機(jī)2還是可以發(fā)送數(shù)據(jù)到主機(jī)1的;當(dāng)主機(jī)2也發(fā)送了FIN報(bào)文段時(shí),這個(gè)時(shí)候就表示主機(jī)2也沒(méi)有數(shù)據(jù)要發(fā)送了愿卸,就會(huì)告訴主機(jī)1灵临,我也沒(méi)有數(shù)據(jù)要發(fā)送了,之后彼此就會(huì)愉快的中斷這次TCP連接趴荸。如果要正確的理解四次分手的原理儒溉,就需要了解四次分手過(guò)程中的狀態(tài)變化。
- FIN_WAIT_1: 這個(gè)狀態(tài)要好好解釋一下发钝,其實(shí)FIN_WAIT_1和FIN_WAIT_2狀態(tài)的真正含義都是表示等待對(duì)方的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)對(duì)方回應(yīng)ACK報(bào)文后孵淘,則進(jìn)入到FIN_WAIT_2狀態(tài)蒲障,當(dāng)然在實(shí)際的正常情況下,無(wú)論對(duì)方何種情況下瘫证,都應(yīng)該馬上回應(yīng)ACK報(bào)文揉阎,所以FIN_WAIT_1狀態(tài)一般是比較難見(jiàn)到的,而FIN_WAIT_2狀態(tài)還有時(shí)常潮嘲疲可以用netstat看到毙籽。(主動(dòng)方)
- FIN_WAIT_2:上面已經(jīng)詳細(xì)解釋了這種狀態(tài),實(shí)際上FIN_WAIT_2狀態(tài)下的SOCKET毡庆,表示半連接坑赡,也即有一方要求close連接,但另外還告訴對(duì)方么抗,我暫時(shí)還有點(diǎn)數(shù)據(jù)需要傳送給你(ACK信息)垮衷,稍后再關(guān)閉連接。(主動(dòng)方)
- CLOSE_WAIT:這種狀態(tài)的含義其實(shí)是表示在等待關(guān)閉乖坠。怎么理解呢搀突?當(dāng)對(duì)方close一個(gè)SOCKET后發(fā)送FIN報(bào)文給自己,你系統(tǒng)毫無(wú)疑問(wèn)地會(huì)回應(yīng)一個(gè)ACK報(bào)文給對(duì)方熊泵,此時(shí)則進(jìn)入到CLOSE_WAIT狀態(tài)仰迁。接下來(lái)呢,實(shí)際上你真正需要考慮的事情是察看你是否還有數(shù)據(jù)發(fā)送給對(duì)方顽分,如果沒(méi)有的話(huà)徐许,那么你也就可以 close這個(gè)SOCKET,發(fā)送FIN報(bào)文給對(duì)方卒蘸,也即關(guān)閉連接雌隅。所以你在CLOSE_WAIT狀態(tài)下翻默,需要完成的事情是等待你去關(guān)閉連接。(被動(dòng)方)
- LAST_ACK: 這個(gè)狀態(tài)還是比較容易好理解的恰起,它是被動(dòng)關(guān)閉一方在發(fā)送FIN報(bào)文后修械,最后等待對(duì)方的ACK報(bào)文。當(dāng)收到ACK報(bào)文后检盼,也即可以進(jìn)入到CLOSED可用狀態(tài)了肯污。(被動(dòng)方)
- TIME_WAIT: 表示收到了對(duì)方的FIN報(bào)文,并發(fā)送出了ACK報(bào)文吨枉,就等2MSL后即可回到CLOSED可用狀態(tài)了蹦渣。如果FINWAIT1狀態(tài)下,收到了對(duì)方同時(shí)帶FIN標(biāo)志和ACK標(biāo)志的報(bào)文時(shí)貌亭,可以直接進(jìn)入到TIME_WAIT狀態(tài)柬唯,而無(wú)須經(jīng)過(guò)FIN_WAIT_2狀態(tài)。(主動(dòng)方)
- CLOSED: 表示連接中斷圃庭。
實(shí)例:
TCP的作用是流量控制锄奢,主要是控制數(shù)據(jù)流的傳輸。下面以瀏覽網(wǎng)頁(yè)為例冤议,根據(jù)自身理解來(lái)解釋一下這個(gè)過(guò)程斟薇。(注:第二個(gè)ack屬于代碼段ack位)
握手過(guò)程中傳送的包里不包含數(shù)據(jù)师坎,三次握手完畢后恕酸,客戶(hù)端與服務(wù)器才正式開(kāi)始傳送數(shù)據(jù)。
第一次握手:客戶(hù)端發(fā)送syn包(syn=j)到服務(wù)器胯陋,并進(jìn)入SYN_SEND狀態(tài)蕊温,等待服務(wù)器確認(rèn);
第二次握手:服務(wù)器收到syn包遏乔,必須確認(rèn)客戶(hù)的SYN(ack=j+1)义矛,同時(shí)自己也發(fā)送一個(gè)SYN包(syn=k),即SYN+ACK包盟萨,此時(shí)服務(wù)器進(jìn)入SYN_RECV狀態(tài)凉翻;
第三次握手:客戶(hù)端收到服務(wù)器的SYN+ACK包,向服務(wù)器發(fā)送確認(rèn)包ACK(ack=k+1)捻激,此包發(fā)送完畢制轰,客戶(hù)端和服務(wù)器進(jìn)入ESTABLISHED狀態(tài),完成三次握手胞谭。
握手過(guò)程中傳送的包里不包含數(shù)據(jù)垃杖,三次握手完畢后,客戶(hù)端與服務(wù)器才正式開(kāi)始傳送數(shù)據(jù)丈屹。理想狀態(tài)下调俘,TCP連接一旦建立,在通信雙方中的任何一方主 動(dòng)關(guān)閉連接之前,TCP 連接都將被一直保持下去彩库。斷開(kāi)連接時(shí)服務(wù)器和客戶(hù)端均可以主動(dòng)發(fā)起斷開(kāi)TCP連接的請(qǐng)求肤无,斷開(kāi)過(guò)程需要經(jīng)過(guò)“四次握手”(過(guò)程就不細(xì)寫(xiě)了,就是服務(wù)器和客 戶(hù)端交互侧巨,最終確定斷開(kāi))
對(duì)應(yīng)的實(shí)例
IP 192.168.1.116.3337 > 192.168.1.123.7788: S 3626544836:3626544836
IP 192.168.1.123.7788 > 192.168.1.116.3337: S 1739326486:1739326486 ack 3626544837
IP 192.168.1.116.3337 > 192.168.1.123.7788: ack 1739326487,ack 1
第一次握手:192.168.1.116發(fā)送位碼syn=1,隨機(jī)產(chǎn)生seq number=3626544836的數(shù)據(jù)包到192.168.1.123,192.168.1.123由SYN=1知道192.168.1.116要求建立聯(lián)機(jī);
第二次握手:192.168.1.123收到請(qǐng)求后要確認(rèn)聯(lián)機(jī)信息舅锄,向192.168.1.116發(fā)送ack number=3626544837,syn=1,ack=1,隨機(jī)產(chǎn)生seq=1739326486的包;
第三次握手:192.168.1.116收到后檢查ack number是否正確,即第一次發(fā)送的seq number+1,以及位碼ack是否為1司忱,若正確皇忿,192.168.1.116會(huì)再發(fā)送ack number=1739326487,ack=1,192.168.1.123收到后確認(rèn)seq=seq+1,ack=1則連接建立成功坦仍。
我想你應(yīng)該懂了
總結(jié)到這里鳍烁,也該結(jié)束了,但是對(duì)于TCP的學(xué)習(xí)遠(yuǎn)還沒(méi)有結(jié)束繁扎。TCP是一個(gè)非常復(fù)雜的協(xié)議幔荒,這里稍微總結(jié)了一下TCP的連接與斷開(kāi)連接是發(fā)生的事情,其中還有很多的“坑”梳玫,讓我們后續(xù)有時(shí)間再繼續(xù)填吧爹梁。好了,完畢提澎!