原文地址緩存
TCP提供一種面向鏈接的,可靠的字節流服務。服務器
TCP首部的數據格式以下。(若是不計任選字段,一般是20個字節)網絡
TCP報頭中的源端口號和目的端口號同IP數據報中的源IP與目的IP惟一肯定一條TCP鏈接。spa
控制位:URG ACK PSH RST SYN FIN,共6個,每個標誌位表示一個控制功能。指針
第一次握手:客戶端發送syn包(syn=x)到服務器,並進入SYN_SEND狀態,等待服務器確認;code
第二次握手:服務器收到syn包,必須確認客戶的SYN(ack=x+1),同時本身也發送一個SYN包(syn=y),即SYN+ACK包,此時服務器進入SYN_RECV狀態;server
第三次握手:客戶端收到服務器的SYN+ACK包,向服務器發送確認包ACK(ack=y+1),此包發送完畢,客戶端和服務器進入ESTABLISHED狀態,完成三次握手。blog
握手過程當中傳送的包裏不包含數據,三次握手完畢後,客戶端與服務器才正式開始傳送數據。理想狀態下,TCP鏈接一旦創建,在通訊雙方中的任何一方主動關閉鏈接以前,TCP 鏈接都將被一直保持下去。接口
創建鏈接的過程是利用客戶服務器模式,假設主機A爲客戶端,主機B爲服務器端。進程
採用三次握手是爲了防止失效的鏈接請求報文段忽然又傳送到主機B,於是產生錯誤。失效的鏈接請求報文段是指:主機A發出的鏈接請求沒有收到主機B的確認,因而通過一段時間後,主機A又從新向主機B發送鏈接請求,且創建成功,順序完成數據傳輸。考慮這樣一種特殊狀況,主機A第一次發送的鏈接請求並無丟失,而是由於網絡節點致使延遲達到主機B,主機B覺得是主機A又發起的新鏈接,因而主機B贊成鏈接,並向主機A發回確認,可是此時主機A根本不會理會,主機B就一直在等待主機A發送數據,致使主機B的資源浪費。
採用兩次握手不行,緣由就是上面說的失效的鏈接請求的特殊狀況。而在三次握手中, client和server都有一個發syn和收ack的過程, 雙方都是發後能收, 代表通訊則準備工做OK.
爲何不是四次握手呢? 你們應該知道通訊中著名的藍軍紅軍約定, 這個例子說明, 通訊不可能100%可靠, 而上面的三次握手已經作好了通訊的準備工做, 再增長握手, 並不能顯著提升可靠性, 並且也沒有必要。
數據傳輸完畢後,雙方均可釋放鏈接。最開始的時候,客戶端和服務器都是處於ESTABLISHED狀態,假設客戶端主動關閉,服務器被動關閉。
第一次揮手:客戶端發送一個FIN,用來關閉客戶端到服務器的數據傳送,也就是客戶端告訴服務器:我已經不 會再給你發數據了(固然,在fin包以前發送出去的數據,若是沒有收到對應的ack確認報文,客戶端依然會重發這些數據),可是,此時客戶端還可 以接受數據。
FIN=1,其序列號爲seq=u(等於前面已經傳送過來的數據的最後一個字節的序號加1),此時,客戶端進入FIN-WAIT-1(終止等待1)狀態。 TCP規定,FIN報文段即便不攜帶數據,也要消耗一個序號。
第二次揮手:服務器收到FIN包後,發送一個ACK給對方而且帶上本身的序列號seq,確認序號爲收到序號+1(與SYN相同,一個FIN佔用一個序號)。此時,服務端就進入了CLOSE-WAIT(關閉等待)狀態。TCP服務器通知高層的應用進程,客戶端向服務器的方向就釋放了,這時候處於半關閉狀態,即客戶端已經沒有數據要發送了,可是服務器若發送數據,客戶端依然要接受。這個狀態還要持續一段時間,也就是整個CLOSE-WAIT狀態持續的時間。
此時,客戶端就進入FIN-WAIT-2(終止等待2)狀態,等待服務器發送鏈接釋放報文(在這以前還須要接受服務器發送的最後的數據)。
第三次揮手:服務器發送一個FIN,用來關閉服務器到客戶端的數據傳送,也就是告訴客戶端,個人數據也發送完了,不會再給你發數據了。因爲在半關閉狀態,服務器極可能又發送了一些數據,假定此時的序列號爲seq=w,此時,服務器就進入了LAST-ACK(最後確認)狀態,等待客戶端的確認。
第四次揮手:主動關閉方收到FIN後,發送一個ACK給被動關閉方,確認序號爲收到序號+1,此時,客戶端就進入了TIME-WAIT(時間等待)狀態。注意此時TCP鏈接尚未釋放,必須通過2∗MSL(最長報文段壽命)的時間後,當客戶端撤銷相應的TCB後,才進入CLOSED狀態。
服務器只要收到了客戶端發出的確認,當即進入CLOSED狀態。一樣,撤銷TCB後,就結束了此次的TCP鏈接。能夠看到,服務器結束TCP鏈接的時間要比客戶端早一些。
至此,完成四次揮手。
MSL(Maximum Segment Lifetime),TCP容許不一樣的實現能夠設置不一樣的MSL值。
第一,保證客戶端發送的最後一個ACK報文可以到達服務器,由於這個ACK報文可能丟失,站在服務器的角度看來,我已經發送了FIN+ACK報文請求斷開了,客戶端尚未給我回應,應該是我發送的請求斷開報文它沒有收到,因而服務器又會從新發送一次,而客戶端就能在這個2MSL時間段內收到這個重傳的報文,接着給出迴應報文,而且會重啓2MSL計時器。
第二,防止相似與「三次握手」中提到了的「已經失效的鏈接請求報文段」出如今本鏈接中。客戶端發送完最後一個確認報文後,在這個2MSL時間中,就可使本鏈接持續的時間內所產生的全部報文段都從網絡中消失。這樣新的鏈接中不會出現舊鏈接的請求報文。
創建鏈接的時候, 服務器在LISTEN狀態下,收到創建鏈接請求的SYN報文後,把ACK和SYN放在一個報文裏發送給客戶端。 而關閉鏈接時,服務器收到對方的FIN報文時,僅僅表示對方再也不發送數據了可是還能接收數據,而本身也未必所有數據都發送給對方了,因此己方能夠當即關閉,也能夠發送一些數據給對方後,再發送FIN報文給對方來表示贊成如今關閉鏈接,所以,己方ACK和FIN通常都會分開發送,從而致使多了一次。