“三次握手囊卜,四次揮手”是什么?你了解嗎雀瓢?

記得剛畢業(yè)找工作面試的時候玉掸,經(jīng)常會被問到:你知道“3次握手,4次揮手”嗎泊业?這時候我會“胸有成竹”地“背誦”前期準備好的“答案”吁伺,第一次怎么怎么租谈,第二次……答完就沒有下文了,面試官貌似也沒有深入下去的意思宦搬,深入下去我也不懂劫拗,皆大歡喜页慷!

作為程序員胁附,要有“刨根問底”的精神控妻。知其然揭绑,更要知其所以然。這篇文章希望能抽絲剝繭菇存,還原背后的原理依鸥。

什么是“3次握手悼沈,4次揮手”?

TCP是一種面向連接的單播協(xié)議衣吠,在發(fā)送數(shù)據(jù)前杯缺,通信雙方必須在彼此間建立一條連接睡榆。所謂的“連接”胀屿,其實是客戶端和服務器的內(nèi)存里保存的一份關于對方的信息,如ip地址亲铡、端口號等葡兑。

TCP可以看成是一種字節(jié)流讹堤,它會處理IP層或以下的層的丟包、重復以及錯誤問題疑务。在連接的建立過程中,雙方需要交換一些連接的參數(shù)知允。這些參數(shù)可以放在TCP頭部温鸽。

TCP提供了一種可靠、面向連接配椭、字節(jié)流雹姊、傳輸層的服務,采用三次握手建立一個連接敦姻。采用4次揮手來關閉一個連接镰惦。

TCP服務模型

在了解了建立連接、關閉連接的“三次握手和四次揮手”后旺入,我們再來看下TCP相關的東西凯力。

一個TCP連接由一個4元組構(gòu)成咐鹤,分別是兩個IP地址和兩個端口號。一個TCP連接通常分為三個階段:啟動祈惶、數(shù)據(jù)傳輸、退出(關閉)凡涩。

當TCP接收到另一端的數(shù)據(jù)時活箕,它會發(fā)送一個確認,但這個確認不會立即發(fā)送讹蘑,一般會延遲一會兒。ACK是累積的陨舱,一個確認字節(jié)號N的ACK表示所有直到N的字節(jié)(不包括N)已經(jīng)成功被接收了版仔。這樣的好處是如果一個ACK丟失蛮粮,很可能后續(xù)的ACK就足以確認前面的報文段了。

一個完整的TCP連接是雙向和對稱的然想,數(shù)據(jù)可以在兩個方向上平等地流動。給上層應用程序提供一種雙工服務令哟。一旦建立了一個連接屏富,這個連接的一個方向上的每個TCP報文段都包含了相反方向上的報文段的一個ACK。

序列號的作用是使得一個TCP接收端可丟棄重復的報文段狠半,記錄以雜亂次序到達的報文段神年。因為TCP使用IP來傳輸報文段瘤袖,而IP不提供重復消除或者保證次序正確的功能昂验。另一方面,TCP是一個字節(jié)流協(xié)議既琴,絕不會以雜亂的次序給上層程序發(fā)送數(shù)據(jù)甫恩。因此TCP接收端會被迫先保持大序列號的數(shù)據(jù)不交給應用程序酌予,直到缺失的小序列號的報文段被填滿奖慌。

TCP頭部

源端口和目的端口在TCP層確定雙方進程简僧,序列號表示的是報文段數(shù)據(jù)中的第一個字節(jié)號岛马,ACK表示確認號啦逆,該確認號的發(fā)送方期待接收的下一個序列號笛洛,即最后被成功接收的數(shù)據(jù)字節(jié)序列號加1,這個字段只有在ACK位被啟用的時候才有效盲镶。

當新建一個連接時蝌诡,從客戶端發(fā)送到服務端的第一個報文段的SYN位被啟用,這稱為SYN報文段宇色,這時序列號字段包含了在本次連接的這個方向上要使用的第一個序列號颁湖,即初始序列號ISN甥捺,之后發(fā)送的數(shù)據(jù)是ISN加1,因此SYN位字段會消耗一個序列號镰禾,這意味著使用重傳進行可靠傳輸。而不消耗序列號的ACK則不是屋休。

