文档章节

TCP連接狀態及三次握手四次揮手

齐勇cn
 齐勇cn
发布于 2016/08/30 07:33
字数 2611
阅读 40
收藏 1

TCP連接狀態及三次握手四次揮手

 2016-04-14 21:23:00

 

TCP一共有11種連接狀態:

  1. SYN_SENT:在發送連接請求後等待匹配的連接請求(客戶端向伺服器端發送SYN請求建立一個連接,之後將狀態置為SYN_SENT)

  2. FIN_WAIT_1:等待遠程TCP連接中斷請求,或先前的連接中斷請求的確認(主動關閉端發送FIN請求主動關閉連接,之後將狀態置為FIN_WAIT_1)

  3. FIN_WAIT_2:從遠程TCP等待連接中斷請求(主動關閉端接到ACK後,之後將狀態置為FIN_WAIT_2,此時是半關閉狀態,即主動關閉端還能夠接受數據,但是無法發送數據 )

  4. CLOSING:等待遠程TCP對連接中斷的確認(如果兩端同時發送FIN,則在發送後兩端都進入FIN_WAIT_1狀態。在收到對端的FIN後回復ACK報文,之後將狀態置為CLOSING,比較少見)

  5. TIME_WAIT:等待足夠的時間以確保遠程TCP接收到連接中斷請求的確認(主動關閉端接收到FIN,TCP就發送ACK包,之後將狀態置為TIME_WAIT)

    ADVERTISEMENT

  6. LISTEN:偵聽來自遠方的TCP埠的連接請求(伺服器端需打開一個socket進行監聽,之後將狀態置為LISTEN)

  7. SYN_RCVD:在收到和發送一個連接請求後等待對方對連接請求的確認(當伺服器端收到客戶端的連接請求後,將標誌位ACK和SYN置為1發送給客戶端,之後將狀態置為SYN_RCVD)

  8. CLOSE_WAIT:等待從本地用戶發來的連接中斷請求(被動關閉端接到FIN後,就發出ACK以回應FIN請求,之後將狀態置為CLOSE_WAIT)

  9. LAST_ACK:等待原來的發向遠程TCP的連接中斷請求的確認(被動關閉端在狀態為CLOSE_WAIT一段時間後,將餘下數據傳送完後發回一個FIN請求關閉連接,之後將狀態置為LAST_ACK)

  10. CLOSED:沒有任何連接狀態(被動關閉端在接受到主動關閉端ACK包,之後將狀態置為CLOSED,連接結束)

  11. ESTABLISHED:代表一個打開的連接(成功建立連接,之後將狀態置為ESTABLISHED,開始傳輸數據)

    ADVERTISEMENT

其中1-5是客戶端獨有的狀態,6-9為服務端獨有的狀態,而10-11是客戶端服務端公有狀態。

再插入的說一下TCP的六個標誌位,按在TCP首部中的順序依次是:

1.URG(urgent緊急數據)

2.ACK(acknowlegment確認)

3.PSH(push推送)

4.RST(reset重置)

5.SYN(synchronized建立聯機同步序號)

6.FIN(finish結束)

需要哪種類型則將該標誌位致為1。

下圖就是比較經典的TCP狀態轉換圖:

接下來就分別通過三次握手(連接建立)和四次揮手(連接釋放)說明下狀態轉化圖。

三次握手:

建立連接前,客戶端和服務端狀態都為CLOSED,服務端創建socket被動打開連接,並將狀態置為LISTEN。

客戶端主動打開連接,向服務端發送SYN報文,將TCP首部控制位中的SYN置為1,同時序號seq為客戶端隨機生成的一個初始序號seq = x(SYN報文段不能攜帶數據,但要消耗一個序列號),並將客戶端狀態置為SYN_SENT。

服務端收到SYN報文後,如同意建立連接,則向客戶端發送SYN+ACK報文,將TCP首部控制位中的SYN和ACK都置為1,確認號為ack = x + 1,同時隨機生成一個自己的序號seq = y,並將服務端狀態致為SYN_RCVD(同步收到狀態)。

客戶端收到SYN+ACK報文後,還需向服務端發送ACK報文,將TCP首部控制位中的ACK置為1,確認號ack = y + 1,序列號seq = x + 1,並將客戶端狀態置為ESTABLISHED。

服務端收到ACK報文後,也將狀態置為ESTABLISHED,此時三次握手完成,連接建立,進入數據傳送狀態。

為什麼要三次握手而不是兩次:

