摘要:原理套接字概念套接字是通信的基石,是支持協(xié)議的網(wǎng)絡(luò)通信的基本操作單元。建立連接建立連接至少需要一對(duì)套接字,其中一個(gè)運(yùn)行于客戶端,稱為,另一個(gè)運(yùn)行于服務(wù)器端,稱為。而服務(wù)器端套接字繼續(xù)處于監(jiān)聽狀態(tài),繼續(xù)接收其他客戶端套接字的連接請(qǐng)求。
最近在惡補(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í)者的身份寫博客,記錄點(diǎn)滴。
通俗理解:但是為什么一定要進(jìn)行三次握手來(lái)保證連接是雙工的呢,一次不行么??jī)纱尾恍忻矗课覀兣e一個(gè)現(xiàn)實(shí)生活中兩個(gè)人進(jìn)行語(yǔ)言溝通的例子來(lái)模擬三次握手。
引用網(wǎng)上的一些通俗易懂的例子,雖然不太正確,后面會(huì)指出,但是不妨礙我們理解,大體就是這么個(gè)理解法。
第一次對(duì)話:老婆讓甲出去打醬油,半路碰到一個(gè)朋友乙,甲問(wèn)了一句:哥們你吃飯了么?
結(jié)果乙?guī)е鷻C(jī)聽歌呢,根本沒(méi)聽到,沒(méi)反應(yīng)。甲心里想:跟你說(shuō)話也沒(méi)個(gè)音,不跟你說(shuō)了,溝通失敗。說(shuō)明乙接受不到甲傳過(guò)來(lái)的信息的情況下溝通肯定是失敗的。
如果乙聽到了甲說(shuō)的話,那么第一次對(duì)話成功,接下來(lái)進(jìn)行第二次對(duì)話。
第二次對(duì)話:乙聽到了甲說(shuō)的話,但是他是老外,中文不好,不知道甲說(shuō)的啥意思也不知道怎樣回答,于是隨便回答了一句學(xué)過(guò)的中文 :我去廁所了。甲一聽立刻笑噴了,“去廁所吃飯”?道不同不相為謀,離你遠(yuǎn)點(diǎn)吧,溝通失敗。說(shuō)明乙無(wú)法做出正確應(yīng)答的情況下溝通失敗。
如果乙聽到了甲的話,做出了正確的應(yīng)答,并且還進(jìn)行了反問(wèn):我吃飯了,你呢?那么第二次握手成功。
通過(guò)前兩次對(duì)話證明了乙能夠聽懂甲說(shuō)的話,并且能做出正確的應(yīng)答。 接下來(lái)進(jìn)行第三次對(duì)話。
第三次對(duì)話:甲剛和乙打了個(gè)招呼,突然老婆喊他,“你個(gè)死鬼,打個(gè)醬油咋這么半天,看我回家咋收拾你”,甲是個(gè)妻管嚴(yán),聽完嚇得二話不說(shuō)就跑回家了,把乙自己晾那了。乙心想:這什么人啊,得,我也回家吧,溝通失敗。說(shuō)明甲無(wú)法做出應(yīng)答的情況下溝通失敗。
如果甲也做出了正確的應(yīng)答:我也吃了。那么第三次對(duì)話成功,兩人已經(jīng)建立起了順暢的溝通渠道,接下來(lái)開始持續(xù)的聊天。
通過(guò)第二次和第三次的對(duì)話證明了甲能夠聽懂乙說(shuō)的話,并且能做出正確的應(yīng)答。
可見,兩個(gè)人進(jìn)行有效的語(yǔ)言溝通,這三次對(duì)話的過(guò)程是必須的。
為了保證服務(wù)端能收接受到客戶端的信息并能做出正確的應(yīng)答而進(jìn)行前兩次(第一次和第二次)握手,為了保證客戶端能夠接收到服務(wù)端的信息并能做出正確的應(yīng)答而進(jìn)行后兩次(第二次和第三次)握手。
這個(gè)例子舉得挺好的。不過(guò)個(gè)人感覺(jué)為什么是三次而不是二次,不是因?yàn)闉榱俗C明甲能聽懂乙并回應(yīng)(第二次乙能正確的響應(yīng)甲說(shuō)明倆人之間溝通已無(wú)障礙了),而是怕出現(xiàn)以下情況而浪費(fèi)感情。這個(gè)情景是這樣的(例子有點(diǎn)不實(shí)際意會(huì)就好):甲在路上跟乙打招呼,由于刮風(fēng)什么的這句活被吹跑了,然后甲又跟打了個(gè)招呼,乙聽到了并作出了回應(yīng)。此時(shí)不管是三次握手還是兩次握手兩個(gè)人都能愉快的溝通。0.1秒后倆人四次揮手告別了。此時(shí)被風(fēng)刮跑的那句話又傳到了乙的耳朵里,乙認(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è)角度闡釋:
在Google Groups的TopLanguage中看到一帖討論TCP“三次握手”覺(jué)得很有意思。貼主提出“TCP建立連接為什么是三次握手?”的問(wèn)題,在眾多回復(fù)中,有一條回復(fù)寫道:“這個(gè)問(wèn)題的本質(zhì)是, 信道不可靠, 但是通信雙發(fā)需要就某個(gè)問(wèn)題達(dá)成一致. 而要解決這個(gè)問(wèn)題, 無(wú)論你在消息中包含什么信息, 三次通信是理論上的最小值. 所以三次握手不是TCP本身的要求, 而是為了滿足"在不可靠信道上可靠地傳輸信息"這一需求所導(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ì)“三次握手”目的的另一種解答思路。
上面的純屬大白話娛樂(lè)講解,可能還有偏差,例子可能有點(diǎn)不得體。在我們真正了解TCP的三次握手和四次分手之前,必須了解一些基本的概念,最后和這大白話例子對(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)是客戶端發(fā)送的每次請(qǐng)求都需要服務(wù)器回送響應(yīng),在請(qǐng)求結(jié)束后,會(huì)主動(dòng)釋放連接。從建立連接到關(guān)閉連接的過(guò)程稱為“一次連接”。
1)在HTTP 1.0中,客戶端的每次請(qǐng)求都要求建立一次多帶帶的連接,在處理完本次請(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連接是一種“短連接”,要保持客戶端程序的在線狀態(tài),需要不斷地向服務(wù)器發(fā)起連接請(qǐng)求。通常 的做法是即時(shí)不需要獲得任何數(shù)據(jù),客戶端也保持每隔一段固定的時(shí)間向服務(wù)器發(fā)送一次“保持連接”的請(qǐng)求,服務(wù)器在收到該請(qǐng)求后對(duì)客戶端進(jìn)行回復(fù),表明知道 客戶端“在線”。若服務(wù)器長(zhǎng)時(shí)間無(wú)法收到客戶端的請(qǐng)求,則認(rèn)為客戶端“下線”,若客戶端長(zhǎng)時(shí)間無(wú)法收到服務(wù)器的回復(fù),則認(rèn)為網(wǎng)絡(luò)已經(jīng)斷開。
???
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連接至少需要一對(duì)套接字,其中一個(gè)運(yùn)行于客戶端,稱為ClientSocket ,另一個(gè)運(yùn)行于服務(wù)器端,稱為ServerSocket 。
套接字之間的連接過(guò)程分為三個(gè)步驟:服務(wù)器監(jiān)聽,客戶端請(qǐng)求,連接確認(rèn)。
服務(wù)器監(jiān)聽:服務(wù)器端套接字并不定位具體的客戶端套接字,而是處于等待連接的狀態(tài),實(shí)時(shí)監(jiān)控網(wǎng)絡(luò)狀態(tài),等待客戶端的連接請(qǐng)求。
客戶端請(qǐng)求:指客戶端的套接字提出連接請(qǐng)求,要連接的目標(biāo)是服務(wù)器端的套接字。為此,客戶端的套接字必須首先描述它要連接的服務(wù)器的套接字,指出服務(wù)器端套接字的地址和端口號(hào),然后就向服務(wù)器端套接字提出連接請(qǐng)求。
連接確認(rèn):當(dāng)服務(wù)器端套接字監(jiān)聽到或者說(shuō)接收到客戶端套接字的連接請(qǐng)求時(shí),就響應(yīng)客戶端套接字的請(qǐng)求,建立一個(gè)新的線程,把服務(wù)器端套接字的描述發(fā) 給客戶端,一旦客戶端確認(rèn)了此描述,雙方就正式建立連接。而服務(wù)器端套接字繼續(xù)處于監(jiān)聽狀態(tài),繼續(xù)接收其他客戶端套接字的連接請(qǐng)求。
創(chuàng)建Socket連接時(shí),可以指定使用的傳輸層協(xié)議,Socket可以支持不同的傳輸層協(xié)議(TCP或UDP),當(dāng)使用TCP協(xié)議進(jìn)行連接時(shí),該Socket連接就是一個(gè)TCP連接。
Socket連接與HTTP連接由于通常情況下Socket連接就是TCP連接,因此Socket連接一旦建立,通信雙方即可開始相互發(fā)送數(shù)據(jù)內(nèi)容,直到雙方連接斷開。但在實(shí)際網(wǎng) 絡(luò)應(yīng)用中,客戶端到服務(wù)器之間的通信往往需要穿越多個(gè)中間節(jié)點(diǎn),例如路由器、網(wǎng)關(guān)、防火墻等,大部分防火墻默認(rèn)會(huì)關(guān)閉長(zhǎng)時(shí)間處于非活躍狀態(tài)的連接而導(dǎo)致 Socket 連接斷連,因此需要通過(guò)輪詢告訴網(wǎng)絡(luò),該連接處于活躍狀態(tài)。
而HTTP連接使用的是“請(qǐng)求—響應(yīng)”的方式,不僅在請(qǐng)求時(shí)需要先建立連接,而且需要客戶端向服務(wù)器發(fā)出請(qǐng)求后,服務(wù)器端才能回復(fù)數(shù)據(jù)。
很多情況下,需要服務(wù)器端主動(dòng)向客戶端推送數(shù)據(jù),保持客戶端與服務(wù)器數(shù)據(jù)的實(shí)時(shí)與同步。此時(shí)若雙方建立的是Socket連接,服務(wù)器就可以直接將數(shù) 據(jù)傳送給客戶端;若雙方建立的是HTTP連接,則服務(wù)器需要等到客戶端發(fā)送一次請(qǐng)求后才能將數(shù)據(jù)傳回給客戶端,因此,客戶端定時(shí)向服務(wù)器端發(fā)送連接請(qǐng)求, 不僅可以保持在線,同時(shí)也是在“詢問(wèn)”服務(wù)器是否有新的數(shù)據(jù),如果有就將數(shù)據(jù)傳給客戶端。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)吧。
?
其中 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ù)包后,連接將被斷開。這個(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)然了,也不是我畫的,我也只是引用過(guò)來(lái)說(shuō)明問(wèn)題了。
第一次握手:建立連接。客戶端發(fā)送連接請(qǐng)求報(bào)文段,將SYN位置為1,Sequence Number為x;然后,客戶端進(jìn)入SYN_SEND狀態(tài),等待服務(wù)器的確認(rèn);
第二次握手:服務(wù)器收到SYN報(bào)文段。服務(wù)器收到客戶端的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ā)送給客戶端,此時(shí)服務(wù)器進(jìn)入SYN_RECV狀態(tài);
第三次握手:客戶端收到服務(wù)器的SYN+ACK報(bào)文段。然后將Acknowledgment Number設(shè)置為y+1,向服務(wù)器發(fā)送ACK報(bào)文段,這個(gè)報(bào)文段發(fā)送完畢以后,客戶端和服務(wù)器端都進(jìn)入ESTABLISHED狀態(tài),完成TCP三次握手。
完成了三次握手,客戶端和服務(wù)器端就可以開始傳送數(shù)據(jù)。以上就是TCP三次握手的總體介紹。
當(dāng)客戶端和服務(wù)器通過(guò)三次握手建立了TCP連接以后,當(dāng)數(shù)據(jù)傳送完畢,肯定是要斷開TCP連接的啊。那對(duì)于TCP的斷開連接,這里就有了神秘的“四次分手”。
第一次分手:主機(jī)1(可以使客戶端,也可以是服務(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ò)》一書中講“三次握手”的目的是為了解決“網(wǎng)絡(luò)中存在延遲的重復(fù)分組”的問(wèn)題。
在謝希仁著《計(jì)算機(jī)網(wǎng)絡(luò)》書中同時(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)一般是比較難見到的,而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)有的話,那么你也就可以 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ù),三次握手完畢后,客戶端與服務(wù)器才正式開始傳送數(shù)據(jù)。
第一次握手:客戶端發(fā)送syn包(syn=j)到服務(wù)器,并進(jìn)入SYN_SEND狀態(tài),等待服務(wù)器確認(rèn);
第二次握手:服務(wù)器收到syn包,必須確認(rèn)客戶的SYN(ack=j+1),同時(shí)自己也發(fā)送一個(gè)SYN包(syn=k),即SYN+ACK包,此時(shí)服務(wù)器進(jìn)入SYN_RECV狀態(tài);
第三次握手:客戶端收到服務(wù)器的SYN+ACK包,向服務(wù)器發(fā)送確認(rèn)包ACK(ack=k+1),此包發(fā)送完畢,客戶端和服務(wù)器進(jìn)入ESTABLISHED狀態(tài),完成三次握手。
握手過(guò)程中傳送的包里不包含數(shù)據(jù),三次握手完畢后,客戶端與服務(wù)器才正式開始傳送數(shù)據(jù)。理想狀態(tài)下,TCP連接一旦建立,在通信雙方中的任何一方主 動(dòng)關(guān)閉連接之前,TCP 連接都將被一直保持下去。斷開連接時(shí)服務(wù)器和客戶端均可以主動(dòng)發(fā)起斷開TCP連接的請(qǐng)求,斷開過(guò)程需要經(jīng)過(guò)“四次握手”(過(guò)程就不細(xì)寫了,就是服務(wù)器和客 戶端交互,最終確定斷開)
???
對(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的連接與斷開連接是發(fā)生的事情,其中還有很多的“坑”,讓我們后續(xù)有時(shí)間再繼續(xù)填吧。好了,完畢!??
搬運(yùn)文章TCP三次握手詳解及釋放連接過(guò)程
首先簡(jiǎn)單介紹一下TCP三次握手
TCP 為什么是三次握手,為什么不是兩次或四次?
最后推薦一個(gè)學(xué)習(xí)HTTP的github項(xiàng)目地址:我自己提煉的關(guān)于《HTTP權(quán)威指南》每章的知識(shí)點(diǎn)總結(jié)!
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/82683.html
摘要:三次握手和四次揮手的問(wèn)題在面試中是最為常見的考點(diǎn)之一。上面有一個(gè)非常特殊的狀態(tài),它是主動(dòng)關(guān)閉的一方在回復(fù)完對(duì)方的揮手后進(jìn)入的一個(gè)長(zhǎng)期狀態(tài),這個(gè)狀態(tài)標(biāo)準(zhǔn)的持續(xù)時(shí)間是分鐘,分鐘后才會(huì)進(jìn)入到狀態(tài),釋放套接字資源。 showImg(https://segmentfault.com/img/remote/1460000018918991); TCP三次握手和四次揮手的問(wèn)題在面試中是最為常見的考點(diǎn)...
摘要:在協(xié)議中,協(xié)議提供可靠的連接服務(wù),連接是通過(guò)三次握手進(jìn)行初始化的。三次握手的目的是同步連接雙方的序列號(hào)和確認(rèn)號(hào)并交換窗口大小信息。采用三次握手的辦法可以防止上述現(xiàn)象發(fā)生。 TCP是什么? 具體的關(guān)于TCP是什么,我不打算詳細(xì)的說(shuō)了;當(dāng)你看到這篇文章時(shí),我想你也知道TCP的概念了,想要更深入的了解TCP的工作,我們就繼續(xù)。它只是一個(gè)超級(jí)麻煩的協(xié)議,而它又是互聯(lián)網(wǎng)的基礎(chǔ),也是每個(gè)程序員必備...
摘要:很多人都知道協(xié)議是基于協(xié)議創(chuàng)造出來(lái)的采用文本方式傳輸非二進(jìn)制傳輸?shù)膽?yīng)用層協(xié)議,協(xié)議是傳輸層協(xié)議,主要解決數(shù)據(jù)如何在網(wǎng)絡(luò)中傳輸,而應(yīng)用層協(xié)議,主要解決如何包裝和規(guī)范數(shù)據(jù)。你也可以自己定義應(yīng)用層協(xié)議,只不過(guò)所有配套的東西都要自己重新造輪子。 從問(wèn)題切入能幫我們更好地理解晦澀難懂的概念。很多人都知道http協(xié)議是基于Tcp協(xié)議創(chuàng)造出來(lái)的采用文本方式傳輸(非二進(jìn)制傳輸)的應(yīng)用層協(xié)議,TPC/I...
閱讀 2167·2023-04-25 20:45
閱讀 1080·2021-09-22 15:13
閱讀 3647·2021-09-04 16:48
閱讀 2583·2019-08-30 15:53
閱讀 933·2019-08-30 15:44
閱讀 946·2019-08-30 15:43
閱讀 1008·2019-08-29 16:33
閱讀 3437·2019-08-29 13:08