頭部長度(圖中的數(shù)據(jù)偏移)以32位字為單位备韧,也就是以4bytes為單位,它只有4位叠艳,最大為15附较,因此頭部最大長度為60字節(jié),而其最小為5声搁,也就是頭部最小為20字節(jié)(可變選項為空)捕发。

ACK —— 確認扎酷,使得確認號有效。 RST —— 重置連接(經(jīng)乘瘢看到的reset by?peer)就是此字段搞的鬼窃植。 SYN —— 用于初如化一個連接的序列號荐糜。?FIN?—— 該報文段的發(fā)送方已經(jīng)結(jié)束向?qū)Ψ桨l(fā)送數(shù)據(jù)。

當一個連接被建立或被終止時延塑,交換的報文段只包含TCP頭部关带,而沒有數(shù)據(jù)宋雏。

狀態(tài)轉(zhuǎn)換

三次握手和四次揮手的狀態(tài)轉(zhuǎn)換如下圖好芭。


為什么要“三次握手冲呢,四次揮手”敬拓?、


三次握手

換個易于理解的視角來看為什么要3次握手乘凸。

客戶端和服務端通信前要進行連接营勤,“3次握手”的作用就是雙方都能明確自己和對方的收、發(fā)能力是正常的葛作。

第一次握手:客戶端發(fā)送網(wǎng)絡包寿羞,服務端收到了。這樣服務端就能得出結(jié)論:客戶端的發(fā)送能力赂蠢、服務端的接收能力是正常的绪穆。

第二次握手:服務端發(fā)包,客戶端收到了虱岂。這樣客戶端就能得出結(jié)論:服務端的接收玖院、發(fā)送能力,客戶端的接收第岖、發(fā)送能力是正常的难菌。 從客戶端的視角來看,我接到了服務端發(fā)送過來的響應數(shù)據(jù)包蔑滓,說明服務端接收到了我在第一次握手時發(fā)送的網(wǎng)絡包扔傅,并且成功發(fā)送了響應數(shù)據(jù)包,這就說明烫饼,服務端的接收杠纵、發(fā)送能力正常铝量。而另一方面,我收到了服務端的響應數(shù)據(jù)包拍谐,說明我第一次發(fā)送的網(wǎng)絡包成功到達服務端,這樣晕翠,我自己的發(fā)送和接收能力也是正常的。

第三次握手:客戶端發(fā)包,服務端收到了简识。這樣服務端就能得出結(jié)論:客戶端的接收、發(fā)送能力,服務端的發(fā)送立由、接收能力是正常的。 第一、二次握手后荷逞,服務端并不知道客戶端的接收能力以及自己的發(fā)送能力是否正常。而在第三次握手時妙同,服務端收到了客戶端對第二次握手作的回應辉浦。從服務端的角度掂恕,我在第二次握手時的響應數(shù)據(jù)發(fā)送出去了,客戶端接收到了店枣。所以,我的發(fā)送能力是正常的。而客戶端的接收能力也是正常的。

經(jīng)歷了上面的三次握手過程帅韧,客戶端和服務端都確認了自己的接收璧亮、發(fā)送能力是正常的。之后就可以正常通信了镀裤。

每次都是接收到數(shù)據(jù)包的一方可以得到一些結(jié)論,發(fā)送的一方其實沒有任何頭緒。我雖然有發(fā)包的動作傅联,但是我怎么知道我有沒有發(fā)出去貌嫡,而對方有沒有接收到呢?

而從上面的過程可以看到,最少是需要三次握手過程的。兩次達不到讓雙方都得出自己、對方的接收、發(fā)送能力都正常的結(jié)論。其實每次收到網(wǎng)絡包的一方至少是可以得到:對方的發(fā)送、我方的接收是正常的之拨。而每一步都是有關聯(lián)的吉挣,下一次的“響應”是由于第一次的“請求”觸發(fā)马胧,因此每次握手其實是可以得到額外的結(jié)論的。比如第三次握手時,服務端收到數(shù)據(jù)包,表明看服務端只能得到客戶端的發(fā)送能力、服務端的接收能力是正常的想暗,但是結(jié)合第二次告唆,說明服務端在第二次發(fā)送的響應包懂牧,客戶端接收到了旋膳,并且作出了響應义图,從而得到額外的結(jié)論:客戶端的接收、服務端的發(fā)送是正常的。