現假定出現一種異常情況:客戶端發送的SYN報文並未丟失,而是在某個網絡節點長時間滯留了,以致延誤到客戶端連接釋放後的某個時間才到達服務端,但服務端收到此失效的SYN報文後,誤以為是客戶端又發出的一次新的連接請求,於是就向客戶端發出SYN+ACK報文段,同意建立連接,假定不採用三次握手而是兩次握手,服務端就認為連接已經建立,並一直等待客戶端發送數據,但由於這次連接在客戶端已經失效了,因此不會對服務端的SYN+ACK報文給予回應,這就造成了服務端許多資源的白白浪費,所有才有三次握手的辦法可以防止上述現象的發生,即防止已失效的SYN報文突然又傳回服務端,因為產生錯誤。例如上述的情況,客戶端不向服務端發回ACK報文,由於客戶端收不到ACK報文,就知道客戶端並未要求建立連接,也不會造成資源的白白浪費,但三次握手也是有一定缺陷的,會被利用發起SYN flood攻擊。

四次揮手:

TCP連接是全雙工的,所以釋放連接會比建立連接略微複雜,釋放連接前,兩端都處於ESTABLISHED數據傳輸狀態。

客戶端先向伺服器端發送FIN報文,將TCP首部控制位中的FIN置為1,其序號seq = u,u等於客戶端前面最後一個已傳送過的包seq,並將狀態置為FIN_WAIT_1,等待服務端的確認。

服務端收到FIN報文後,將發送ACK報文,確認號ack = u + 1,序號seq = v,v等於服務端前面最後一個已傳送過的包的seq,之後將狀態致為CLOSE_WAIT(此時TCP連接處於半關閉狀態,即客戶端已經沒有數據要發送了,但若服務端要發送數據,客戶端仍要接受,也就是說服務端到客戶端這個方向的連接並未關閉,這個狀態可能會持續一段時間)。

當客戶端收到服務端傳來的確認報文後,將狀態致為FIN_WATI_2,等待服務端發送的FIN+ACK報文段。

若服務端沒有要向客戶端發送的數據,其應用進程就通知TCP釋放連接,將FIN+ACK報文段TCP首部控制位FIN和ACK置為1,此時序號seq = w(因為之前可能又傳遞一些數據),確認號ack = u + 1(上次的確認號),並將狀態置為LAST_ACK。

客戶端收到服務端的FIN+ACK報文後,需發送確認報文段,確認號ack = w + 1,序列號為seq = u + 1,並將狀態置為TIME_WAIT狀態,現在TCP連接還沒有釋放掉,必須經過2MSL(Max Segment Lifetime 最長報文段壽命)後才能進入CLOSED狀態,服務端在接受到確認報文後將狀態置為CLOSED。

上述的TCP連接釋放過程是四次揮手。

為什麼四次揮手:

TCP連接是全雙工的,當關閉連接時,當收到客戶端的FIN報文時,僅僅表示客戶端沒有數據發送給服務端了;但未必服務端所有的數據都發送給客戶端了,所以服務端未必會馬上會關閉SOCKET,也即服務端可能還需要發送一些數據給客戶端之後,再發送FIN+ACK報文給客戶端來表示現在可以關閉連接了,所以服務端這裡的ACK報文和FIN報文多數情況下都是分開發送的以確保數據能夠完成傳輸。

1.保證客戶端發送的最後一個ACK報文能夠到達服務端:

客戶端發送的最後一個ACK報文段可能會丟失,而處在LAST_ACK狀態的服務端因收不到客戶端的ACK報文會超時重傳FIN+ACK報文,因此客戶端就能在2MSL時間內收到這個重傳的FIN+ACK報文並重傳一次ACK報文,同時也重新啟動2MSL計時器,這樣客戶端服務端都能正常進入CLOSED狀態。如果客戶端不在TIME_WAIT狀態下等待一段時間,而是在發完ACK報文就進入CLOESD狀態釋放連接,那麼一旦這個ACK報文丟失,服務端收不到此ACK報文就無法正常進入CLOESD狀態。

2.防止已失效的SYN報文出現在此次連接中:

客戶端在發送完最後一個ACK報文經過2MSL後,就可以使此次連接持續的時間內所產生的所有報文從網絡中消失,這樣就能確保下一次新的連接中不會出現舊的連接請求報文。

最後再結合wireshark詳細看一下三次握手,四次揮手的過程:

三次握手:

可以看到該包為SYN包,並且seq = 54778471

該包為SYN+ACK包,ack = 54778471 + 1 = 54778472;seq = 720032937

該包為ACK包, ack = 750032937 + 1 = 750032938;seq = 54778472

至此,三次握手連接建立完成,兩端開始傳輸數據。

四次揮手:

這個是客戶端發送的最後的包,其中seq = 54779313;ack=720114520;

