国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

斷開TCP連接

fyber / 2974人閱讀

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

客戶端斷電或網絡異常

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

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

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

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

Socket感知連接斷開 正常情況

客戶端正常關閉連接:

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

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

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

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

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

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

相關文章

  • TCP協議小結

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

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

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

    weknow619 評論0 收藏0

發表評論

0條評論

fyber

|高級講師

TA的文章

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