三次握手-四次揮手
三次握手

第一次握手: 客戶端給服務(wù)端發(fā)送一個
SYN(同步序列編號(Synchronize Sequence Numbers))報文。第二次握手: 服務(wù)端收到客戶端發(fā)送的
SYN報文后,進(jìn)行應(yīng)答,發(fā)送給客戶端一個SYN+ACK(確認(rèn)編號(Acknowledgement Number))報文。第三次握手: 客戶端收到
SYN+ACK報文后之后,會回應(yīng)服務(wù)端一個ACK報文。服務(wù)端收到客戶端
ACK報文后,三次握手建立完成。
1.為什么是三次握手?不能是兩次?
解釋一下為啥只有三次握手才能確認(rèn)雙方的接受與發(fā)送能力是否正常,而兩次卻不可以
第一次握手: 客戶端發(fā)送網(wǎng)絡(luò)包,服務(wù)端收到。這樣服務(wù)端可以得出結(jié)論:客戶端的發(fā)送能力正常,服務(wù)端的數(shù)據(jù)接收的也正常。
第二次握手: 服務(wù)端發(fā)送包,客戶端收到。這樣客戶端可以得出結(jié)論:服務(wù)端的接收能力正常,發(fā)送能力正常,客戶端的發(fā)送能力正常,接收能力正常。但是此時服務(wù)端并不能確認(rèn)客戶端的接收能力是否正常。
第三次握手: 客戶端發(fā)包,服務(wù)端收到,這樣服務(wù)端就可以得出結(jié)論:客戶端的接收/發(fā)送能力正常。服務(wù)端自己的發(fā)送/接收能力也正常。
說明
三次握手的過程中,客戶端和服務(wù)端的狀態(tài)也在發(fā)生變化:
開始狀態(tài):客戶端是處于
closed的狀態(tài),服務(wù)端是處于listen狀態(tài);第一次握手: 客戶端給服務(wù)端發(fā)送一個
SYN報文,并指明客戶端的初始化序列號ISN(c),此時客戶端的狀態(tài)處于SYN_Send狀態(tài);第二次握手: 服務(wù)端收到客戶端的
SYN報文之后,會以自己的SYN報文作為應(yīng)答,并指定了自己的初始化序列號ISN(s),同時會把客戶端的ISN+1作為ACK的值,表示服務(wù)端已經(jīng)收到了客戶端的SYN,此時服務(wù)端處于SYN_REVD的狀態(tài)。第三次握手: 客戶端收到服務(wù)端發(fā)送的
SYN報文之后,會應(yīng)答服務(wù)端發(fā)送一個ACK報文,同樣把服務(wù)端的ISN+1作為ACK的值,表示已經(jīng)收到服務(wù)端的SYN報文,此時客戶端處于establised的狀態(tài)。當(dāng)服務(wù)器收到客戶端的
ACK報文后,也處于establised狀態(tài),雙方建立鏈接完成。
1、確認(rèn)雙方的接受能力、發(fā)送能力是否正常。
2、指定自己的初始化序列號,為后面的可靠傳送做準(zhǔn)備。
3、如果是 https 協(xié)議的話,三次握手這個過程,還會進(jìn)行數(shù)字證書的驗(yàn)證以及加密密鑰的生成到。
2. TCP初始化序列號ISN
ISN(Initial Sequence Number) 是固定的嗎?
三次握手的一個重要功能是客戶端和服務(wù)端交換ISN,以便讓對方知道接下來接收數(shù)據(jù)的時候如何按序列號組裝數(shù)據(jù)。
TCP初始化序列號不能設(shè)置為一個固定值,因?yàn)檫@樣容易被攻擊者猜出后續(xù)序列號,從而遭到攻擊。
RFC1948(RFC 1948 序列號攻擊)中提出了一個較好的初始化序列號
ISN隨機(jī)生成算法。
ISN = M + F(localhost, localport, remotehost,remoteport).
M:是一個計時器,這個計時器每隔4微秒加1。
F:是一個Hash算法,根據(jù)源IP、目的IP、源端口、目的端口生成一個隨機(jī)數(shù)值。要保證hash算法不能被外部輕易推算得出,用MD5算法是一個比較好的選擇。
3. 什么是半連接隊(duì)列? 全連接隊(duì)里?
- 客戶端第一次發(fā)送SYN同步信號,客戶端處于
SYN_SEND,服務(wù)器第一次收到客戶端的SYN同步信號,然后服務(wù)端就會處于SYN_RCVD,此時雙方還沒有完全建立連接,服務(wù)器會把這種狀態(tài)的請求連接放在一個隊(duì)列里面,此隊(duì)列為半連接隊(duì)列。 - 已經(jīng)完成三次握手,建立起來的連接就會放到全連接隊(duì)里:全連接隊(duì)列,如果隊(duì)列滿了,則可能會出現(xiàn)丟包的現(xiàn)象。
- 在tcp連接的三次握手中最后一次中丟包:服務(wù)器收到
SYN包后發(fā)出SYN+ACK數(shù)據(jù)包,服務(wù)器進(jìn)入SYN_RECV狀態(tài)。這個時候客戶端發(fā)送ACK給服務(wù)器失敗了,服務(wù)器沒辦法進(jìn)入ESTABLISH狀態(tài),這個時候肯定不能傳輸數(shù)據(jù)的,不論客戶端主動發(fā)送數(shù)據(jù)與否,服務(wù)器都會有定時器發(fā)送第二步SYN+ACK數(shù)據(jù)包,如果客戶端再次發(fā)送ACK成功,建立連接。如果一直不成功,服務(wù)器會有超時(大概64s)設(shè)置,超時之后會給客戶端發(fā)RTS報文,進(jìn)入CLOSED狀態(tài),防止SYN洪泛攻擊,這個時候客戶端應(yīng)該也會關(guān)閉連接。
4. SYN-ACK 重傳次數(shù) 重傳
- 服務(wù)器發(fā)送完SYN+ACK包之后,如果未收到客戶端的確認(rèn)(ACK)包, 服務(wù)器就會進(jìn)行首次重傳,等待一段時間如果仍未收到客戶端確認(rèn)包,則進(jìn)行第二次重傳,... 如果重傳次數(shù)超過系統(tǒng)規(guī)定的最大重傳次數(shù)(
Server重發(fā)SYN+ACK包的次數(shù),可以通過設(shè)置/proc/sys/net/ipv4/tcp_synack_retries修改,默認(rèn)值為5),系統(tǒng)會將該連接的信息從半連接隊(duì)列中刪除。 - 每次重傳等待的時間不一定相同,一般會是指數(shù)增長:1s, 2s, 4s, 8s,...
- 但是Client認(rèn)為這個連接已經(jīng)建立,如果Client端向Server寫數(shù)據(jù),Server端將以RST包響應(yīng),方能感知到Server的錯誤。
5. 三次握手過程中可以修改數(shù)據(jù)嗎?
第一次、第二次握手不可以攜帶數(shù)據(jù)。
第三次 握手是可以攜帶數(shù)據(jù)的。
說明
1. 假如第一次握手可以攜帶數(shù)據(jù)的話,如果有人要惡意攻擊服務(wù)器,那他每次都在第一次握手中的 `SYN` 報文中放入大量的數(shù)據(jù),
因?yàn)楣粽吒揪筒焕矸?wù)器的接收、發(fā)送能力是否正常,然后瘋狂著重復(fù)發(fā) `SYN` 報文的話,這會讓服務(wù)器花費(fèi)很多時間、
內(nèi)存空間來接收這些報文。也就是說,第一次握手可以放數(shù)據(jù)的話,其中一個簡單的原因就是會讓服務(wù)器更加容易受到攻擊了。
2. 第三次的話,此時客戶端已經(jīng)處于 `established` 狀態(tài),也就是說,對于客戶端來說,已經(jīng)建立起連接了,
并且也已經(jīng)知道服務(wù)器的接收、發(fā)送能力是正常的了,所以能攜帶數(shù)據(jù)頁沒啥毛病。
四次揮手
- 對方一個
FIN報文,我方一個ACK報文,再我方一個FIN報文,對方一個ACK報文。