用表格總結(jié)一下:

視角客收客發(fā)服收服發(fā)

客視角二一 + 二一 + 二二

服視角二 + 三一一二 + 三

四次揮手

TCP連接是雙向傳輸?shù)膶Φ鹊哪J降牛褪钦f雙方都可以同時向?qū)Ψ桨l(fā)送或接收數(shù)據(jù)借帘。當有一方要關閉連接時拾碌,會發(fā)送指令告知對方,我要關閉連接了豫柬。這時對方會回一個ACK烧给,此時一個方向的連接關閉榴鼎。但是另一個方向仍然可以繼續(xù)傳輸數(shù)據(jù)巫财,等到發(fā)送完了所有的數(shù)據(jù)后悍及,會發(fā)送一個FIN段來關閉此方向上的連接缨叫。接收方發(fā)送ACK確認關閉連接销钝。

注意,接收到FIN報文的一方只能回復一個ACK, 它是無法馬上返回對方一個FIN報文段的,因為結(jié)束數(shù)據(jù)傳輸?shù)摹爸噶睢笔巧蠈討脤咏o出的汤求,我只是一個“搬運工”,我無法了解“上層的意志”严拒。

“三次握手扬绪,四次揮手”怎么完成?

其實3次握手的目的并不只是讓通信雙方都了解到一個連接正在建立裤唠,還在于利用數(shù)據(jù)包的選項來傳輸特殊的信息挤牛,交換初始序列號ISN。

3次握手是指發(fā)送了3個報文段种蘸,4次揮手是指發(fā)送了4個報文段墓赴。注意,SYN和FIN段都是會利用重傳進行可靠傳輸?shù)摹?/p>

三次握手

客戶端發(fā)送一個SYN段劈彪,并指明客戶端的初始序列號竣蹦,即ISN(c).

服務端發(fā)送自己的SYN段作為應答,同樣指明自己的ISN(s)沧奴。為了確認客戶端的SYN痘括,將ISN(c)+1作為ACK數(shù)值。這樣,每發(fā)送一個SYN纲菌,序列號就會加1. 如果有丟失的情況挠日,則會重傳。

為了確認服務器端的SYN翰舌,客戶端將ISN(s)+1作為返回的ACK數(shù)值嚣潜。

四次揮手

客戶端發(fā)送一個FIN段,并包含一個希望接收者看到的自己當前的序列號K. 同時還包含一個ACK表示確認對方最近一次發(fā)過來的數(shù)據(jù)椅贱。

服務端將K值加1作為ACK序號值懂算,表明收到了上一個包。這時上層的應用程序會被告知另一端發(fā)起了關閉操作庇麦,通常這將引起應用程序發(fā)起自己的關閉操作计技。

服務端發(fā)起自己的FIN段,ACK=K+1, Seq=L 4. 客戶端確認山橄。ACK=L+1

為什么建立連接是三次握手垮媒,而關閉連接卻是四次揮手呢?

這是因為服務端在LISTEN狀態(tài)下航棱,收到建立連接請求的SYN報文后睡雇,把ACK和SYN放在一個報文里發(fā)送給客戶端。而關閉連接時饮醇,當收到對方的FIN報文時它抱,僅僅表示對方不再發(fā)送數(shù)據(jù)了但是還能接收數(shù)據(jù),己方是否現(xiàn)在關閉發(fā)送數(shù)據(jù)通道驳阎,需要上層應用來決定抗愁,因此,己方ACK和FIN一般都會分開發(fā)送呵晚。

“三次握手,四次揮手”進階

ISN

