成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專欄INFORMATION COLUMN

斷開TCP連接

fyber / 3092人閱讀

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

我們知道TCP通過(guò)三次握手建立可靠連接,通過(guò)四次揮手?jǐn)嚅_連接,TCP連接是比較昂貴的資源。為什么TCP需要通過(guò)三次握手才能建立可靠的連接??jī)纱尾恍忻矗繑嚅_連接為什么需要四次?TCP連接昂貴在哪里?

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

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

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

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

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

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

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

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

當(dāng)客戶端程序因未知原因崩潰或異常退出后,操作系統(tǒng)會(huì)給服務(wù)端發(fā)送一條RST消息,阻塞模型下,服務(wù)端內(nèi)核無(wú)法主動(dòng)通知應(yīng)用層出錯(cuò),只有應(yīng)用層主動(dòng)調(diào)用read()或者write()這樣的IO系統(tǒng)調(diào)用時(shí),內(nèi)核才會(huì)利用出錯(cuò)來(lái)通知應(yīng)用層對(duì)端RSTLinux系統(tǒng)報(bào)Connection reset by peer)。非阻塞模型下,服務(wù)端select或者epoll會(huì)返回sockfd可讀,應(yīng)用層對(duì)其進(jìn)行讀取時(shí),read()會(huì)報(bào)錯(cuò)RST。

哪些情況下,會(huì)收到來(lái)自對(duì)端的RST消息呢。

connect一個(gè)不存在的端口,客戶端會(huì)收到一條RST,報(bào)錯(cuò)Connection refused;

程序崩潰或異常退出,會(huì)向?qū)Χ税l(fā)送。

對(duì)端斷電重啟,send數(shù)據(jù)時(shí)會(huì)收到來(lái)自對(duì)端的RST。

close(sockfd)時(shí),直接丟棄接收緩沖區(qū)未讀取的數(shù)據(jù),并給對(duì)方發(fā)一個(gè)RST。這個(gè)是由SO_LINGER選項(xiàng)來(lái)控制的;

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

客戶端斷電或網(wǎng)絡(luò)異常

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

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

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

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

Socket感知連接斷開 正常情況

客戶端正常關(guān)閉連接:

//發(fā)送FIN消息,說(shuō)明客戶端已經(jīng)沒有數(shù)據(jù)發(fā)送,服務(wù)端read時(shí)會(huì)返回-1或者null
socket.shutdownOutput();
//默認(rèn)的SO_LINGER參數(shù),客戶端發(fā)送FIN消息,服務(wù)端read時(shí)會(huì)返回-1或者null
socket.close();
//設(shè)置了立即關(guān)閉,客戶端發(fā)送RST消息,服務(wù)端`read`時(shí)會(huì)報(bào)`connection rest by peer`。
socket.close();
非正常情況

客戶端程序崩潰或異常退出:服務(wù)端read時(shí)會(huì)報(bào)connection rest by peer。

斷電重啟:服務(wù)端發(fā)送心跳信息時(shí),會(huì)收到客戶端的RST消息,調(diào)用read時(shí)會(huì)報(bào)connection rest by peer。

斷電或網(wǎng)絡(luò)中斷:服務(wù)端發(fā)送心跳信息后超時(shí)。

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

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/72749.html

相關(guān)文章

  • TCP協(xié)議小結(jié)

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

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

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

    weknow619 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<