寫在前面:由于工作需要饲宿,在網(wǎng)上學(xué)習了一些TCP相關(guān)的知識點,內(nèi)容不是很深刻胆描,都是一些常用的需要了解的部分瘫想。在此非常感謝網(wǎng)上的眾位大神給出的TCP相關(guān)的文章,本文是學(xué)習后整理下來的讀書筆記昌讲,因為時隔一段時間国夜,并且閱讀了好幾篇文章,所以不記得大神們的文章地址了短绸,無法給出具體的參考文章地址车吹,非常抱歉!
一醋闭、TCP和UDP
1. 什么是TCP和UDP
?OSI 七層模型通過七個層次化的結(jié)構(gòu)模型使不同的系統(tǒng)不同的網(wǎng)絡(luò)之間實現(xiàn)可靠的通訊窄驹,因此其最主要的功能就是幫助不同類型的主機實現(xiàn)數(shù)據(jù)傳輸 。
? ? ?完成中繼功能的節(jié)點通常稱為中繼系統(tǒng)证逻。在OSI七層模型中乐埠,處于不同層的中繼系統(tǒng)具有不同的名稱。
? ? ?一個設(shè)備工作在哪一層囚企,關(guān)鍵看它工作時利用哪一層的數(shù)據(jù)頭部信息丈咐。網(wǎng)橋工作時,是以MAC頭部來決定轉(zhuǎn)發(fā)端口的龙宏,因此顯然它是數(shù)據(jù)鏈路層的設(shè)備棵逊。
? ? ?具體說:
? ? ?? ? ?物理層:網(wǎng)卡,網(wǎng)線银酗,集線器辆影,中繼器掩浙,調(diào)制解調(diào)器
? ? ?? ? ?數(shù)據(jù)鏈路層:網(wǎng)橋,交換機
? ? ?? ? ?網(wǎng)絡(luò)層:路由器
? ? ?? ? ?網(wǎng)關(guān)工作在第四層傳輸層及其以上
? ? ?? ? ?tcp/udp在模型的傳輸層
? ? ?更詳細的可參考:OSI七層模型詳解?
? ? ?這里我們只需要知道:HTTP秸歧、WebSocket 等協(xié)議都是處于 OSI 模型的最高層:?應(yīng)用層?厨姚。而 IP 協(xié)議工作在網(wǎng)絡(luò)層(第3層),TCP 協(xié)議键菱、UDP協(xié)議工作在傳輸層(第4層)谬墙。
2.TCP與UDP的區(qū)別
? ? 2.1. TCP與UDP及其優(yōu)缺點:
3.TCP長連接、短連接
? ? 3.1 TCP長連接
? ? ? ? ? 所謂長連接经备,指在一個TCP連接上可以連續(xù)發(fā)送多個數(shù)據(jù)包拭抬,在TCP連接保持期間,如果沒有數(shù)據(jù)包發(fā)送侵蒙,需要雙方發(fā)檢測包以維持此連接造虎,一般需要自己做在線維持(不發(fā)生RST包和四次揮手)。 ? ? ?
? ? ? ? ? 整個過程:連接→數(shù)據(jù)傳輸→保持連接(心跳)→數(shù)據(jù)傳輸→保持連接(心跳)→……→關(guān)閉連接(一個TCP連接通道多個讀寫通信)纷闺;?
? ? ? ? ?這就要求長連接在沒有數(shù)據(jù)通信時算凿,定時發(fā)送數(shù)據(jù)包(心跳),以維持連接狀態(tài)犁功;
? ? ? ? ?TCP泵ズ洌活功能,苯裕活功能主要為服務(wù)器應(yīng)用提供署鸡,服務(wù)器應(yīng)用希望知道客戶主機是否崩潰,從而可以代表客戶使用資源限嫌。如果客戶已經(jīng)消失靴庆,使得服務(wù)器上保留一個半開放的連接,而服務(wù)器又在等待來自客戶端的數(shù)據(jù)怒医,則服務(wù)器將應(yīng)遠等待客戶端的數(shù)據(jù)炉抒,保活功能就是試圖在服務(wù)器端檢測到這種半開放的連接裆熙。
? ? ? ? ?如果一個給定的連接在兩小時內(nèi)沒有任何的動作端礼,則服務(wù)器就向客戶發(fā)一個探測報文段禽笑,客戶主機必須處于以下4個狀態(tài)之一:
客戶主機依然正常運行入录,并從服務(wù)器可達〖丫担客戶的TCP響應(yīng)正常僚稿,而服務(wù)器也知道對方是正常的,服務(wù)器在兩小時后將斌吧欤活定時器復(fù)位蚀同。
客戶主機已經(jīng)崩潰缅刽,并且關(guān)閉或者正在重新啟動。在任何一種情況下蠢络,客戶的TCP都沒有響應(yīng)衰猛。服務(wù)端將不能收到對探測的響應(yīng),并在75秒后超時刹孔。服務(wù)器總共發(fā)送10個這樣的探測 啡省,每個間隔75秒。如果服務(wù)器沒有收到一個響應(yīng)髓霞,它就認為客戶主機已經(jīng)關(guān)閉并終止連接卦睹。
客戶主機崩潰并已經(jīng)重新啟動。服務(wù)器將收到一個對其狈娇猓活探測的響應(yīng)结序,這個響應(yīng)是一個復(fù)位,使得服務(wù)器終止這個連接纵潦。
客戶機正常運行徐鹤,但是服務(wù)器不可達,這種情況與2類似邀层,TCP能發(fā)現(xiàn)的就是沒有收到探查的響應(yīng)凳干。
在長連接中一般是沒有條件能夠判斷讀寫什么時候結(jié)束,所以必須要加長度報文頭被济。讀函數(shù)先是讀取報文頭的長度救赐,再根據(jù)這個長度去讀相應(yīng)長度的報文。
? ? ?3.2. TCP短連接
短連接是指通信雙方有數(shù)據(jù)交互時只磷,就建立一個TCP連接经磅,數(shù)據(jù)發(fā)送完成后,則斷開此TCP連接(管理起來比較簡單钮追,存在的連接都是有用的連接预厌,不需要額外的控制手段);
? ? ? ? ? ? ? 整個過程:連接→數(shù)據(jù)傳輸→關(guān)閉連接元媚;
? ? ?3.3 TCP長連接和短連接的優(yōu)缺點:
?3.3 TCP長連接和短連接的應(yīng)用場景:
? ? ? ? ? ? ?長連接多用于操作頻繁(讀寫)轧叽,點對點的通訊,而且連接數(shù)不能太多情況刊棕,炭晒。每個TCP連接都需要三步握手,這需要時間甥角,如果每個操作都是先連接网严,再操作的話那么處理速度會降低很多,所以每個操作完后都不斷開嗤无,次處理時直接發(fā)送數(shù)據(jù)包就OK了震束,不用建立TCP連接怜庸。例如:數(shù)據(jù)庫的連接用長連接, 如果用短連接頻繁的通信會造成socket錯誤垢村,而且頻繁的socket 創(chuàng)建也是對資源的浪費割疾。
? ? ? ? ? ? ?而像WEB網(wǎng)站的http服務(wù)一般都用短鏈接(http1.0只支持短連接,1.1keep alive 帶時間嘉栓,操作次數(shù)限制的長連接)杈曲,因為長連接對于服務(wù)端來說會耗費一定的資源,而像WEB網(wǎng)站這么頻繁的成千上萬甚至上億客戶端的連接用短連接會更省一些資源胸懈,如果用長連接担扑,而且同時有成千上萬的用戶,如果每個用戶都占用一個連接的話趣钱,那可想而知吧涌献。所以并發(fā)量大,但每個用戶無需頻繁操作情況下需用短連好首有;
二燕垃、TCP的三次握手和四次揮手
上面說到過:TCP 協(xié)議、UDP協(xié)議工作在傳輸層(第4層)井联。從最上面的圖中卜壕,我們也可以看到,HTTP烙常、WebSocket 等應(yīng)用層協(xié)議轴捎,都是基于 TCP 協(xié)議來傳輸數(shù)據(jù)的。我們可以把這些高級協(xié)議理解成對 TCP 的封裝蚕脏。
? ? 既然大家都使用 TCP 協(xié)議侦副,那么大家的連接和斷開,都要遵循?TCP 協(xié)議中的三次握手(建立連接)和四次握手(斷開連接) 驼鞭,只是在連接之后發(fā)送的內(nèi)容不同秦驯,或者是斷開的時間不同。
1.TCP的三次握手(用于建立連接)
? ? ? 首先Client端發(fā)送連接請求報文挣棕,Server段接受連接后回復(fù)ACK報文译隘,并為這次連接分配資源。Client端接收到ACK報文后也向Server段發(fā)生ACK報文洛心,并分配資源固耘,這樣TCP連接就建立了。
在TCP/IP協(xié)議中皂甘,TCP協(xié)議通過三次握手建立一個可靠的連接
2.TCP的四次握手(用于斷開連接)
?當客戶端和服務(wù)器通過三次握手建立了TCP連接以后玻驻,當數(shù)據(jù)傳送完畢,肯定是要斷開TCP連接的啊偿枕。那對于TCP的斷開連接璧瞬,這里就有了神秘的“四次揮手”。
第一次揮手:主機1(可以使客戶端渐夸,也可以是服務(wù)器端)嗤锉,設(shè)置Sequence Number和Acknowledgment Number,向主機2發(fā)送一個FIN報文段墓塌;此時瘟忱,主機1進入FIN_WAIT_1狀態(tài);這表示主機1沒有數(shù)據(jù)要發(fā)送給主機2了苫幢;
第二次揮手:主機2收到了主機1發(fā)送的FIN報文段访诱,向主機1回一個ACK報文段,Acknowledgment Number為Sequence Number加1韩肝;主機1進入FIN_WAIT_2狀態(tài)触菜;主機2告訴主機1,我“同意”你的關(guān)閉請求哀峻;
第三次揮手:主機2向主機1發(fā)送FIN報文段涡相,請求關(guān)閉連接,同時主機2進入LAST_ACK狀態(tài)剩蟀;
第四次揮手:主機1收到主機2發(fā)送的FIN報文段催蝗,向主機2發(fā)送ACK報文段,然后主機1進入TIME_WAIT狀態(tài)育特;主機2收到主機1的ACK報文段以后丙号,就關(guān)閉連接;此時缰冤,主機1等待2MSL后依然沒有收到回復(fù)槽袄,則證明Server端已正常關(guān)閉,那好锋谐,主機1也可以關(guān)閉連接了遍尺。
【注意】?在TIME_WAIT狀態(tài)中,如果TCP client端最后一次發(fā)送的ACK丟失了涮拗,它將重新發(fā)送乾戏。TIME_WAIT狀態(tài)中所需要的時間是依賴于實現(xiàn)方法的。典型的值為30秒三热、1分鐘和2分鐘鼓择。等待之后連接正式關(guān)閉,并且所有的資源(包括端口號)都被釋放就漾。
? ??【問題】為什么TIME_WAIT狀態(tài)需要經(jīng)過2MSL(最大報文段生存時間)才能返回到CLOSE狀態(tài)呐能?
? ? ? 答:雖然按道理,四個報文都發(fā)送完畢,我們可以直接進入CLOSE狀態(tài)了摆出,但是我們必須假象網(wǎng)絡(luò)是不可靠的朗徊,有可以最后一個ACK丟失。所以TIME_WAIT狀態(tài)就是用來重發(fā)可能丟失的ACK報文偎漫。
3.為什么要四次握手(用于斷開連接)
那四次分手又是為何呢爷恳?TCP協(xié)議是一種面向連接的、可靠的象踊、基于字節(jié)流的運輸層通信協(xié)議温亲。TCP是全雙工模式,這就意味著杯矩,當主機1發(fā)出FIN報文段時栈虚,只是表示主機1已經(jīng)沒有數(shù)據(jù)要發(fā)送了球订,主機1告訴主機2致讥,它的數(shù)據(jù)已經(jīng)全部發(fā)送完畢了宫患;但是凶掰,這個時候主機1還是可以接受來自主機2的數(shù)據(jù)阵子;當主機2返回ACK報文段時往果,表示它已經(jīng)知道主機1沒有數(shù)據(jù)發(fā)送了磷雇,但是主機2還是可以發(fā)送數(shù)據(jù)到主機1的羔砾;當主機2也發(fā)送了FIN報文段時魄幕,這個時候就表示主機2也沒有數(shù)據(jù)要發(fā)送了相艇,就會告訴主機1,我也沒有數(shù)據(jù)要發(fā)送了纯陨,之后彼此就會愉快的中斷這次TCP連接坛芽。如果要正確的理解四次分手的原理,就需要了解四次分手過程中的狀態(tài)變化翼抠。
FIN_WAIT_1: 這個狀態(tài)要好好解釋一下咙轩,其實FIN_WAIT_1和FIN_WAIT_2狀態(tài)的真正含義都是表示等待對方的FIN報文。而這兩種狀態(tài)的區(qū)別是:FIN_WAIT_1狀態(tài)實際上是當SOCKET在ESTABLISHED狀態(tài)時阴颖,它想主動關(guān)閉連接活喊,向?qū)Ψ桨l(fā)送了FIN報文,此時該SOCKET即進入到FIN_WAIT_1狀態(tài)量愧。而當對方回應(yīng)ACK報文后钾菊,則進入到FIN_WAIT_2狀態(tài),當然在實際的正常情況下偎肃,無論對方何種情況下煞烫,都應(yīng)該馬上回應(yīng)ACK報文,所以FIN_WAIT_1狀態(tài)一般是比較難見到的累颂,而FIN_WAIT_2狀態(tài)還有時常持拖辏可以用netstat看到。(主動方)
FIN_WAIT_2:上面已經(jīng)詳細解釋了這種狀態(tài),實際上FIN_WAIT_2狀態(tài)下的SOCKET料饥,表示半連接蒲犬,也即有一方要求close連接,但另外還告訴對方稀火,我暫時還有點數(shù)據(jù)需要傳送給你(ACK信息)暖哨,稍后再關(guān)閉連接赌朋。(主動方)
CLOSE_WAIT:這種狀態(tài)的含義其實是表示在等待關(guān)閉凰狞。怎么理解呢?當對方close一個SOCKET后發(fā)送FIN報文給自己沛慢,你系統(tǒng)毫無疑問地會回應(yīng)一個ACK報文給對方赡若,此時則進入到CLOSE_WAIT狀態(tài)。接下來呢团甲,實際上你真正需要考慮的事情是察看你是否還有數(shù)據(jù)發(fā)送給對方逾冬,如果沒有的話,那么你也就可以 close這個SOCKET躺苦,發(fā)送FIN報文給對方身腻,也即關(guān)閉連接。所以你在CLOSE_WAIT狀態(tài)下匹厘,需要完成的事情是等待你去關(guān)閉連接嘀趟。(被動方)
LAST_ACK: 這個狀態(tài)還是比較容易好理解的,它是被動關(guān)閉一方在發(fā)送FIN報文后愈诚,最后等待對方的ACK報文她按。當收到ACK報文后,也即可以進入到CLOSED可用狀態(tài)了炕柔。(被動方)
TIME_WAIT: 表示收到了對方的FIN報文酌泰,并發(fā)送出了ACK報文,就等2MSL后即可回到CLOSED可用狀態(tài)了匕累。如果FINWAIT1狀態(tài)下陵刹,收到了對方同時帶FIN標志和ACK標志的報文時,可以直接進入到TIME_WAIT狀態(tài)欢嘿,而無須經(jīng)過FIN_WAIT_2狀態(tài)。(主動方)
CLOSED: 表示連接中斷际插。
4.為什么連接的時候是三次握手碘耳,關(guān)閉的時候卻是四次握手?
? ??因為當Server端收到Client端的SYN連接請求報文后框弛,可以直接發(fā)送SYN+ACK報文辛辨。其中ACK報文是用來應(yīng)答的,SYN報文是用來同步的。但是關(guān)閉連接時斗搞,當Server端收到FIN報文時指攒,很可能并不會立即關(guān)閉SOCKET,所以只能先回復(fù)一個ACK報文僻焚,告訴Client端允悦,"你發(fā)的FIN報文我收到了"。只有等到我Server端所有的報文都發(fā)送完了虑啤,我才能發(fā)送FIN報文隙弛,因此不能一起發(fā)送。故需要四步握手狞山。
5. TCP斷開由誰發(fā)起全闷?
? ??中斷連接端可以是Client端,也可以是Server端萍启。
? ??假設(shè)Client端發(fā)起中斷連接請求总珠,也就是發(fā)送FIN報文。Server端接到FIN報文后勘纯,意思是說"我Client端沒有數(shù)據(jù)要發(fā)給你了"局服,但是如果你還有數(shù)據(jù)沒有發(fā)送完成,則不必急著關(guān)閉Socket驳遵,可以繼續(xù)發(fā)送數(shù)據(jù)淫奔。所以你先發(fā)送ACK,"告訴Client端超埋,你的請求我收到了搏讶,但是我還沒準備好,請繼續(xù)你等我的消息"霍殴。這個時候Client端就進入FIN_WAIT狀態(tài)媒惕,繼續(xù)等待Server端的FIN報文。當Server端確定數(shù)據(jù)已發(fā)送完成来庭,則向Client端發(fā)送FIN報文妒蔚,"告訴Client端,好了月弛,我這邊數(shù)據(jù)發(fā)完了肴盏,準備好關(guān)閉連接了"。Client端收到FIN報文后帽衙,"就知道可以關(guān)閉連接了菜皂,但是他還是不相信網(wǎng)絡(luò),怕Server端不知道要關(guān)閉厉萝,所以發(fā)送ACK后進入TIME_WAIT狀態(tài)恍飘,如果Server端沒有收到ACK則可以重傳榨崩。“章母,Server端收到ACK后母蛛,"就知道可以斷開連接了"。Client端等待了2MSL后依然沒有收到回復(fù)乳怎,則證明Server端已正常關(guān)閉彩郊,那好,我Client端也可以關(guān)閉連接了蚪缀。Ok秫逝,TCP連接就這樣關(guān)閉了!
? ??整個過程Client端所經(jīng)歷的狀態(tài)如下:
而Server端所經(jīng)歷的過程如下: