建立TCP需要三次握手才能建立积糯,而斷開連接則需要四次握手跨嘉。
但是為什么一定要進(jìn)行三次握手來保證連接是雙工的呢琴拧,一次不行么沛膳?兩次不行么?我們舉一個(gè)現(xiàn)實(shí)生活中兩個(gè)人進(jìn)行語言溝通的例子來模擬三次握手。
引用網(wǎng)上的一些通俗易懂的例子,雖然不太正確廓俭,后面會(huì)指出雹熬,但是不妨礙我們理解,大體就是這么個(gè)理解法。
第一次對(duì)話:
老婆讓甲出去打醬油,半路碰到一個(gè)朋友乙,甲問了一句:哥們你吃飯了么懊直?
結(jié)果乙?guī)е鷻C(jī)聽歌呢盼铁,根本沒聽到当辐,沒反應(yīng)寺晌。甲心里想:跟你說話也沒個(gè)音,不跟你說了灾锯,溝通失敗。說明乙接受不到甲傳過來的信息的情況下溝通肯定是失敗的佃乘。
如果乙聽到了甲說的話鹅巍,那么第一次對(duì)話成功枫攀,接下來進(jìn)行第二次對(duì)話僵闯。
第二次對(duì)話:
乙聽到了甲說的話泳秀,但是他是老外币他,中文不好庆杜,不知道甲說的啥意思也不知道怎樣回答罗洗,于是隨便回答了一句學(xué)過的中文 :我去廁所了。甲一聽立刻笑噴了迂尝,“去廁所吃飯”?道不同不相為謀锻梳,離你遠(yuǎn)點(diǎn)吧废亭,溝通失敗。說明乙無法做出正確應(yīng)答的情況下溝通失敗恋追。
如果乙聽到了甲的話,做出了正確的應(yīng)答愉昆,并且還進(jìn)行了反問:我吃飯了牵祟,你呢诺苹?那么第二次握手成功模暗。
通過前兩次對(duì)話證明了乙能夠聽懂甲說的話枚驻,并且能做出正確的應(yīng)答缠俺。?接下來進(jìn)行第三次對(duì)話。
第三次對(duì)話:
甲剛和乙打了個(gè)招呼贷岸,突然老婆喊他壹士,“你個(gè)死鬼,打個(gè)醬油咋這么半天偿警,看我回家咋收拾你”躏救,甲是個(gè)妻管嚴(yán),聽完嚇得二話不說就跑回家了,把乙自己晾那了盒使。乙心想:這什么人啊崩掘,得,我也回家吧,溝通失敗。說明甲無法做出應(yīng)答的情況下溝通失敗炒瘟。
如果甲也做出了正確的應(yīng)答:我也吃了。那么第三次對(duì)話成功物延,兩人已經(jīng)建立起了順暢的溝通渠道,接下來開始持續(xù)的聊天。
通過第二次和第三次的對(duì)話證明了甲能夠聽懂乙說的話,并且能做出正確的應(yīng)答辑畦。
可見,兩個(gè)人進(jìn)行有效的語言溝通贺纲,這三次對(duì)話的過程是必須的。
為了保證服務(wù)端能收接受到客戶端的信息并能做出正確的應(yīng)答而進(jìn)行前兩次(第一次和第二次)握手褪测,為了保證客戶端能夠接收到服務(wù)端的信息并能做出正確的應(yīng)答而進(jìn)行后兩次(第二次和第三次)握手猴誊。
這個(gè)例子舉得挺好的。不過個(gè)人感覺為什么是三次而不是二次侮措,不是因?yàn)闉榱俗C明甲能聽懂乙并回應(yīng)(第二次乙能正確的響應(yīng)甲說明倆人之間溝通已無障礙了)懈叹,而是怕出現(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)。(問題出現(xiàn)了)假如采用2次握手宏悦,乙就認(rèn)定了甲要跟他溝通镐确,于是就不停的等,浪費(fèi)感情饼煞≡春可如果是采用3次握手,乙等了一會(huì)后發(fā)現(xiàn)甲沒有回應(yīng)他就認(rèn)為甲走了然后自己也就走了砖瞧!
這就很明白了息堂,其實(shí)第三步是防止了乙的一直等待而浪費(fèi)自己的時(shí)間,而不是為了保證甲能夠正確回應(yīng)乙的信息块促。
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)閉連接的過程稱為“一次連接”只酥。
1)在HTTP 1.0中,客戶端的每次請(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連接是一種“短連接”十饥,要保持客戶端程序的在線狀態(tài),需要不斷地向服務(wù)器發(fā)起連接請(qǐng)求祖乳。通常 的做法是即時(shí)不需要獲得任何數(shù)據(jù)逗堵,客戶端也保持每隔一段固定的時(shí)間向服務(wù)器發(fā)送一次“保持連接”的請(qǐng)求,服務(wù)器在收到該請(qǐng)求后對(duì)客戶端進(jìn)行回復(fù)眷昆,表明知道 客戶端“在線”蜒秤。若服務(wù)器長時(shí)間無法收到客戶端的請(qǐng)求,則認(rèn)為客戶端“下線”亚斋,若客戶端長時(shí)間無法收到服務(wù)器的回復(fù)作媚,則認(rèn)為網(wǎng)絡(luò)已經(jīng)斷開。
SOCKET原理
套接字(socket)概念
套接字(socket)是通信的基石帅刊,是支持TCP/IP協(xié)議的網(wǎng)絡(luò)通信的基本操作單元掂骏。它是網(wǎng)絡(luò)通信過程中端點(diǎn)的抽象表示,包含進(jìn)行網(wǎng)絡(luò)通信必須的五種信息:連接使用的協(xié)議厚掷,本地主機(jī)的IP地址弟灼,本地進(jìn)程的協(xié)議端口,遠(yuǎn)地主機(jī)的IP地址冒黑,遠(yuǎn)地進(jìn)程的協(xié)議端口田绑。
應(yīng)用層通過傳輸層進(jìn)行數(shù)據(jù)通信時(shí),TCP會(huì)遇到同時(shí)為多個(gè)應(yīng)用程序進(jìn)程提供并發(fā)服務(wù)的問題抡爹。多個(gè)TCP連接或多個(gè)應(yīng)用程序進(jìn)程可能需要通過同一個(gè) TCP協(xié)議端口傳輸數(shù)據(jù)掩驱。為了區(qū)別不同的應(yīng)用程序進(jìn)程和連接,許多計(jì)算機(jī)操作系統(tǒng)為應(yīng)用程序與TCP/IP協(xié)議交互提供了套接字(Socket)接口。應(yīng) 用層可以和傳輸層通過Socket接口欧穴,區(qū)分來自不同應(yīng)用程序進(jìn)程或網(wǎng)絡(luò)連接的通信民逼,實(shí)現(xiàn)數(shù)據(jù)傳輸?shù)牟l(fā)服務(wù)。
建立socket連接
建立Socket連接至少需要一對(duì)套接字涮帘,其中一個(gè)運(yùn)行于客戶端拼苍,稱為ClientSocket ,另一個(gè)運(yùn)行于服務(wù)器端调缨,稱為ServerSocket 疮鲫。
套接字之間的連接過程分為三個(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)聽到或者說接收到客戶端套接字的連接請(qǐng)求時(shí)媒熊,就響應(yīng)客戶端套接字的請(qǐng)求,建立一個(gè)新的線程坟比,把服務(wù)器端套接字的描述發(fā) 給客戶端芦鳍,一旦客戶端確認(rèn)了此描述,雙方就正式建立連接葛账。而服務(wù)器端套接字繼續(xù)處于監(jiān)聽狀態(tài)柠衅,繼續(xù)接收其他客戶端套接字的連接請(qǐng)求。
SOCKET連接與TCP連接
創(chuàng)建Socket連接時(shí)籍琳,可以指定使用的傳輸層協(xié)議菲宴,Socket可以支持不同的傳輸層協(xié)議(TCP或UDP),當(dāng)使用TCP協(xié)議進(jìn)行連接時(shí)趋急,該Socket連接就是一個(gè)TCP連接喝峦。
由于通常情況下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)閉長時(shí)間處于非活躍狀態(tài)的連接而導(dǎo)致 Socket 連接斷連册烈,因此需要通過輪詢告訴網(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ù)器是否有新的數(shù)據(jù)侄柔,如果有就將數(shù)據(jù)傳給客戶端共啃。TCP(Transmission Control Protocol) 傳輸控制協(xié)議
TCP是主機(jī)對(duì)主機(jī)層的傳輸控制協(xié)議,提供可靠的連接服務(wù)暂题,采用三次握手確認(rèn)建立一個(gè)連接:
TCP是什么移剪?
TCP(Transmission Control Protocol 傳輸控制協(xié)議)是一種面向連接的、可靠的薪者、基于字節(jié)流的傳輸層通信協(xié)議纵苛。
具體的關(guān)于TCP是什么,我不打算詳細(xì)的說了言津;當(dāng)你看到這篇文章時(shí)攻人,我想你也知道TCP的概念了,想要更深入的了解TCP的工作悬槽,我們就繼續(xù)怀吻。它只是一個(gè)超級(jí)麻煩的協(xié)議,而它又是互聯(lián)網(wǎng)的基礎(chǔ)陷谱,也是每個(gè)程序員必備的基本功烙博。首先來看看OSI的七層模型:
TCP是一個(gè)協(xié)議瑟蜈,那這個(gè)協(xié)議是如何定義的,它的數(shù)據(jù)格式是什么樣子的呢渣窜?要進(jìn)行更深層次的剖析铺根,就需要了解,甚至是熟記TCP協(xié)議中每個(gè)字段的含義乔宿。哦位迂,來吧。
TCP頭部
其中 ACK SYN 序號(hào) 這三個(gè)部分在以下會(huì)用到详瑞,它們的介紹也在下面掂林。
上面就是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)行端口掃描民泵。
三次握手的過程:
第一次握手:建立連接诫咱。客戶端發(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)閉連接了镜粤。