鏈接:https://www.zhihu.com/question/24853633/answer/254224088
來源:知乎
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。
TCP三次握手

PS:TCP協議中,主動發起請求的一端稱為『客戶端』,被動連接的一端稱為『服務端』。不管是客戶端還是服務端,TCP連接建立完后都能發送和接收數據。
起初,服務器和客戶端都為CLOSED狀態。在通信開始前,雙方都得創建各自的傳輸控制塊(TCB)。
服務器創建完TCB后遍進入LISTEN狀態,此時准備接收客戶端發來的連接請求。
第一次握手
客戶端向服務端發送連接請求報文段。該報文段的頭部中SYN=1,ACK=0,seq=x。請求發送后,客戶端便進入SYN-SENT狀態。
- PS1:SYN=1,ACK=0表示該報文段為連接請求報文。
- PS2:x為本次TCP通信的字節流的初始序號。
TCP規定:SYN=1的報文段不能有數據部分,但要消耗掉一個序號。
第二次握手
服務端收到連接請求報文段后,如果同意連接,則會發送一個應答:SYN=1,ACK=1,seq=y,ack=x+1。
該應答發送完成后便進入SYN-RCVD狀態。
- PS1:SYN=1,ACK=1表示該報文段為連接同意的應答報文。
- PS2:seq=y表示服務端作為發送者時,發送字節流的初始序號。
- PS3:ack=x+1表示服務端希望下一個數據報發送序號從x+1開始的字節。
第三次握手
當客戶端收到連接同意的應答后,還要向服務端發送一個確認報文段,表示:服務端發來的連接同意應答已經成功收到。
該報文段的頭部為:ACK=1,seq=x+1,ack=y+1。
客戶端發完這個報文段后便進入ESTABLISHED狀態,服務端收到這個應答后也進入ESTABLISHED狀態,此時連接的建立完成!
為什么連接建立需要三次握手,而不是兩次握手?
防止失效的連接請求報文段被服務端接收,從而產生錯誤。
PS:失效的連接請求:若客戶端向服務端發送的連接請求丟失,客戶端等待應答超時后就會再次發送連接請求,此時,上一個連接請求就是『失效的』。
若建立連接只需兩次握手,客戶端並沒有太大的變化,仍然需要獲得服務端的應答后才進入ESTABLISHED狀態,而服務端在收到連接請求后就進入ESTABLISHED狀態。此時如果網絡擁塞,客戶端發送的連接請求遲遲到不了服務端,客戶端便超時重發請求,如果服務端正確接收並確認應答,雙方便開始通信,通信結束后釋放連接。此時,如果那個失效的連接請求抵達了服務端,由於只有兩次握手,服務端收到請求就會進入ESTABLISHED狀態,等待發送數據或主動發送數據。但此時的客戶端早已進入CLOSED狀態,服務端將會一直等待下去,這樣浪費服務端連接資源。
TCP四次揮手

TCP連接的釋放一共需要四步,因此稱為『四次揮手』。
我們知道,TCP連接是雙向的,因此在四次揮手中,前兩次揮手用於斷開一個方向的連接,后兩次揮手用於斷開另一方向的連接。
第一次揮手
若A認為數據發送完成,則它需要向B發送連接釋放請求。該請求只有報文頭,頭中攜帶的主要參數為:
FIN=1,seq=u。此時,A將進入FIN-WAIT-1狀態。
- PS1:FIN=1表示該報文段是一個連接釋放請求。
- PS2:seq=u,u-1是A向B發送的最后一個字節的序號。
第二次揮手
B收到連接釋放請求后,會通知相應的應用程序,告訴它A向B這個方向的連接已經釋放。此時B進入CLOSE-WAIT狀態,並向A發送連接釋放的應答,其報文頭包含:
ACK=1,seq=v,ack=u+1。
- PS1:ACK=1:除TCP連接請求報文段以外,TCP通信過程中所有數據報的ACK都為1,表示應答。
- PS2:seq=v,v-1是B向A發送的最后一個字節的序號。
- PS3:ack=u+1表示希望收到從第u+1個字節開始的報文段,並且已經成功接收了前u個字節。
A收到該應答,進入FIN-WAIT-2狀態,等待B發送連接釋放請求。
第二次揮手完成后,A到B方向的連接已經釋放,B不會再接收數據,A也不會再發送數據。但B到A方向的連接仍然存在,B可以繼續向A發送數據。
第三次揮手
當B向A發完所有數據后,向A發送連接釋放請求,請求頭:FIN=1,ACK=1,seq=w,ack=u+1。B便進入LAST-ACK狀態。
第四次揮手
A收到釋放請求后,向B發送確認應答,此時A進入TIME-WAIT狀態。該狀態會持續2MSL時間,若該時間段內沒有B的重發請求的話,就進入CLOSED狀態,撤銷TCB。當B收到確認應答后,也便進入CLOSED狀態,撤銷TCB。
為什么A要先進入TIME-WAIT狀態,等待2MSL時間后才進入CLOSED狀態?
為了保證B能收到A的確認應答。
若A發完確認應答后直接進入CLOSED狀態,那么如果該應答丟失,B等待超時后就會重新發送連接釋放請求,但此時A已經關閉了,不會作出任何響應,因此B永遠無法正常關閉
謝希仁版《計算機網絡》中的例子是這樣的,“已失效的連接請求報文段”的產生在這樣一種情況下:client發出的第一個連接請求報文段並沒有丟失,而是在某個網絡結點長時間的滯留了,以致延誤到連接釋放以后的某個時間才到達server。本來這是一個早已失效的報文段。但server收到此失效的連接請求報文段后,就誤認為是client再次發出的一個新的連接請求。於是就向client發出確認報文段,同意建立連接。假設不采用“三次握手”,那么只要server發出確認,新的連接就建立了。由於現在client並沒有發出建立連接的請求,因此不會理睬server的確認,也不會向server發送數據。但server卻以為新的運輸連接已經建立,並一直等待client發來數據。這樣,server的很多資源就白白浪費掉了。采用“三次握手”的辦法可以防止上述現象發生。例如剛才那種情況,client不會向server的確認發出確認。server由於收不到確認,就知道client並沒有要求建立連接。