這個是客戶端主動發起的FIN包,seq =54779313;ack = 720114250

這是服務端回的FIN+ACK包,因為CLOSE_WAIT下沒有數據,所以兩個過程合一塊了,seq = 720114250, ack = 54779313 + 1 = 54779314

這是客戶端回的最後一個ACK包,seq = 54779314;ack = 720114250 + 1 =720114251

至此,四次握手連接釋放完成,兩端進入CLOSED狀態。

數據傳遞:

這是服務端傳送數據的一個包,seq = 720033157;ack = 54778889,len = 1440

這是客戶端收到數據後發的確認包,可見seq = 54778889;ack = 720033157 + len = 720034597

可知:

客戶端seq = 上個服務端包ack值,ack = 上個服務端包seq + len值

服務端seq = 上個客戶端包ack值,ack = 上個客戶端包seq + len值

本文转载自:https://read01.com/jgAByD.html

共有 人打赏支持
齐勇cn
粉丝 5
博文 19
码字总数 8610
作品 0
西安
技术主管
私信 提问
WP7 修練 DAY 05:釐清 WP7 閒置偵測機制的疑問(转载)

不管開發何種類型的應用程式,其執行生命週期永遠都是最需要先瞭解的,當然撰寫 Windows Phone 7 應用程式也不例外,不瞭解這些生命週期就會經常遇到鬼打牆的情況,在此我極力推薦 邊做邊學 ...

junwong
2012/02/24
103
0
【转】跟着动画来学习TCP三次握手和四次挥手

最近看到一篇很通俗易懂的描述TCP三次握手和四次挥手概念的文章,觉得特别好,怕以后找不到了,特意转载在这里学习一下。 原文地址:跟着动画来学习TCP三次握手和四次挥手 作者:老錢 链接:...

欧阳鹏
2018/07/16
0
0
可靠的TCP连接为何是三次握手

首先,咱们先来熟悉下经典的tcp/ip模型。 tcp/ip 模型为了方便使用,将osi七层模型划分成了四层,分别为网络接口层,网络层,传输层,应用层。 他们作用分别为: 1)网络接口层:主要作用是将...

xiaoer_03
2018/06/13
0
0
简明理解三次握手和四次挥手

注:三次握手和四次挥手本身并不复杂,但却可以从很多角度理解这两个过程,本文仅取一个视点解读,如有其它看法欢迎留言交流。 三次握手与四次挥手分别对应TCP连接建立过程与断开过程,先上T...

hello-k
2018/02/28
0
0
Windows Phone 7 - 取得Device的NetworkInformation(转载)

在介紹了DeviceStatus API之後,接下來往下介紹有關Device網路狀況的擷取。 為何要了解這個資訊呢,因為撰寫App當需要與Server或Remote Resouce互動時,一開始就先識別目前Device的網路狀態,...

junwong
2012/02/24
361
0

没有更多内容

加载失败,请刷新页面

加载更多

泛型就这么简单

前言 从今天开始进入Java基础的复习,可能一个星期会有一篇的<十道简单算法>,我写博文的未必都是正确的~如果有写错的地方请大家多多包涵并指正~ 今天要复习的是泛型,泛型在Java中也是个很...

群星纪元
22分钟前
2
0
大数据提醒你:中国这些古建筑,可能是下一个巴黎圣母院!

大家晚上好,我是今天的提笔人嗅嗅。 巴黎圣母院失火事件让我的心情很沉重,一句无关痛痒的安慰“巴黎不哭”,已经不能表达我对这场文化之殇的惋惜之痛,人类伟大的建筑在一瞬间被毁灭。 世界...

forespider
33分钟前
0
0
mysql函数substring_index的用法

substring_index 按索引字符位进行截取字符串 substring_index(“待截取的字符串”,“截取数据依据的字符”,截取字符的位置N) 第三个参数可正,可负。正数表示索引字符前面的字符串,负数...

echojson
33分钟前
1
0
好程序员web前端分享用CSS和JS打造一个简单的图片编辑器

好程序员web前端分享用CSS和JS打造一个简单的图片编辑器,本文主要是利用CSS的 filter和简单的Jquery代码来实现一个简单的图片编辑器,包括对图片的透明度,黑白,图片亮度等调节。 CSS filt...

好程序员IT
43分钟前
2
0
浅析spring mvc的细节

spring mvc 整体结构 系统监听到请求 -> 通知tomcat -> 根据web.xml 通知相应的拦截器(spring mvc 通常指DispatcherServlet) --> 检查url是否有相匹配的请求实现 --> 拿到请求实现bean的适配...

最爱肉肉
45分钟前
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部