摘要:在協(xié)議中,協(xié)議提供可靠的連接服務(wù),連接是通過三次握手進(jìn)行初始化的。三次握手的目的是同步連接雙方的序列號(hào)和確認(rèn)號(hào)并交換窗口大小信息。采用三次握手的辦法可以防止上述現(xiàn)象發(fā)生。
TCP是什么?
具體的關(guān)于TCP是什么,我不打算詳細(xì)的說了;當(dāng)你看到這篇文章時(shí),我想你也知道TCP的概念了,想要更深入的了解TCP的工作,我們就繼續(xù)。它只是一個(gè)超級(jí)麻煩的協(xié)議,而它又是互聯(lián)網(wǎng)的基礎(chǔ),也是每個(gè)程序員必備的基本功。首先來看看OSI的七層模型:
我們需要知道TCP工作在網(wǎng)絡(luò)OSI的七層模型中的第四層——Transport層,IP在第三層——Network層,ARP在第二層——Data Link層;在第二層上的數(shù)據(jù),我們把它叫Frame,在第三層上的數(shù)據(jù)叫Packet,第四層的數(shù)據(jù)叫Segment。 同時(shí),我們需要簡單的知道,數(shù)據(jù)從應(yīng)用層發(fā)下來,會(huì)在每一層都會(huì)加上頭部信息,進(jìn)行封裝,然后再發(fā)送到數(shù)據(jù)接收端。這個(gè)基本的流程你需要知道,就是每個(gè)數(shù)據(jù)都會(huì)經(jīng)過數(shù)據(jù)的封裝和解封裝的過程。 在OSI七層模型中,每一層的作用和對(duì)應(yīng)的協(xié)議如下:
TCP是一個(gè)協(xié)議,那這個(gè)協(xié)議是如何定義的,它的數(shù)據(jù)格式是什么樣子的呢?要進(jìn)行更深層次的剖析,就需要了解,甚至是熟記TCP協(xié)議中每個(gè)字段的含義。哦,來吧。
上面就是TCP協(xié)議頭部的格式,由于它太重要了,是理解其它內(nèi)容的基礎(chǔ),下面就將每個(gè)字段的信息都詳細(xì)的說明一下。
Source Port和Destination Port:分別占用16位,表示源端口號(hào)和目的端口號(hào);用于區(qū)別主機(jī)中的不同進(jìn)程,而IP地址是用來區(qū)分不同的主機(jī)的,源端口號(hào)和目的端口號(hào)配合上IP首部中的源IP地址和目的IP地址就能唯一的確定一個(gè)TCP連接;
Sequence Number:用來標(biāo)識(shí)從TCP發(fā)端向TCP收端發(fā)送的數(shù)據(jù)字節(jié)流,它表示在這個(gè)報(bào)文段中的的第一個(gè)數(shù)據(jù)字節(jié)在數(shù)據(jù)流中的序號(hào);主要用來解決網(wǎng)絡(luò)報(bào)亂序的問題;
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。不過,只有當(dāng)標(biāo)志位中的ACK標(biāo)志(下面介紹)為1時(shí)該確認(rèn)序列號(hào)的字段才有效。主要用來解決不丟包的問題;
Offset:給出首部中32 bit字的數(shù)目,需要這個(gè)值是因?yàn)槿芜x字段的長度是可變的。這個(gè)字段占4bit(最多能表示15個(gè)32bit的的字,即4*15=60個(gè)字節(jié)的首部長度),因此TCP最多有60字節(jié)的首部。然而,沒有任選字段,正常的長度是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包的緊急指針域(后面馬上就要說到)有效,用來保證TCP連接不被中斷,并且督促中間層設(shè)備要盡快處理這些數(shù)據(jù);
ACK:此標(biāo)志表示應(yīng)答域有效,就是說前面所說的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)求。用來復(fù)位那些產(chǎn)生錯(cuò)誤的連接,也被用來拒絕錯(cuò)誤和非法的數(shù)據(jù)包;
SYN:表示同步序號(hào),用來建立連接。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)常被用來進(jìn)行端口掃描。掃描者發(fā)送一個(gè)只有SYN的數(shù)據(jù)包,如果對(duì)方主機(jī)響應(yīng)了一個(gè)數(shù)據(jù)包回來 ,就表明這臺(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ù)末尾,也就是說雙方的數(shù)據(jù)傳送完成,沒有數(shù)據(jù)可以傳送了,發(fā)送FIN標(biāo)志位的TCP數(shù)據(jù)包后,連接將被斷開。這個(gè)標(biāo)志的數(shù)據(jù)包也經(jīng)常被用于進(jìn)行端口掃描。
Window:窗口大小,也就是有名的滑動(dòng)窗口,用來進(jìn)行流量控制;這是一個(gè)復(fù)雜的問題,這篇博文中并不會(huì)進(jìn)行總結(jié)的;
好了,基本知識(shí)都已經(jīng)準(zhǔn)備好了,開始下一段的征程吧。
三次握手又是什么?TCP是面向連接的,無論哪一方向另一方發(fā)送數(shù)據(jù)之前,都必須先在雙方之間建立一條連接。在TCP/IP協(xié)議中,TCP協(xié)議提供可靠的連接服務(wù),連接是通過三次握手進(jìn)行初始化的。三次握手的目的是同步連接雙方的序列號(hào)和確認(rèn)號(hào)并交換 TCP窗口大小信息。這就是面試中經(jīng)常會(huì)被問到的TCP三次握手。只是了解TCP三次握手的概念,對(duì)你獲得一份工作是沒有任何幫助的,你需要去了解TCP三次握手中的一些細(xì)節(jié)。先來看圖說話。
多么清晰的一張圖,當(dāng)然了,也不是我畫的,我也只是引用過來說明問題了。
第一次握手:建立連接。客戶端發(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ù)器通過三次握手建立了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沒有數(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后依然沒有收到回復(fù),則證明Server端已正常關(guān)閉,那好,主機(jī)1也可以關(guān)閉連接了。
至此,TCP的四次分手就這么愉快的完成了。當(dāng)你看到這里,你的腦子里會(huì)有很多的疑問,很多的不懂,感覺很凌亂;沒事,我們繼續(xù)總結(jié)。
為什么要三次握手既然總結(jié)了TCP的三次握手,那為什么非要三次呢?怎么覺得兩次就可以完成了。那TCP為什么非要進(jìn)行三次連接呢?在謝希仁的《計(jì)算機(jī)網(wǎng)絡(luò)》中是這樣說的:
為了防止已失效的連接請(qǐng)求報(bào)文段突然又傳送到了服務(wù)端,因而產(chǎn)生錯(cuò)誤。
在書中同時(shí)舉了一個(gè)例子,如下:
“已失效的連接請(qǐng)求報(bào)文段”的產(chǎn)生在這樣一種情況下:client發(fā)出的第一個(gè)連接請(qǐng)求報(bào)文段并沒有丟失,而是在某個(gè)網(wǎng)絡(luò)結(jié)點(diǎn)長時(shí)間的滯留了,以致延誤到連接釋放以后的某個(gè)時(shí)間才到達(dá)server。本來這是一個(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并沒有發(fā)出建立連接的請(qǐng)求,因此不會(huì)理睬server的確認(rèn),也不會(huì)向server發(fā)送數(shù)據(jù)。但server卻以為新的運(yùn)輸連接已經(jīng)建立,并一直等待client發(fā)來數(shù)據(jù)。這樣,server的很多資源就白白浪費(fèi)掉了。采用“三次握手”的辦法可以防止上述現(xiàn)象發(fā)生。例如剛才那種情況,client不會(huì)向server的確認(rèn)發(fā)出確認(rèn)。server由于收不到確認(rèn),就知道client并沒有要求建立連接。”
這就很明白了,防止了服務(wù)器端的一直等待而浪費(fèi)資源。
為什么要四次分手那四次分手又是為何呢?TCP協(xié)議是一種面向連接的、可靠的、基于字節(jié)流的運(yùn)輸層通信協(xié)議。TCP是全雙工模式,這就意味著,當(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ā)送完畢了;但是,這個(gè)時(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ā)送了,就會(huì)告訴主機(jī)1,我也沒有數(shù)據(jù)要發(fā)送了,之后彼此就會(huì)愉快的中斷這次TCP連接。如果要正確的理解四次分手的原理,就需要了解四次分手過程中的狀態(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í)際的正常情況下,無論對(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)毫無疑問地會(huì)回應(yīng)一個(gè)ACK報(bào)文給對(duì)方,此時(shí)則進(jìn)入到CLOSE_WAIT狀態(tài)。接下來呢,實(shí)際上你真正需要考慮的事情是察看你是否還有數(shù)據(jù)發(fā)送給對(duì)方,如果沒有的話,那么你也就可以 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),而無須經(jīng)過FIN_WAIT_2狀態(tài)。(主動(dòng)方)
CLOSED: 表示連接中斷。
我想你應(yīng)該懂了總結(jié)到這里,也該結(jié)束了,但是對(duì)于TCP的學(xué)習(xí)遠(yuǎn)還沒有結(jié)束。TCP是一個(gè)非常復(fù)雜的協(xié)議,這里稍微總結(jié)了一下TCP的連接與斷開連接是發(fā)生的事情,其中還有很多的“坑”,讓我們后續(xù)有時(shí)間再繼續(xù)填吧。好了,完畢!
閱讀更多高級(jí)面試題總結(jié)—線程池還能這么玩?
?一招教你讀懂JVM和Dalvik之間的區(qū)別
?我的Android重構(gòu)之旅:插件化篇
20+個(gè)很棒的Android開源項(xiàng)目
看完你就該會(huì)git了(手把手教你用vue+node+mongodb搭建一個(gè)小商城)
相信自己,沒有做不到的,只有想不到的在這里獲得的不僅僅是技術(shù)!
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/76518.html
摘要:構(gòu)造函數(shù)默認(rèn)空閑的最大連接數(shù)為個(gè),的時(shí)間為秒通過構(gòu)造函數(shù)可以看出默認(rèn)的空閑的最大連接數(shù)為個(gè),的時(shí)間為秒。實(shí)例化實(shí)例化是在實(shí)例化時(shí)進(jìn)行的在的構(gòu)造函數(shù)中調(diào)用了省略省略緩存操作提供對(duì)進(jìn)行操作的方法分別為和幾個(gè)操作。 1.引子 在了解OkHttp的復(fù)用連接池之前,我們首先要了解幾個(gè)概念。 TCP三次握手 通常我們進(jìn)行HTTP連接網(wǎng)絡(luò)的時(shí)候我們會(huì)進(jìn)行TCP的三次握手,然后傳輸數(shù)據(jù),然后再釋放連接...
摘要:原理套接字概念套接字是通信的基石,是支持協(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ī)...
摘要:我沒有什么本事,人也丑,也不會(huì)忽悠,只能硬著頭皮學(xué)習(xí)了。最近計(jì)劃學(xué)習(xí)后臺(tái),因?yàn)樽罱恿怂交畹膯栴},好多都要后臺(tái)和前端一起做。 我沒有什么本事,人也丑,也不會(huì)忽悠,只能硬著頭皮學(xué)習(xí)了。最近計(jì)劃學(xué)習(xí)Java后臺(tái),因?yàn)樽罱恿怂交畹膯栴},好多都要Java后臺(tái)和前端一起做。平常我在做什么,當(dāng)然是忙著賺錢了 除了敲代碼,你還有什么副業(yè)嗎?接了活自己還要找開發(fā)Java后臺(tái)開發(fā)的,為什么我自己不會(huì)呢...
閱讀 4078·2021-10-08 10:04
閱讀 3061·2021-08-11 11:20
閱讀 2731·2021-07-25 21:37
閱讀 2681·2019-08-30 12:44
閱讀 2306·2019-08-30 11:12
閱讀 1314·2019-08-26 13:45
閱讀 2338·2019-08-26 11:53
閱讀 3057·2019-08-26 11:32