三次握手的一個重要功能是客戶端和服務端交換ISN(Initial Sequence Number), 以便讓對方知道接下來接收數(shù)據(jù)的時候如何按序列號組裝數(shù)據(jù)沫屡。

如果ISN是固定的饵隙,攻擊者很容易猜出后續(xù)的確認號。

ISN = M + F(localhost, localport, remotehost, remoteport)

M是一個計時器沮脖,每隔4毫秒加1金矛。F是一個Hash算法,根據(jù)源IP勺届、目的IP驶俊、源端口、目的端口生成一個隨機數(shù)值免姿。要保證hash算法不能被外部輕易推算得出饼酿。

序列號回繞

因為ISN是隨機的,所以序列號容易就會超過2^31-1. 而tcp對于丟包和亂序等問題的判斷都是依賴于序列號大小比較的。此時就出現(xiàn)了所謂的tcp序列號回繞(sequence wraparound)問題故俐。怎么解決想鹰?

/** The next routines deal with comparing 32 bit unsigned ints

* and worry about wraparound (automatic with unsigned arithmetic).*/

static inline int before(__u32 seq1, __u32 seq2){

return (__s32)(seq1-seq2) < 0;}

#define after(seq2, seq1) before(seq1, seq2)

上述代碼是內(nèi)核中的解決回繞問題代碼。s32是有符號整型的意思药版,而u32則是無符號整型辑舷。序列號發(fā)生回繞后,序列號變小槽片,相減之后何缓,把結(jié)果變成有符號數(shù)了,因此結(jié)果成了負數(shù)还栓。

假設seq1=255碌廓, seq2=1(發(fā)生了回繞)。

seq1 = 1111 1111 seq2 = 0000 0001

我們希望比較結(jié)果是

seq1 - seq2=

1111 1111

-0000 0001

1111 1110

由于我們將結(jié)果轉(zhuǎn)化成了有符號數(shù)蝙云,由于最高位是1氓皱,因此結(jié)果是一個負數(shù),負數(shù)的絕對值為

0000 0001 + 1 = 0000 0010 = 2

因此seq1 - seq2 < 0

syn flood攻擊

最基本的DoS攻擊就是利用合理的服務請求來占用過多的服務資源勃刨,從而使合法用戶無法得到服務的響應波材。syn flood屬于Dos攻擊的一種。

如果惡意的向某個服務器端口發(fā)送大量的SYN包身隐,則可以使服務器打開大量的半開連接廷区,分配TCB(Transmission Control Block), 從而消耗大量的服務器資源,同時也使得正常的連接請求無法被相應贾铝。當開放了一個TCP端口后隙轻,該端口就處于Listening狀態(tài),不停地監(jiān)視發(fā)到該端口的Syn報文垢揩,一 旦接收到Client發(fā)來的Syn報文玖绿,就需要為該請求分配一個TCB,通常一個TCB至少需要280個字節(jié)叁巨,在某些操作系統(tǒng)中TCB甚至需要1300個字節(jié)斑匪,并返回一個SYN ACK命令,立即轉(zhuǎn)為SYN-RECEIVED即半開連接狀態(tài)锋勺。系統(tǒng)會為此耗盡資源蚀瘸。

常見的防攻擊方法有:

無效連接的監(jiān)視釋放

監(jiān)視系統(tǒng)的半開連接和不活動連接,當達到一定閾值時拆除這些連接庶橱,從而釋放系統(tǒng)資源贮勃。這種方法對于所有的連接一視同仁,而且由于SYN Flood造成的半開連接數(shù)量很大苏章,正常連接請求也被淹沒在其中被這種方式誤釋放掉寂嘉,因此這種方法屬于入門級的SYN Flood方法。

延緩TCB分配方法

消耗服務器資源主要是因為當SYN數(shù)據(jù)報文一到達,系統(tǒng)立即分配TCB垫释,從而占用了資源丝格。而SYN Flood由于很難建立起正常連接,因此棵譬,當正常連接建立起來后再分配TCB則可以有效地減輕服務器資源的消耗显蝌。常見的方法是使用Syn Cache和Syn?Cookie技術。

Syn Cache技術:系統(tǒng)在收到一個SYN報文時订咸,在一個專用HASH表中保存這種半連接信息曼尊,直到收到正確的回應ACK報文再分配TCB。這個開銷遠小于TCB的開銷脏嚷。當然還需要保存序列號骆撇。

Syn Cookie技術:Syn Cookie技術則完全不使用任何存儲資源,這種方法比較巧妙父叙,它使用一種特殊的算法生成Sequence Number神郊,這種算法考慮到了對方的IP、端口趾唱、己方IP涌乳、端口的固定信息,以及對方無法知道而己方比較固定的一些信息甜癞,如MSS(Maximum Segment Size夕晓,最大報文段大小,指的是TCP報文的最大數(shù)據(jù)報長度悠咱,其中不包括TCP首部長度蒸辆。)、時間等析既,在收到對方 的ACK報文后躬贡,重新計算一遍,看其是否與對方回應報文中的(Sequence Number-1)相同眼坏,從而決定是否分配TCB資源逗宜。

使用SYN Proxy防火墻

一種方式是防止墻dqywb連接的有效性后,防火墻才會向內(nèi)部服務器發(fā)起SYN請求空骚。防火墻代服務器發(fā)出的SYN ACK包使用的序列號為c, 而真正的服務器回應的序列號為c', 這樣,在每個數(shù)據(jù)報文經(jīng)過防火墻的時候進行序列號的修改擂仍。另一種方式是防火墻確定了連接的安全后囤屹,會發(fā)出一個safe reset命令,client會進行重新連接逢渔,這時出現(xiàn)的syn報文會直接放行肋坚。這樣不需要修改序列號了。但是,client需要發(fā)起兩次握手過程智厌,因此建立連接的時間將會延長诲泌。

連接隊列

在外部請求到達時,被服務程序最終感知到前铣鹏,連接可能處于SYN_RCVD狀態(tài)或是ESTABLISHED狀態(tài)敷扫,但還未被應用程序接受。

對應地诚卸,服務器端也會維護兩種隊列葵第,處于SYN_RCVD狀態(tài)的半連接隊列,而處于ESTABLISHED狀態(tài)但仍未被應用程序accept的為全連接隊列合溺。如果這兩個隊列滿了之后卒密,就會出現(xiàn)各種丟包的情形。

查看是否有連接溢出

netstat -s | grep LISTEN

半連接隊列滿了

在三次握手協(xié)議中棠赛,服務器維護一個半連接隊列哮奇,該隊列為每個客戶端的SYN包開設一個條目(服務端在接收到SYN包的時候,就已經(jīng)創(chuàng)建了request_sock結(jié)構(gòu)睛约,存儲在半連接隊列中)鼎俘,該條目表明服務器已收到SYN包,并向客戶發(fā)出確認痰腮,正在等待客戶的確認包而芥。這些條目所標識的連接在服務器處于Syn_RECV狀態(tài),當服務器收到客戶的確認包時膀值,刪除該條目棍丐,服務器進入ESTABLISHED狀態(tài)。

目前沧踏,Linux下默認會進行5次重發(fā)SYN-ACK包歌逢,重試的間隔時間從1s開始,下次的重試間隔時間是前一次的雙倍翘狱,5次的重試時間間隔為1s, 2s, 4s, 8s, 16s, 總共31s, 稱為指數(shù)退避秘案,第5次發(fā)出后還要等32s才知道第5次也超時了,所以潦匈,總共需要 1s + 2s + 4s+ 8s+ 16s + 32s = 63s, TCP才會把斷開這個連接阱高。由于,SYN超時需要63秒茬缩,那么就給攻擊者一個攻擊服務器的機會赤惊,攻擊者在短時間內(nèi)發(fā)送大量的SYN包給Server(俗稱SYN flood攻擊),用于耗盡Server的SYN隊列凰锡。對于應對SYN 過多的問題未舟,linux提供了幾個TCP參數(shù):tcp_syncookies圈暗、tcp_synack_retries、tcp_max_syn_backlog裕膀、tcp_abort_on_overflow 來調(diào)整應對员串。

全連接隊列滿

當?shù)谌挝帐謺r,當server接收到ACK包之后昼扛,會進入一個新的叫 accept 的隊列寸齐。

當accept隊列滿了之后,即使client繼續(xù)向server發(fā)送ACK的包野揪,也會不被響應访忿,此時ListenOverflows+1,同時server通過tcp_abort_on_overflow來決定如何返回斯稳,0表示直接丟棄該ACK海铆,1表示發(fā)送RST通知client;相應的挣惰,client則會分別返回read timeout 或者 connection reset by peer卧斟。另外,tcp_abort_on_overflow是0的話憎茂,server過一段時間再次發(fā)送syn+ack給client(也就是重新走握手的第二步)珍语,如果client超時等待比較短,就很容易異常了竖幔。而客戶端收到多個 SYN ACK 包板乙,則會認為之前的 ACK 丟包了。于是促使客戶端再次發(fā)送 ACK 拳氢,在 accept隊列有空閑的時候最終完成連接募逞。若 accept隊列始終滿員,則最終客戶端收到 RST 包(此時服務端發(fā)送syn+ack的次數(shù)超出了tcp_synack_retries)馋评。

服務端僅僅只是創(chuàng)建一個定時器放接,以固定間隔重傳syn和ack到服務端:

命令

netstat -s命令

[root@server ~]# netstat -s | egrep "listen|LISTEN"?

667399 times the listen queue of a socket overflowed

667399 SYNs to LISTEN sockets ignored

上面看到的 667399 times ,表示全連接隊列溢出的次數(shù)留特,隔幾秒鐘執(zhí)行下纠脾,如果這個數(shù)字一直在增加的話肯定全連接隊列偶爾滿了。

[root@server ~]# netstat -s | grep TCPBacklogDrop

查看?Accept?queue 是否有溢出蜕青。

ss命令

[root@server ~]# ss -lnt

State Recv-Q Send-Q Local Address:Port?Peer?Address:Port

LISTEN 0 128 *:6379 *:*

LISTEN 0 128 *:22 *:*

如果State是listen狀態(tài)苟蹈,Send-Q 表示第三列的listen端口上的全連接隊列最大為50,第一列Recv-Q為全連接隊列當前使用了多少右核。 非 LISTEN 狀態(tài)中 Recv-Q 表示 receive queue 中的 bytes 數(shù)量汉操;Send-Q 表示 send queue 中的 bytes 數(shù)值。

小結(jié)

當外部連接請求到來時蒙兰,TCP模塊會首先查看max_syn_backlog磷瘤,如果處于SYN_RCVD狀態(tài)的連接數(shù)目超過這一閾值,進入的連接會被拒絕搜变。根據(jù)tcp_abort_on_overflow字段來決定是直接丟棄采缚,還是直接reset.

從服務端來說,三次握手中挠他,第一步server接受到client的syn后扳抽,把相關信息放到半連接隊列中,同時回復syn+ack給client. 第三步當收到客戶端的ack, 將連接加入到全連接隊列殖侵。

一般贸呢,全連接隊列比較小,會先滿拢军,此時半連接隊列還沒滿楞陷。如果這時收到syn報文,則會進入半連接隊列茉唉,沒有問題固蛾。但是如果收到了三次握手中的第3步(ACK),則會根據(jù)tcp_abort_on_overflow字段來決定是直接丟棄度陆,還是直接reset.此時艾凯,客戶端發(fā)送了ACK, 那么客戶端認為三次握手完成,它認為服務端已經(jīng)準備好了接收數(shù)據(jù)的準備懂傀。但此時服務端可能因為全連接隊列滿了而無法將連接放入趾诗,會重新發(fā)送第2步的syn+ack, 如果這時有數(shù)據(jù)到來,服務器TCP模塊會將數(shù)據(jù)存入隊列中蹬蚁。一段時間后恃泪,client端沒收到回復,超時缚忧,連接異常悟泵,client會主動關閉連接。

“三次握手闪水,四次揮手”Redis實例分析

我在dev機器上部署redis服務糕非,端口號為6379;

通過tcpdump工具獲取數(shù)據(jù)包球榆,使用如下命令:

tcpdump -w /tmp/a.cap port 6379 -s0

-w把數(shù)據(jù)寫入文件朽肥,-s0設置每個數(shù)據(jù)包的大小默認為68字節(jié),如果用-S 0則會抓到完整數(shù)據(jù)包

在dev2機器上用redis-cli訪問dev:6379持钉,發(fā)送一個ping衡招,得到回復pong;

停止抓包每强,用tcpdump讀取捕獲到的數(shù)據(jù)包:

tcpdump -r /tmp/a.cap -n -nn -A -x| vim -

(-x 以16進制形式展示始腾,便于后面分析)

共收到了7個包州刽。

抓到的是IP數(shù)據(jù)包,IP數(shù)據(jù)包分為IP頭部和IP數(shù)據(jù)部分浪箭,IP數(shù)據(jù)部分是TCP頭部加TCP數(shù)據(jù)部分穗椅。

IP的數(shù)據(jù)格式為:

它由固定長度20B+可變長度構(gòu)成。

10:55:45.662077 IP dev2.39070 > dev.6379: Flags [S], seq 4133153791, win 29200, options [mss 1460,sackOK,TS val 2959270704 ecr 0,nop,wscale 7], length 0

0x0000: 4500 003c 08cf 4000 3606 14a5 0ab3 b561?

0x0010: 0a60 5cd4 989e 18eb f65a ebff 0000 0000?

0x0020: a002 7210 872f 0000 0204 05b4 0402 080a?

0x0030: b062 e330 0000 0000 0103 0307?

對著IP頭部格式奶栖,來拆解數(shù)據(jù)包的具體含義匹表。

剩余的數(shù)據(jù)部分即為TCP協(xié)議相關的。TCP也是20B固定長度+可變長度部分宣鄙。

可變長度部分袍镀,協(xié)議如下:

這樣第一個包分析完了。dev2向dev發(fā)送SYN請求冻晤。也就是三次握手中的第一次了苇羡。 SYN seq(c)=4133153791

第二個包,dev響應連接,ack=4133153792. 表明dev下次準備接收這個序號的包,用于tcp字節(jié)注的順序控制胧华。dev(也就是server端)的初始序號為seq=4264776963, syn=1.?SYN?ack=seq(c)+1 seq(s)=4264776963

第三個包,client包確認绣硝,這里使用了相對值應答。seq=4133153792, 等于第二個包的ack. ack=4264776964. ack=seq(s)+1, seq=seq(c)+1 至此撑刺,三次握手完成鹉胖。接下來就是發(fā)送ping和pong的數(shù)據(jù)了。

接著第四個包够傍。

10:55:48.090073 IP dev2.39070 > dev.6379: Flags [P.], seq 1:15, ack 1, win 229, options [nop,nop,TS val 2959273132 ecr 3132256230], length 14

0x0000: 4500 0042 08d1 4000 3606 149d 0ab3 b561?

0x0010: 0a60 5cd4 989e 18eb f65a ec00 fe33 5504?

0x0020: 8018 00e5 4b5f 0000 0101 080a b062 ecac?

0x0030: bab2 6fe6 2a31 0d0a 2434 0d0a 7069 6e67?

0x0040: 0d0a?

tcp首部長度為32B, 可選長度為12B. IP報文的總長度為66B, 首部長度為20B, 因此TCP數(shù)據(jù)部分長度為14B. seq=0xf65a ec00=4133153792 ACK, PSH. 數(shù)據(jù)部分為2a31 0d0a 2434 0d0a 7069 6e67 0d0a:

0x2a31 -> *1

0x0d0a -> \r\n

0x2434 -> $4

0x0d0a -> \r\n

0x7069 0x6e67 -> ping

0x0d0a -> \r\n

dev2向dev發(fā)送了ping數(shù)據(jù)甫菠,第四個包完畢。

第五個包冕屯,dev2向dev發(fā)送ack響應寂诱。 序列號為0xfe33 5504=4264776964,?ack確認號為0xf65a ec0e=4133153806=(4133153792+14).

