成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

斷開TCP連接

fyber / 2988人閱讀

摘要:我們知道通過三次握手建立可靠連接,通過四次揮手斷開連接,連接是比較昂貴的資源。從上分析,安全可靠的斷開連接至少需要四次,再多一次的意義不大。連接的異常斷開以上都是在理想的情況下發(fā)生的,理想狀態(tài)下,一個連接可以被長期保持。

我們知道TCP通過三次握手建立可靠連接,通過四次揮手斷開連接,TCP連接是比較昂貴的資源。為什么TCP需要通過三次握手才能建立可靠的連接?兩次不行么?斷開連接為什么需要四次?TCP連接昂貴在哪里?

三次握手
客戶端:“喂,聽得到嗎?” 
服務端:“我能聽到,你能聽到我嗎?”
客戶端:“恩,能聽到?!?/pre>

為什么需要三次握手,對客戶端而言,再收到服務端的ACK后,能確定我發(fā)的消息服務端能收到,服務端發(fā)的消息我也能收到了,那為什么還要第三次握手?這要從服務端考慮,服務端在接收到SYN后只能確定自己能收到客戶端發(fā)來的消息,如果沒有第三次握手,服務端是不確定對方是否能接收到自己這邊發(fā)送的消息的,這種不確定勢必影響到了信道的可靠性。既然三次就已經確保了信道的可靠性,如果在加一次肯定就增加了網絡消耗從而影響了建立連接的效率。

四次揮手
客戶端:“不說了,掛了吧?!?br>服務端:“OK!”
服務端:“你要注意身體啊!”
服務端:“拜拜!”
客戶端:“拜拜!”

斷開連接是釋放資源的過程,還是從客戶端和服務端兩個人的角度去分析揮手過程。

首先建立連接是為了可靠的數據交付,現在連接建立已經有一段時間了,客戶端說數據已經發(fā)完了,已經沒什么要發(fā)送了,于是告訴操作系統(tǒng),嘿,老兄,我數據已經發(fā)完了,你可以把我的發(fā)送資源釋放啦,于是操作系統(tǒng)鎖住了發(fā)送資源(比如發(fā)送隊列)準備釋放,并標記了TCP連接狀態(tài)為FIN_WAIT_1,由于數據發(fā)送是雙方的事情,客戶端這邊的發(fā)送資源已經釋放,客戶端有義務告知服務端這邊的數據已經發(fā)送完畢,所以操作系統(tǒng)會發(fā)送一條FIN消息到服務端,告知服務端可以釋放接收資源了,為了保證服務端確實收到了FIN消息并釋放了接收資源,服務端也需要返回一條ACK消息給客戶端,如果客戶端沒收到ACK消息,則重試剛剛的FIN消息??蛻舳艘坏┦盏?b>ACK消息,則說明服務端已經釋放了接收資源,操作系統(tǒng)將TCP連接狀態(tài)改為FIN_WAIT_2。到這里TCP連接已經關閉一半。

上面的過程只是結束了客戶端的數據發(fā)送,釋放了發(fā)送數據需要的資源,但是客戶端依然可以接收從服務端發(fā)來的數據,服務端只是結束了數據接收并釋放相關資源,依然可以放數據,因為服務端處理完接收的數據后要反饋結果給客戶端。等結果反饋完后,沒有數據要處理了,服務端也要結束發(fā)送過程,同樣也得告知客戶端讓其釋放接收數據所需要的資源。服務端重復上面的過程。但不同的是,客戶端接收到FIN消息并返回ACK消息后需要等一段時間,這是由于擔心服務端沒有收到ACK又重發(fā)了FIN消息。等過了一段時間后并沒有收到重發(fā)的消息,客戶端就會釋放所有資源(這里就不管服務端到底有沒有收到ACK了,如果一直管下去就是個死循環(huán))。服務端也是一樣,重試多次以后也就釋放了所有資源(這里不清楚到底是不是釋放了資源,也有可能有其他機制)。

從上分析,安全可靠的斷開連接至少需要四次,再多一次的意義不大。

