本機ip: 192.168.0.72html
訪問地址: [http://www.cnblogs.com/tankxiao]()服務器
記錄378,419,427就對應着著名的TCP三次握手網絡
數據幀格式以下學習
三次握手流程圖spa
SYN:創建鏈接計算機網絡
FIN:關閉鏈接server
ACK:響應htm
PSH:數據傳輸blog
RST:鏈接重製ip
A->B:在嗎?聽的到嗎?
B->A:在啊?你聽獲得嗎?(告訴A,經過B的回覆來確認,A->B通訊正常)
A->B:聽的見(告訴B,經過A的回覆來確認,B->A通訊正常)
客戶端向服務端創建鏈接的信號 Syn = 1,seq 爲隨機數
圖中 Sequence number: 0 (relative sequence number),反映的是相對seq
真實的 seq 在圖中下部分,用16進制 "532d0c99"表示,轉換成10進製爲 "1395461273"
服務端向客戶端發送響應 Ack = seq(來自客戶端,1395461273) + 1,Syn = 1,seq 爲隨機數
圖中 Acknowledgment number: 1 (relative ack number),反映的是相對Ack
真實的 ack 在圖中下部分,用16進制"532d0c9a"表示,轉換成10進製爲 "1395461274"
同理 seq "96fb78d2" 的10進製爲 "2533062866"
客戶端向服務端發送響應 Ack = seq (來自服務端,2533062866) + 1,seq 爲隨機數
圖中 Ack 的16進製爲"96fb78d3",轉換成10進製爲"2533062867"
圖中 seq 的16進製爲"532d0c9a",轉換成10進製爲"1395461274"
至此之後,客戶端就能夠愉快地和服務端通訊了
「已失效的鏈接請求報文段」的產生在這樣一種狀況下:client發出的第一個鏈接請求報文段並無丟失,而是在某個網絡結點長時間的滯留了,以至延誤到鏈接釋放之後的某個時間纔到達server。原本這是一個早已失效的報文段。但server收到此失效的鏈接請求報文段後,就誤認爲是client再次發出的一個新的鏈接請求。因而就向client發出確認報文段,贊成創建鏈接。假設不採用「三次握手」,那麼只要server發出確認,新的鏈接就創建了。因爲如今client並無發出創建鏈接的請求,所以不會理睬server的確認,也不會向server發送數據。但server卻覺得新的運輸鏈接已經創建,並一直等待client發來數據。這樣,server的不少資源就白白浪費掉了。採用「三次握手」的辦法能夠防止上述現象發生。例如剛纔那種狀況,client不會向server的確認發出確認。server因爲收不到確認,就知道client並無要求創建鏈接。」
摘自謝希仁著《計算機網絡》
TCP維持數據不丟失的關鍵在於Seq和Ack
在18.443018時,客戶端向服務端發送數據包P1,內容是發送http請求,Seq = 1,Len = 1083,命名爲數據包P1
在18.469641時,服務端告訴客戶端數據包P1已經收到, Ack = 數據包P1的Seq + 數據包P1的Len
在18.495616時,服務端向客戶端發送數據包P2,內容是html文檔,Seq = 1, Len = 1452
在18.495617時,服務端向客戶端發送數據包P3,內容還是html文檔,Seq = 1453,Len = 133
在18.495680時,客戶端告訴服務端數據包P3已經收到,Ack = 數據包P3的Seq + 數據包P3的Len
TCP提供的確認機制,能夠在通訊過程當中能夠不對每個TCP數據包發出單獨的確認包(Delayed ACK機制),而是在傳送數據時,順便把確認信息傳出, 這樣能夠大大提升網絡的利用率和傳輸效率。同時,TCP的確認機制,也能夠一次確認多個數據報,例如,接收方收到了201,301,401的數據報,則只 須要對401的數據包進行確認便可,對401的數據包的確認也意味着401以前的全部數據包都已經確認,這樣也能夠提升系統的效率。
在18.496954-18.496961期間,服務端發送了5個數據包,其中最後一個數據包是響應頭,"HTTP/1.1 200 OK..."
在18.497018-18.499389期間,客戶端對發來的數據包進行確認
發送數據包,數據的序號Seq和數據的長度Len
確認包,Ack = 收到的最後的數據包的序號Seq+Len,
同時由於做爲確認包,在服務端與客戶端交換數據的過程當中,沒有向服務端發送數據,因此 Seq 不變
在某種程度上能夠這樣理解Seq和Ack,在發送這個包以前,我已經向對方發送的數據量Seq,我已經接受到的數據量Ack
這是由於服務端的LISTEN狀態下的SOCKET當收到SYN報文的鏈接請求後,它能夠把ACK和SYN(ACK起應答做用,而SYN起同步做用)放在一個報文裏來發送。但關閉鏈接時,當收到對方的FIN報文通知時,它僅僅表示對方沒有數據發送給你了;但未必你全部的數據都所有發送給對方了,因此你可能未必會立刻會關閉SOCKET,也即你可能還須要發送一些數據給對方以後,再發送FIN報文給對方來表示你贊成如今能夠關閉鏈接了,因此它這裏的ACK報文和FIN報文多數狀況下都是分開發送的。
因爲TCP鏈接是全雙工的,所以每一個方向都必須單獨進行關閉。這個原則是當一方完成它的數據發送任務後就能發送一個FIN來終止這個方向的鏈接。收到一個 FIN只意味着這一方向上沒有數據流動,一個TCP鏈接在收到一個FIN後仍能發送數據。首先進行關閉的一方將執行主動關閉,而另外一方執行被動關閉。
(1)客戶端A發送一個FIN,用來關閉客戶A到服務器B的數據傳送。
(2)服務器B收到這個FIN,它發回一個ACK,確認序號爲收到的序號加1。和SYN同樣,一個FIN將佔用一個序號。
(3)服務器B關閉與客戶端A的鏈接,發送一個FIN給客戶端A。
(4)客戶端A發回ACK報文確認,並將確認序號設置爲收到序號加1。
A->B:我對你已經沒話說了
B->A:我知道你對我沒話說了
B->A:我對你也沒話說了
A->B:我知道你對我也沒話說了