第六個包,dev向dev2響應pong消息安聘。序列號fe33 5504痰洒,確認號f65a ec0e,TCP頭部可選長度為12B浴韭,IP數(shù)據(jù)報總長度為59B丘喻,首部長度為20B,因此TCP數(shù)據(jù)長度為7B念颈。數(shù)據(jù)部分2b50 4f4e 470d 0a泉粉,翻譯過來就是+PONG\r\n。

至此,Redis客戶端和Server端的三次握手過程分析完畢嗡靡。

總結(jié)

“三次握手跺撼,四次揮手”看似簡單,但是深究進去叽躯,還是可以延伸出很多知識點的财边。比如半連接隊列、全連接隊列等等点骑。以前關于TCP建立連接、關閉連接的過程很容易就會忘記谍夭,可能是因為只是死記硬背了幾個過程黑滴,沒有深入研究背后的原理。

所以紧索,“三次握手袁辈,四次揮手”你真的懂了嗎?

“我自己是一名從事了5年前端的老程序員珠漂,辭職目前在做講師晚缩,今年年初我花了一個月整理了一份最適合2019年學習的web前端干貨,從最基礎的HTML+CSS+JS到移動端HTML5到各種框架都有整理媳危,送給每一位前端小伙伴荞彼,這里是小白聚集地,歡迎初學和進階中的小伙伴待笑。"

加微?:QD_666_QD

?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末鸣皂,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子暮蹂,更是在濱河造成了極大的恐慌寞缝,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,406評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件仰泻,死亡現(xiàn)場離奇詭異荆陆,居然都是意外死亡,警方通過查閱死者的電腦和手機集侯,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,732評論 3 393
  • 文/潘曉璐 我一進店門被啼,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人浅悉,你說我怎么就攤上這事趟据。” “怎么了术健?”我有些...
    開封第一講書人閱讀 163,711評論 0 353
  • 文/不壞的土叔 我叫張陵汹碱,是天一觀的道長。 經(jīng)常有香客問我荞估,道長咳促,這世上最難降的妖魔是什么稚新? 我笑而不...
    開封第一講書人閱讀 58,380評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮跪腹,結(jié)果婚禮上褂删,老公的妹妹穿的比我還像新娘。我一直安慰自己冲茸,他們只是感情好屯阀,可當我...
    茶點故事閱讀 67,432評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著轴术,像睡著了一般难衰。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上逗栽,一...
    開封第一講書人閱讀 51,301評論 1 301
  • 那天盖袭,我揣著相機與錄音,去河邊找鬼彼宠。 笑死鳄虱,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的凭峡。 我是一名探鬼主播拙已,決...
    沈念sama閱讀 40,145評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼想罕!你這毒婦竟也來了悠栓?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,008評論 0 276
  • 序言:老撾萬榮一對情侶失蹤按价,失蹤者是張志新(化名)和其女友劉穎惭适,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體楼镐,經(jīng)...
    沈念sama閱讀 45,443評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡癞志,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,649評論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了框产。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片凄杯。...
    茶點故事閱讀 39,795評論 1 347
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖秉宿,靈堂內(nèi)的尸體忽然破棺而出戒突,到底是詐尸還是另有隱情,我是刑警寧澤描睦,帶...
    沈念sama閱讀 35,501評論 5 345
  • 正文 年R本政府宣布膊存,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏隔崎。R本人自食惡果不足惜今艺,卻給世界環(huán)境...
    茶點故事閱讀 41,119評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望爵卒。 院中可真熱鬧虚缎,春花似錦、人聲如沸钓株。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,731評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽轴合。三九已至铲掐,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間值桩,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,865評論 1 269
  • 我被黑心中介騙來泰國打工豪椿, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留奔坟,地道東北人。 一個月前我還...
    沈念sama閱讀 47,899評論 2 370
  • 正文 我出身青樓搭盾,卻偏偏與公主長得像咳秉,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子鸯隅,可洞房花燭夜當晚...
    茶點故事閱讀 44,724評論 2 354

推薦閱讀更多精彩內(nèi)容