Session和cookie應該如何去選擇適用場景?
54、瀏覽器在與服務器建立了一個 TCP 連接后是否會在一個 HTTP 請求完成后斷開?什么情況下會斷開?
在 HTTP/1.0 中,一個服務器在發(fā)送完一個 HTTP 響應后,會斷開 TCP 鏈接。但是這樣每次請求都會重新建立和斷開 TCP 連接,代價過大。所以雖然標準中沒有設定,某些服務器對 Connection: keep-alive 的 Header 進行了支持。意思是說,完成這個 HTTP 請求之后,不要斷開 HTTP 請求使用的 TCP 連接。這樣的好處是連接可以被重新使用,之后發(fā)送 HTTP 請求的時候不需要重新建立 TCP 連接,以及如果維持連接,那么 SSL 的開銷也可以避免。
持久連接:既然維持 TCP 連接好處這么多,HTTP/1.1 就把 Connection 頭寫進標準,并且默認開啟持久連接,除非請求中寫明 Connection: close,那么瀏覽器和服務器之間是會維持一段時間的 TCP 連接,不會一個請求結束就斷掉。
默認情況下建立 TCP 連接不會斷開,只有在請求報頭中聲明 Connection: close 才會在請求完成后關閉連接。
55、三次握手相關內(nèi)容
三次握手(Three-way Handshake)其實就是指建立一個TCP連接時,需要客戶端和服務器總共發(fā)送3個包。進行三次握手的主要作用就是為了確認雙方的接收能力和發(fā)送能力是否正常、指定自己的初始化序列號為后面的可靠性傳送做準備。實質(zhì)上其實就是連接服務器指定端口,建立TCP連接,并同步連接雙方的序列號和確認號,交換TCP窗口大小信息。
第一種回答
剛開始客戶端處于 Closed 的狀態(tài),服務端處于 Listen 狀態(tài),進行三次握手:
第一次握手:客戶端給服務端發(fā)一個 SYN 報文,并指明客戶端的初始化序列號 ISN(c)。此時客戶端處于 SYN_SEND 狀態(tài)。
首部的同步位SYN=1,初始序號seq=x,SYN=1的報文段不能攜帶數(shù)據(jù),但要消耗掉一個序號。
第二次握手:服務器收到客戶端的 SYN 報文之后,會以自己的 SYN 報文作為應答,并且也是指定了自己的初始化序列號 ISN(s)。同時會把客戶端的 ISN + 1 作為ACK 的值,表示自己已經(jīng)收到了客戶端的 SYN,此時服務器處于 SYN_RCVD 的狀態(tài)。
在確認報文段中SYN=1,ACK=1,確認號ack=x+1,初始序號seq=y(tǒng)。
第三次握手:客戶端收到 SYN 報文之后,會發(fā)送一個 ACK 報文,當然,也是一樣把服務器的 ISN + 1 作為 ACK 的值,表示已經(jīng)收到了服務端的 SYN 報文,此時客戶端處于 ESTABLISHED 狀態(tài)。服務器收到 ACK 報文之后,也處于 ESTABLISHED 狀態(tài),此時,雙方已建立起了連接。
確認報文段ACK=1,確認號ack=y(tǒng)+1,序號seq=x+1(初始為seq=x,第二個報文段所以要+1),ACK報文段可以攜帶數(shù)據(jù),不攜帶數(shù)據(jù)則不消耗序號。
發(fā)送第一個SYN的一端將執(zhí)行主動打開(active open),接收這個SYN并發(fā)回下一個SYN的另一端執(zhí)行被動打開(passive open)。
在socket編程中,客戶端執(zhí)行connect()時,將觸發(fā)三次握手。
第二種回答初始狀態(tài):客戶端處于 closed(關閉)狀態(tài),服務器處于 listen(監(jiān)聽) 狀態(tài)。第一次握手:客戶端發(fā)送請求報文將 SYN = 1同步序列號和初始化序列號seq = x發(fā)送給服務端,發(fā)送完之后客戶端處于SYN_Send狀態(tài)。(驗證了客戶端的發(fā)送能力和服務端的接收能力)第二次握手:服務端受到 SYN 請求報文之后,如果同意連接,會以自己的同步序列號SYN(服務端) = 1、初始化序列號 seq = y和確認序列號(期望下次收到的數(shù)據(jù)包)ack = x+ 1 以及確認號ACK = 1報文作為應答,服務器為SYN_Receive狀態(tài)。(問題來了,兩次握手之后,站在客戶端角度上思考:我發(fā)送和接收都ok,服務端的發(fā)送和接收也都ok。但是站在服務端的角度思考:哎呀,我服務端接收ok,但是我不清楚我的發(fā)送ok不ok呀,而且我還不知道你接受能力如何呢?所以老哥,你需要給我三次握手來傳個話告訴我一聲。你要是不告訴我,萬一我認為你跑了,然后我可能出于安全性的考慮繼續(xù)給你發(fā)一次,看看你回不回我。)第三次握手:客戶端接收到服務端的 SYN + ACK之后,知道可以下次可以發(fā)送了下一序列的數(shù)據(jù)包了,然后發(fā)送同步序列號 ack = y + 1和數(shù)據(jù)包的序列號 seq = x + 1以及確認號ACK = 1確認包作為應答,客戶端轉(zhuǎn)為established狀態(tài)。(分別站在雙方的角度上思考,各自ok)
56、為什么需要三次握手,兩次不行嗎?
弄清這個問題,我們需要先弄明白三次握手的目的是什么,能不能只用兩次握手來達到同樣的目的。
第一次握手:客戶端發(fā)送網(wǎng)絡包,服務端收到了。這樣服務端就能得出結論:客戶端的發(fā)送能力、服務端的接收能力是正常的。第二次握手:服務端發(fā)包,客戶端收到了。這樣客戶端就能得出結論:服務端的接收、發(fā)送能力,客戶端的接收、發(fā)送能力是正常的。不過此時服務器并不能確認客戶端的接收能力是否正常。第三次握手:客戶端發(fā)包,服務端收到了。這樣服務端就能得出結論:客戶端的接收、發(fā)送能力正常,服務器自己的發(fā)送、接收能力也正常。
因此,需要三次握手才能確認雙方的接收與發(fā)送能力是否正常。
試想如果是用兩次握手,則會出現(xiàn)下面這種情況:
如客戶端發(fā)出連接請求,但因連接請求報文丟失而未收到確認,于是客戶端再重傳一次連接請求。后來收到了確認,建立了連接。數(shù)據(jù)傳輸完畢后,就釋放了連接,客戶端共發(fā)出了兩個連接請求報文段,其中第一個丟失,第二個到達了服務端,但是第一個丟失的報文段只是在某些網(wǎng)絡結點長時間滯留了,延誤到連接釋放以后的某個時間才到達服務端,此時服務端誤認為客戶端又發(fā)出一次新的連接請求,于是就向客戶端發(fā)出確認報文段,同意建立連接,不采用三次握手,只要服務端發(fā)出確認,就建立新的連接了,此時客戶端忽略服務端發(fā)來的確認,也不發(fā)送數(shù)據(jù),則服務端一致等待客戶端發(fā)送數(shù)據(jù),浪費資源。
57、什么是半連接隊列?
服務器第一次收到客戶端的 SYN 之后,就會處于 SYN_RCVD 狀態(tài),此時雙方還沒有完全建立其連接,服務器會把此種狀態(tài)下請求連接放在一個隊列里,我們把這種隊列稱之為半連接隊列。
當然還有一個全連接隊列,就是已經(jīng)完成三次握手,建立起連接的就會放在全連接隊列中。如果隊列滿了就有可能會出現(xiàn)丟包現(xiàn)象。
這里在補充一點關于SYN-ACK 重傳次數(shù)的問題:服務器發(fā)送完SYN-ACK包,如果未收到客戶確認包,服務器進行首次重傳,等待一段時間仍未收到客戶確認包,進行第二次重傳。如果重傳次數(shù)超過系統(tǒng)規(guī)定的最大重傳次數(shù),系統(tǒng)將該連接信息從半連接隊列中刪除。注意,每次重傳等待的時間不一定相同,一般會是指數(shù)增長,例如間隔時間為 1s,2s,4s,8s......
58、 ISN(Initial Sequence Number)是固定的嗎?
當一端為建立連接而發(fā)送它的SYN時,它為連接選擇一個初始序號。ISN隨時間而變化,因此每個連接都將具有不同的ISN。ISN可以看作是一個32比特的計數(shù)器,每4ms加1 。這樣選擇序號的目的在于防止在網(wǎng)絡中被延遲的分組在以后又被傳送,而導致某個連接的一方對它做錯誤的解釋。
三次握手的其中一個重要功能是客戶端和服務端交換 ISN(Initial Sequence Number),以便讓對方知道接下來接收數(shù)據(jù)的時候如何按序列號組裝數(shù)據(jù)。如果 ISN 是固定的,攻擊者很容易猜出后續(xù)的確認號,因此 ISN 是動態(tài)生成的。
59、 三次握手過程中可以攜帶數(shù)據(jù)嗎?
其實第三次握手的時候,是可以攜帶數(shù)據(jù)的。但是,第一次、第二次握手不可以攜帶數(shù)據(jù)
為什么這樣呢?大家可以想一個問題,假如第一次握手可以攜帶數(shù)據(jù)的話,如果有人要惡意攻擊服務器,那他每次都在第一次握手中的 SYN 報文中放入大量的數(shù)據(jù)。因為攻擊者根本就不理服務器的接收、發(fā)送能力是否正常,然后瘋狂著重復發(fā) SYN 報文的話,這會讓服務器花費很多時間、內(nèi)存空間來接收這些報文。
也就是說,第一次握手不可以放數(shù)據(jù),其中一個簡單的原因就是會讓服務器更加容易受到攻擊了。而對于第三次的話,此時客戶端已經(jīng)處于 ESTABLISHED 狀態(tài)。對于客戶端來說,他已經(jīng)建立起連接了,并且也已經(jīng)知道服務器的接收、發(fā)送能力是正常的了,所以能攜帶數(shù)據(jù)也沒啥毛病。
60、SYN攻擊是什么?
服務器端的資源分配是在二次握手時分配的,而客戶端的資源是在完成三次握手時分配的,所以服務器容易受到SYN洪泛攻擊。SYN攻擊就是Client在短時間內(nèi)偽造大量不存在的IP地址,并向Server不斷地發(fā)送SYN包,Server則回復確認包,并等待Client確認,由于源地址不存在,因此Server需要不斷重發(fā)直至超時,這些偽造的SYN包將長時間占用未連接隊列,導致正常的SYN請求因為隊列滿而被丟棄,從而引起網(wǎng)絡擁塞甚至系統(tǒng)癱瘓。SYN 攻擊是一種典型的 DoS/DDoS 攻擊。
檢測 SYN 攻擊非常的方便,當你在服務器上看到大量的半連接狀態(tài)時,特別是源IP地址是隨機的,基本上可以斷定這是一次SYN攻擊。在 Linux/Unix 上可以使用系統(tǒng)自帶的 netstats 命令來檢測 SYN 攻擊。
netstat -n -p TCP | grep SYN_RECV
復制代碼
常見的防御 SYN 攻擊的方法有如下幾種:
縮短超時(SYN Timeout)時間增加最大半連接數(shù)過濾網(wǎng)關防護SYN cookies技術
61、 四次揮手相關內(nèi)容
建立一個連接需要三次握手,而終止一個連接要經(jīng)過四次揮手(也有將四次揮手叫做四次握手的)。這由TCP的半關閉(half-close)造成的。所謂的半關閉,其實就是TCP提供了連接的一端在結束它的發(fā)送后還能接收來自另一端數(shù)據(jù)的能力。
TCP 的連接的拆除需要發(fā)送四個包,因此稱為四次揮手(Four-way handshake),客戶端或服務器均可主動發(fā)起揮手動作。
第一種回答
剛開始雙方都處于 ESTABLISHED 狀態(tài),假如是客戶端先發(fā)起關閉請求。四次揮手的過程如下:
第一次揮手:客戶端發(fā)送一個 FIN 報文,報文中會指定一個序列號。此時客戶端處于 FIN_WAIT1 狀態(tài)。即發(fā)出連接釋放報文段(FIN=1,序號seq=u),并停止再發(fā)送數(shù)據(jù),主動關閉TCP連接,進入FIN_WAIT1(終止等待1)狀態(tài),等待服務端的確認。第二次揮手:服務端收到 FIN 之后,會發(fā)送 ACK 報文,且把客戶端的序列號值 +1 作為 ACK 報文的序列號值,表明已經(jīng)收到客戶端的報文了,此時服務端處于 CLOSE_WAIT 狀態(tài)。即服務端收到連接釋放報文段后即發(fā)出確認報文段(ACK=1,確認號ack=u+1,序號seq=v),服務端進入CLOSE_WAIT(關閉等待)狀態(tài),此時的TCP處于半關閉狀態(tài),客戶端到服務端的連接釋放?蛻舳耸盏椒⻊斩说拇_認后,進入FIN_WAIT2(終止等待2)狀態(tài),等待服務端發(fā)出的連接釋放報文段。第三次揮手:如果服務端也想斷開連接了,和客戶端的第一次揮手一樣,發(fā)給 FIN 報文,且指定一個序列號。此時服務端處于 LAST_ACK 的狀態(tài)。即服務端沒有要向客戶端發(fā)出的數(shù)據(jù),服務端發(fā)出連接釋放報文段(FIN=1,ACK=1,序號seq=w,確認號ack=u+1),服務端進入LAST_ACK(最后確認)狀態(tài),等待客戶端的確認。第四次揮手:客戶端收到 FIN 之后,一樣發(fā)送一個 ACK 報文作為應答,且把服務端的序列號值 +1 作為自己 ACK 報文的序列號值,此時客戶端處于 TIME_WAIT 狀態(tài)。需要過一陣子以確保服務端收到自己的 ACK 報文之后才會進入 CLOSED 狀態(tài),服務端收到 ACK 報文之后,就處于關閉連接了,處于 CLOSED 狀態(tài)。即客戶端收到服務端的連接釋放報文段后,對此發(fā)出確認報文段(ACK=1,seq=u+1,ack=w+1),客戶端進入TIME_WAIT(時間等待)狀態(tài)。此時TCP未釋放掉,需要經(jīng)過時間等待計時器設置的時間2MSL后,客戶端才進入CLOSED狀態(tài)。
收到一個FIN只意味著在這一方向上沒有數(shù)據(jù)流動?蛻舳藞(zhí)行主動關閉并進入TIME_WAIT是正常的,服務端通常執(zhí)行被動關閉,不會進入TIME_WAIT狀態(tài)。
在socket編程中,任何一方執(zhí)行close()操作即可產(chǎn)生揮手操作。
第二種回答初始化狀態(tài):客戶端和服務端都在連接狀態(tài),接下來開始進行四次分手斷開連接操作。第一次分手:第一次分手無論是客戶端還是服務端都可以發(fā)起,因為 TCP 是全雙工的!
假如客戶端發(fā)送的數(shù)據(jù)已經(jīng)發(fā)送完畢,發(fā)送FIN = 1 告訴服務端,客戶端所有數(shù)據(jù)已經(jīng)全發(fā)完了,服務端你可以關閉接收了,但是如果你們服務端有數(shù)據(jù)要發(fā)給客戶端,客戶端照樣可以接收的。此時客戶端處于FIN = 1等待服務端確認釋放連接狀態(tài)。
第二次分手:服務端接收到客戶端的釋放請求連接之后,知道客戶端沒有數(shù)據(jù)要發(fā)給自己了,然后服務端發(fā)送ACK = 1告訴客戶端收到你發(fā)給我的信息,此時服務端處于 CLOSE_WAIT 等待關閉狀態(tài)。(服務端先回應給客戶端一聲,我知道了,但服務端的發(fā)送數(shù)據(jù)能力即將等待關閉,于是接下來第三次就來了。)第三次分手:此時服務端向客戶端把所有的數(shù)據(jù)發(fā)送完了,然后發(fā)送一個FIN = 1,用于告訴客戶端,服務端的所有數(shù)據(jù)發(fā)送完畢,客戶端你也可以關閉接收數(shù)據(jù)連接了。此時服務端狀態(tài)處于LAST_ACK狀態(tài),來等待確認客戶端是否收到了自己的請求。(服務端等客戶端回復是否收到呢,不收到的話,服務端不知道客戶端是不是掛掉了還是咋回事呢,所以服務端不敢關閉自己的接收能力,于是第四次就來了。)第四次分手:此時如果客戶端收到了服務端發(fā)送完的信息之后,就發(fā)送ACK = 1,告訴服務端,客戶端已經(jīng)收到了你的信息。有一個 2 MSL 的延遲等待。
62、揮手為什么需要四次?
第一種回答
因為當服務端收到客戶端的SYN連接請求報文后,可以直接發(fā)送SYN+ACK報文。其中ACK報文是用來應答的,SYN報文是用來同步的。但是關閉連接時,當服務端收到FIN報文時,很可能并不會立即關閉SOCKET,所以只能先回復一個ACK報文,告訴客戶端,"你發(fā)的FIN報文我收到了"。只有等到我服務端所有的報文都發(fā)送完了,我才能發(fā)送FIN報文,因此不能一起發(fā)送。故需要四次揮手。
第二種回答
任何一方都可以在數(shù)據(jù)傳送結束后發(fā)出連接釋放的通知,待對方確認后進入半關閉狀態(tài)。當另一方也沒有數(shù)據(jù)再發(fā)送的時候,則發(fā)出連接釋放通知,對方確認后就完全關閉了TCP連接。舉個例子:A 和 B 打電話,通話即將結束后,A 說“我沒啥要說的了”,B回答“我知道了”,但是 B 可能還會有要說的話,A 不能要求 B 跟著自己的節(jié)奏結束通話,于是 B 可能又巴拉巴拉說了一通,最后 B 說“我說完了”,A 回答“知道了”,這樣通話才算結束。
63、2MSL等待狀態(tài)?
TIME_WAIT狀態(tài)也成為2MSL等待狀態(tài)。每個具體TCP實現(xiàn)必須選擇一個報文段最大生存時間MSL(Maximum Segment Lifetime),它是任何報文段被丟棄前在網(wǎng)絡內(nèi)的最長時間。這個時間是有限的,因為TCP報文段以IP數(shù)據(jù)報在網(wǎng)絡內(nèi)傳輸,而IP數(shù)據(jù)報則有限制其生存時間的TTL字段。
對一個具體實現(xiàn)所給定的MSL值,處理的原則是:當TCP執(zhí)行一個主動關閉,并發(fā)回最后一個ACK,該連接必須在TIME_WAIT狀態(tài)停留的時間為2倍的MSL。這樣可讓TCP再次發(fā)送最后的ACK以防這個ACK丟失(另一端超時并重發(fā)最后的FIN)。
這種2MSL等待的另一個結果是這個TCP連接在2MSL等待期間,定義這個連接的插口(客戶的IP地址和端口號,服務器的IP地址和端口號)不能再被使用。這個連接只能在2MSL結束后才能再被使用。
64、四次揮手釋放連接時,等待2MSL的意義?
MSL是Maximum Segment Lifetime的英文縮寫,可譯為“最長報文段壽命”,它是任何報文在網(wǎng)絡上存在的最長時間,超過這個時間報文將被丟棄。
為了保證客戶端發(fā)送的最后一個ACK報文段能夠到達服務器。因為這個ACK有可能丟失,從而導致處在LAST-ACK狀態(tài)的服務器收不到對FIN-ACK的確認報文。服務器會超時重傳這個FIN-ACK,接著客戶端再重傳一次確認,重新啟動時間等待計時器。最后客戶端和服務器都能正常的關閉。假設客戶端不等待2MSL,而是在發(fā)送完ACK之后直接釋放關閉,一但這個ACK丟失的話,服務器就無法正常的進入關閉連接狀態(tài)。
兩個理由保證客戶端發(fā)送的最后一個ACK報文段能夠到達服務端。這個ACK報文段有可能丟失,使得處于LAST-ACK狀態(tài)的B收不到對已發(fā)送的FIN+ACK報文段的確認,服務端超時重傳FIN+ACK報文段,而客戶端能在2MSL時間內(nèi)收到這個重傳的FIN+ACK報文段,接著客戶端重傳一次確認,重新啟動2MSL計時器,最后客戶端和服務端都進入到CLOSED狀態(tài),若客戶端在TIME-WAIT狀態(tài)不等待一段時間,而是發(fā)送完ACK報文段后立即釋放連接,則無法收到服務端重傳的FIN+ACK報文段,所以不會再發(fā)送一次確認報文段,則服務端無法正常進入到CLOSED狀態(tài)。防止“已失效的連接請求報文段”出現(xiàn)在本連接中。客戶端在發(fā)送完最后一個ACK報文段后,再經(jīng)過2MSL,就可以使本連接持續(xù)的時間內(nèi)所產(chǎn)生的所有報文段都從網(wǎng)絡中消失,使下一個新的連接中不會出現(xiàn)這種舊的連接請求報文段。
65、為什么TIME_WAIT狀態(tài)需要經(jīng)過2MSL才能返回到CLOSE狀態(tài)?
第一種回答
理論上,四個報文都發(fā)送完畢,就可以直接進入CLOSE狀態(tài)了,但是可能網(wǎng)絡是不可靠的,有可能最后一個ACK丟失。所以TIME_WAIT狀態(tài)就是用來重發(fā)可能丟失的ACK報文。
第二種回答
對應這樣一種情況,最后客戶端發(fā)送的ACK = 1給服務端的過程中丟失了,服務端沒收到,服務端怎么認為的?我已經(jīng)發(fā)送完數(shù)據(jù)了,怎么客戶端沒回應我?是不是中途丟失了?然后服務端再次發(fā)起斷開連接的請求,一個來回就是2MSL。
客戶端給服務端發(fā)送的ACK = 1丟失,服務端等待 1MSL沒收到,然后重新發(fā)送消息需要1MSL。如果再次接收到服務端的消息,則重啟2MSL計時器,發(fā)送確認請求?蛻舳酥恍璧却2MSL,如果沒有再次收到服務端的消息,就說明服務端已經(jīng)接收到自己確認消息;此時雙方都關閉的連接,TCP 四次分手完畢
66、TCP粘包問題是什么?你會如何去解決它?
TCP粘包是指發(fā)送方發(fā)送的若干包數(shù)據(jù)到接收方接收時粘成一包,從接收緩沖區(qū)看,后一包數(shù)據(jù)的頭緊接著前一包數(shù)據(jù)的尾。
由TCP連接復用造成的粘包問題。因為TCP默認會使用Nagle算法,此算法會導致粘包問題。只有上一個分組得到確認,才會發(fā)送下一個分組;收集多個小分組,在一個確認到來時一起發(fā)送。數(shù)據(jù)包過大造成的粘包問題。流量控制,擁塞控制也可能導致粘包。接收方不及時接收緩沖區(qū)的包,造成多個包接收
解決:
Nagle算法問題導致的,需要結合應用場景適當關閉該算法尾部標記序列。通過特殊標識符表示數(shù)據(jù)包的邊界,例如, ,或者一些隱藏字符。頭部標記分步接收。在TCP報文的頭部加上表示數(shù)據(jù)長度。應用層發(fā)送數(shù)據(jù)時定長發(fā)送。結語
嗯,到這里就結束了。
PDF還沒更新哈,還是上次的,下篇更完再出 PDF 版本好了,哈哈。
請輸入評論內(nèi)容...
請輸入評論/評論長度6~500個字
最新活動更多
-
10月31日立即下載>> 【限時免費下載】TE暖通空調(diào)系統(tǒng)高效可靠的組件解決方案
-
即日-11.13立即報名>>> 【在線會議】多物理場仿真助跑新能源汽車
-
11月28日立即報名>>> 2024工程師系列—工業(yè)電子技術在線會議
-
12月19日立即報名>> 【線下會議】OFweek 2024(第九屆)物聯(lián)網(wǎng)產(chǎn)業(yè)大會
-
即日-12.26火熱報名中>> OFweek2024中國智造CIO在線峰會
-
即日-2025.8.1立即下載>> 《2024智能制造產(chǎn)業(yè)高端化、智能化、綠色化發(fā)展藍皮書》
推薦專題
- 高級軟件工程師 廣東省/深圳市
- 自動化高級工程師 廣東省/深圳市
- 光器件研發(fā)工程師 福建省/福州市
- 銷售總監(jiān)(光器件) 北京市/海淀區(qū)
- 激光器高級銷售經(jīng)理 上海市/虹口區(qū)
- 光器件物理工程師 北京市/海淀區(qū)
- 激光研發(fā)工程師 北京市/昌平區(qū)
- 技術專家 廣東省/江門市
- 封裝工程師 北京市/海淀區(qū)
- 結構工程師 廣東省/深圳市