昂貴的資源
上面分析可知,三次握手和四次揮手無疑會造成巨大的網絡資源和CPU資源的消耗(如果連接沒有被復用,這就是一種浪費),另外,客戶端和服務端分別要維護各自的發(fā)送和接收緩存,各自在操作系統(tǒng)里面的變量(比如文件描述符,操作系統(tǒng)維護的一套數據結構),在阻塞式的網絡模型中,服務端還要開啟線程來處理這條連接。所以說TCP連接是比較昂貴的資源,需要連接池這種技術來提高它的復用性。
TCP連接的異常斷開
以上都是在理想的情況下發(fā)生的,理想狀態(tài)下,一個TCP連接可以被長期保持。但是現實總是很骨感,在保持TCP連接的過程中很可能出現各種意外的情況,比如網絡故障,客戶端崩潰或者異常重啟,在這種情況下,如果服務端沒有及時清理這些連接,服務端將發(fā)生連接泄露,直至服務端資源耗盡拒絕提供服務(connection refused exception)。因此在實際應用中,服務器端需要采取相應的方法來探測TCP連接是否已經斷連。探測的原理就是心跳機制,可以是應用層面的心跳,也可以是第三方的心跳,但是絕大部分類Unix系統(tǒng)均在TCP中提供了相應的心跳檢測功能(雖然并不是TCP規(guī)范中的一部分)。
客戶端程序崩潰或異常退出

當客戶端程序因未知原因崩潰或異常退出后,操作系統(tǒng)會給服務端發(fā)送一條RST消息,阻塞模型下,服務端內核無法主動通知應用層出錯,只有應用層主動調用read()或者write()這樣的IO系統(tǒng)調用時,內核才會利用出錯來通知應用層對端RSTLinux系統(tǒng)報Connection reset by peer)。非阻塞模型下,服務端select或者epoll會返回sockfd可讀,應用層對其進行讀取時,read()會報錯RST。

哪些情況下,會收到來自對端的RST消息呢。

connect一個不存在的端口,客戶端會收到一條RST,報錯Connection refused;

程序崩潰或異常退出,會向對端發(fā)送。

對端斷電重啟,send數據時會收到來自對端的RST

close(sockfd)時,直接丟棄接收緩沖區(qū)未讀取的數據,并給對方發(fā)一個RST。這個是由SO_LINGER選項來控制的;

TCP socket在任何狀態(tài)下,只要收到RST包,即可釋放連接資源。

客戶端斷電或網絡異常

如果客戶端斷電或網絡異常,并且連接通道內沒有任何數據交互,服務端是感知不到客戶端掉線的,此時需要借助心跳機制來感知這種狀況,一般的做法是,服務端往對端發(fā)送一個心跳包并啟動一個超時定時器,如果能正確收到對端的回應,說明在線,如果超時,可以進行一系列操作,比如重試、關閉連接等等。

keep alive or heart beart
借鑒一下大神的文章

很多人都知道TCP并不會去主動檢測連接的丟失,這意味著,如果雙方不產生交互,那么如果網絡斷了或者有一方機器崩潰,另外一方將永遠不知道連接已經不可用了。檢測連接是否丟失的方法大致有兩種:keepaliveheart-beat。