說明
初始階段:雙方都處于establised,假如是客戶端先發(fā)起關(guān)閉請求:
第一次:客戶端發(fā)送一個
FIN報文,報文中指定一個序列號,此時客戶端處于FIN_WAIT1狀態(tài)。第二次:服務(wù)端收到客戶端的
FIN報文后,會發(fā)送應(yīng)答ACK報文,且把客戶端的序列號值 + 1作為應(yīng)答ACK報文的序列值,表明已經(jīng)收到客戶端的報文,此時服務(wù)端處于CLOSE_WAIT2狀態(tài)??蛻舳耸盏椒?wù)端的ACK應(yīng)答報文后,處于FIN_WAIT2狀態(tài)。第三次:服務(wù)端想斷開連接,發(fā)送給客戶端
FIN報文,且指定一個序列號,此時服務(wù)端處于LAST_ACK狀態(tài)。第四次:當(dāng)客戶端收到服務(wù)端
FIN報文后,一樣發(fā)送一個應(yīng)答ACK報文作為應(yīng)答,且把服務(wù)端發(fā)送的序列號值+1 作為自己ACK應(yīng)答報文的序列號值,此時客戶端處于TIME_WAIT。需要等一段時間確保服務(wù)端收到自己的ACK報文之后進(jìn)入CLOSED狀態(tài)。服務(wù)端收到客戶端
ACK應(yīng)答報文后,就處于關(guān)閉CLOSED狀態(tài)LISTEN- 偵聽來自遠(yuǎn)方TCP端口的連接請求;SYN-SENT-在發(fā)送連接請求后等待匹配的連接請求;SYN-RECEIVED- 在收到和發(fā)送一個連接請求后等待對連接請求的確認(rèn);ESTABLISHED- 代表一個打開的連接,數(shù)據(jù)可以傳送給用戶;FIN-WAIT-1-FIN_WAIT_1狀態(tài)實(shí)際上是當(dāng)SOCKET在ESTABLISHED狀態(tài)時,它想主動關(guān)閉連接,向?qū)Ψ桨l(fā)送了FIN報文,此時該SOCKET即進(jìn)入到FIN_WAIT_1狀態(tài)。當(dāng)對方回應(yīng)ACK報文后,則進(jìn)入到FIN_WAIT_2狀態(tài),當(dāng)然在實(shí)際的正常情況下,無論對方何種情況下,都應(yīng)該馬上回應(yīng)ACK報文,所以FIN_WAIT_1狀態(tài)一般是比較難見到的,而FIN_WAIT_2狀態(tài)還有時常常可以用netstat看到。FIN-WAIT-2- 從遠(yuǎn)程TCP等待連接中斷請求,實(shí)際上FIN_WAIT_2狀態(tài)下的SOCKET,表示半連接,也即有一方要求close連接,但另外還告訴對方,我暫時還有點(diǎn)數(shù)據(jù)需要傳送給你,稍后再關(guān)閉連接。;LAST-ACK- 等待原來發(fā)向遠(yuǎn)程TCP的連接中斷請求的確認(rèn);TIME-WAIT-等待足夠的時間以確保遠(yuǎn)程TCP接收到連接中斷請求的確認(rèn),表示收到了對方的FIN報文,并發(fā)送出了ACK報文,就等2MSL后即可回到CLOSED可用狀態(tài)了。如果FIN_WAIT_1狀態(tài)下,收到了對方同時帶FIN標(biāo)志和ACK標(biāo)志的報文時,可以直接進(jìn)入到TIME_WAIT狀態(tài),而無須經(jīng)過FIN_WAIT_2狀態(tài)。CLOSED- 沒有任何連接狀態(tài);這個表示初始狀態(tài)。CLOSE-WAIT- 這種狀態(tài)的含義其實(shí)是表示在等待關(guān)閉。當(dāng)對方close一個SOCKET后發(fā)送FIN報文給自己,你系統(tǒng)毫無疑問地會回應(yīng)一個ACK報文給對方,此時則進(jìn)入到CLOSE_WAIT狀態(tài)。接下來呢 ,實(shí)際上你真正需要考慮的事情是察看你是否還有數(shù)據(jù)發(fā)送給對方,如果沒有的話,那么你也就可以close這個SOCKET,發(fā)送FIN報文給對方,也即關(guān)閉連接。所以你在CLOSE_WAIT狀態(tài)下,需要完成的事情是等待你去關(guān)閉連接CLOSING-這種狀態(tài)比較特殊,實(shí)際情況中應(yīng)該是很少見,屬于一種比較罕見的例外狀態(tài)。正常情況下,當(dāng)你發(fā)送FIN報文后,按理來說是應(yīng)該先收到(或同時收到)對方的ACK報文,再收到對方的FIN報文。但是CLOSING狀態(tài)表示你發(fā)送FIN報文后,并沒有收到對方的ACK報文,反而卻也收到了對方的FIN報文。什么情況下會出現(xiàn)此種情況呢?其實(shí)細(xì)想一下,也不難得出結(jié)論:那就是如果雙方幾乎在同時close一個SOCKET的話,那么就出現(xiàn)了雙方同時發(fā)送FIN報文的情況,也即會出現(xiàn)CLOSING狀態(tài),表示雙方都正在關(guān)閉SOCKET連接。
注意
注:`MSL`(最大分段生存期)指明TCP報文在Internet上最長生存時間,
每個具體的TCP實(shí)現(xiàn)都必須選擇一個確定的`MSL`值.RFC 1122建議是2分鐘,
但BSD傳統(tǒng)實(shí)現(xiàn)采用了30秒.TIME_WAIT 狀態(tài)最大保持時間是2 * MSL,也就是1-4分鐘