日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 综合教程 >内容正文

综合教程

TCP ------ TCP四次挥手(断开连接)及断开过程

發布時間:2024/6/21 综合教程 42 生活家
生活随笔 收集整理的這篇文章主要介紹了 TCP ------ TCP四次挥手(断开连接)及断开过程 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1、正常情況下,調用close(),產生的其中一個效果就是發送FIN,只有雙方都調用close(),才會出現正常的四次揮手。

2、如果是服務器,發起四次揮手是在關閉accept()返回的套接字,而不是socket()返回的套接字

3、Initiator=client,Receiver=server 情況:如果是服務器進入CLOSE_WAIT,而不發送FIN的話(也就是不調用close()),重新創建服務器需要等待一段時間bind才能成功,這個時間就是客戶端FIN_WAIT_2的超時時間,超時后客戶端發送RST給服務器。所以客戶端close(),服務器必須也執行close()

4、主動調用 close() 一方才會進入 TIME_WAIT

5、調用shutdown()并不會啟動四次揮手

斷開為什么需要四次握手:

TCP協議是一種面向連接的、可靠的、基于字節流的運輸層通信協議。TCP是全雙工模式,這就意味著,當主機1發出FIN報文段時,只是表示主機1已經沒有數據要發送了,主機1告訴主機2,它的數據已經全部發送完畢了;但是,這個時候主機1還是可以接受來自主機2的數據;當主機2返回ACK報文段時,表示它已經知道主機1沒有數據發送了,但是主機2還是可以發送數據到主機1的;當主機2也發送了FIN報文段時,這個時候就表示主機2也沒有數據要發送了,就會告訴主機1,我也沒有數據要發送了,之后彼此就會愉快的中斷這次TCP連接。

為什么TIME_WAIT狀態需要經過2MSL(最大報文段生存時間)才能到CLOSE狀態

注:主動關閉一方會進入TIME_WAIT狀態,以下假設Client是主動方

1、如果Client直接CLOSED了,那么由于IP協議的不可靠性或者是其它網絡原因,導致Server沒有收到Client最后回復的ACK。那么Server就會在超時之后繼續發送FIN,此時由于Client已經CLOSED了,就找不到與重發的FIN對應的連接,最后Server就會收到RST而不是ACK,Server就會以為是連接錯誤把問題報告給高層。這樣的情況雖然不會造成數據丟失,但是卻導致TCP協議不符合可靠連接的要求。所以,Client不是直接進入CLOSED,而是要保持TIME_WAIT,保證能再次接收 FIN 并發送 ACK。(猜測: FIN超時時間應該小于MSL,否則Client等待2MSL,也可能接收不到FIN)

2、如果Client直接CLOSED,然后又再向Server發起一個新連接,我們不能保證這個新連接與剛關閉的連接的端口號是不同的。也就是說有可能新連接和老連接的端口號是相同的。一般來說不會發生什么問題,但是還是有特殊情況出現:假設新連接和已經關閉的老連接端口號是一樣的,如果前一次連接的某些數據仍然滯留在網絡中,這些延遲數據在建立新連接之后才到達Server,由于新連接和老連接的端口號是一樣的,又因為TCP協議判斷不同連接的依據是socket pair,于是,TCP協議就認為那個延遲的數據是屬于新連接的,這樣就和真正的新連接的數據包發生混淆了。所以TCP連接還要在TIME_WAIT狀態等待2倍MSL,這樣可以保證本次連接的所有數據都從網絡中消失。

服務端為了解決這個TIME_WAIT問題,可選擇的方式有三種:

Ø 服務器關閉的時候使用RST的方式(這是網友說的,我使用ESP8266做服務器,發送RST《發送RST的原因是調用 close() 時接收緩沖區還有未讀完的數據》還是會等待2MSL)

 Ø 服務器close()發送RST而不是FIN

Ø 在創建socket,bind之前使能SO_REUSEADDR,然后close()(如果客戶端斷網了,假如服務器端沒有keepalive(或者心跳包),服務器端沒法知道客戶端斷網了,也就沒法執行close()函數,而是傻傻繼續等待客戶端的數據)------- 適用于服務器不用檢測客戶端是否存在

Ø 如果使用keepalive,客戶端斷開網絡(比如客戶端被拔了網線),服務器的keepalive機制可以檢測到,read()返回失敗,服務器再次創建時不需要等待2MSL ------- 適用于服務器需要檢測客戶端是否存在

對于TIME_WAIT的插曲:

當建立一個TCP連接時,服務器端會繼續用原有端口監聽,同時用這個端口與客戶端通信。而客戶端默認情況下會使用一個隨機端口與服務器端的監聽端口通信。有時候,為了服務器端的安全性,我們需要對客戶端進行驗證,即限定某個IP某個特定端口的客戶端??蛻舳丝梢允褂胋ind來使用特定的端口。對于服務器端,當設置了SO_REUSEADDR選項時,它可以在2MSL內啟動并listen成功。但是對于客戶端,當使用bind并設置SO_REUSEADDR時,如果在2MSL內啟動,雖然bind會成功,但是在windows平臺上connect會失敗。而在linux上則不存在這個問題。(我的實驗平臺:winxp, ubuntu7.10)

要解決windows平臺的這個問題,可以設置SO_LINGER選項。SO_LINGER選項決定調用close時TCP的行為。SO_LINGER涉及到linger結構體,如果設置結構體中l_onoff為非0,l_linger為0,那么調用close時TCP連接會立刻斷開,TCP不會將發送緩沖中未發送的數據發送,而是立即發送一個RST報文給對方,這個時候TCP連接就不會進入TIME_WAIT狀態。如你所見,這樣做雖然解決了問題,但是并不安全。通過以上方式設置SO_LINGER狀態,等同于設置SO_DONTLINGER狀態。

套接字 SO_LINGER 選項可以規定 close() 的行為:

l_onoff為0,則該選項關閉,l_linger的值被忽略,等于缺省情況,close立即返回;
l_onoff為非0,l_linger為0,則套接口關閉TCP連接時,TCP將丟棄保留在套接口發送緩沖區中的任何數據并發送一個RST給對方,而不是通常的四分組終止序列,這避免了TIME_WAIT狀態;
l_onoff為非0,l_linger為非0,當套接口關閉時內核將拖延一段時間(由l_linger決定)。如果套接口緩沖區中仍殘留數據,進程將處于睡眠狀態,直到(a)所有數據發送完且被對方確認,之后進行正常的終止序列(描述字訪問計數為0)或(b)延遲時間到。此種情況下,應用程序檢查close的返回值是非常重要的,如果在數據發送完并被確認前時間到,close將返回EWOULDBLOCK錯誤且套接口發送緩沖區中的任何數據都丟失。close的成功返回僅告訴我們發送的數據(和FIN)已由對方TCP確認,它并不能告訴我們對方應用進程是否已讀了數據。如果套接口設為非阻塞的,它將不等待close完成

總結

以上是生活随笔為你收集整理的TCP ------ TCP四次挥手(断开连接)及断开过程的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。