Keepalive是很多的TCP實現提供的一種機制,它允許連接在空閑的時候雙方會發(fā)送一些特殊的數據段,并通過響應與否來判斷連接是否還存活著(所謂keep~~alive)。我曾經寫過一篇關于keepalive的blog ,但后來我也發(fā)現,其實keepalive在實際的應用中并不常見。為何如此?這得歸結于keepalive設計的初衷。Keepalive適用于清除死亡時間比較長的連接。
比如這樣的場景:一個用戶創(chuàng)建tcp連接訪問了一個web服務器,當用戶完成他執(zhí)行的操作后,很粗暴的直接撥了網線。這種情況下,這個tcp連接已經斷開了,但是web服務器并不知道,它會依然守護著這個連接。如果web server設置了keepalive,那么它就能夠在用戶斷開網線的大概幾個小時以后,確認這個連接已經中斷,然后丟棄此連接,回收資源。
采用keepalive,它會先要求此連接一定時間沒有活動(一般是幾個小時),然后發(fā)出數據段,經過多次嘗試后(每次嘗試之間也有時間間隔),如果仍沒有響應,則判斷連接中斷??上攵?,整個周期需要很長的時間。
所以,如前面的場景那樣,需要一種方法能夠清除和回收那些在系統(tǒng)不知情的情況下死去了很久的連接,keepalive是非常好的選擇。
但是,在大部分情況下,特別是分布式環(huán)境中,我們需要的是一個能夠快速或者實時監(jiān)控連接狀態(tài)的機制,這里,heart-beat才是更加合適的方案。
Heart-beat(心跳),按我的理解,它的原理和keepalive非常類似,都是發(fā)送一個信號給對方,如果多次發(fā)送都沒有響應的話,則判斷連接中斷。它們的不同點在于,keepalivetcp實現中內建的機制,是在創(chuàng)建tcp連接時通過設置參數啟動keepalive機制;而heart-beat則需要在tcp之上的應用層實現。一個簡單的heart-beat實現一般測試連接是否中斷采用的時間間隔都比較短,可以很快的決定連接是否中斷。并且,由于是在應用層實現,因為可以自行決定當判斷連接中斷后應該采取的行為,而keepalive在判斷連接失敗后只會將連接丟棄。
關于heart-beat,一個非常有趣的問題是,應該在傳輸真正數據的連接中發(fā)送心跳信號,還是可以專門創(chuàng)建一個發(fā)送“心跳”信號的連接。比如說,A,B兩臺機器之間通過連接m來傳輸數據,現在為了能夠檢測A,B之間的連接狀態(tài),我們是應該在連接m中傳輸心跳信號,還是創(chuàng)建新的連接n來專門傳輸心跳呢?我個人認為兩者皆可。如果擔心的是端到端的連接狀態(tài),那么就直接在該條連接中實現心跳。但很多時候,關注的是網絡狀況和兩臺主機間的連接狀態(tài),這種情況下, 創(chuàng)建專門的心跳連接也未嘗不可。

Socket感知連接斷開 正常情況

客戶端正常關閉連接:

//發(fā)送FIN消息,說明客戶端已經沒有數據發(fā)送,服務端read時會返回-1或者null
socket.shutdownOutput();
//默認的SO_LINGER參數,客戶端發(fā)送FIN消息,服務端read時會返回-1或者null
socket.close();
//設置了立即關閉,客戶端發(fā)送RST消息,服務端`read`時會報`connection rest by peer`。
socket.close();
非正常情況

客戶端程序崩潰或異常退出:服務端read時會報connection rest by peer。

斷電重啟:服務端發(fā)送心跳信息時,會收到客戶端的RST消息,調用read時會報connection rest by peer

斷電或網絡中斷:服務端發(fā)送心跳信息后超時。

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規(guī)行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://systransis.cn/yun/72749.html

相關文章

  • TCP協(xié)議小結

    摘要:協(xié)議的定義屬于傳輸層協(xié)議,提供了一種端到端的連接。如果兩次校驗和一致說明數據是正確的,否則將認為數據被破壞,接收端將丟棄該數據緊急指針盡在緊急控制位為時有效。結尾是一個非常復雜的協(xié)議,這里稍微總結了一下,隨著學習時間增加,繼續(xù)補充。 TCP協(xié)議的定義 TCP屬于傳輸層協(xié)議,提供了一種端到端的連接。 是面向連接的、可靠的的進程到進程通信的協(xié)議 TCP提供全雙工服務,即數據可在同一時間雙...

    Freelander 評論0 收藏0
  • 淺談Http協(xié)議(五):基于Tcp協(xié)議的三次握手和四次揮手

    摘要:很多人都知道協(xié)議是基于協(xié)議創(chuàng)造出來的采用文本方式傳輸非二進制傳輸的應用層協(xié)議,協(xié)議是傳輸層協(xié)議,主要解決數據如何在網絡中傳輸,而應用層協(xié)議,主要解決如何包裝和規(guī)范數據。你也可以自己定義應用層協(xié)議,只不過所有配套的東西都要自己重新造輪子。 從問題切入能幫我們更好地理解晦澀難懂的概念。很多人都知道http協(xié)議是基于Tcp協(xié)議創(chuàng)造出來的采用文本方式傳輸(非二進制傳輸)的應用層協(xié)議,TPC/I...

    weknow619 評論0 收藏0

發(fā)表評論

0條評論

fyber

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<