TCP中一些需要知道的事情

寫在前面:由于工作需要,在網上學習了一些TCP相關的知識點,內容不是很深刻,都是一些常用的需要了解的部分。在此非常感謝網上的眾位大神給出的TCP相關的文章,本文是學習后整理下來的讀書筆記,因為時隔一段時間,并且閱讀了好幾篇文章,所以不記得大神們的文章地址了,無法給出具體的參考文章地址,非常抱歉!

一、TCP和UDP

1. 什么是TCP和UDP

?OSI 七層模型通過七個層次化的結構模型使不同的系統不同的網絡之間實現可靠的通訊,因此其最主要的功能就是幫助不同類型的主機實現數據傳輸 。

? ? ?完成中繼功能的節點通常稱為中繼系統。在OSI七層模型中,處于不同層的中繼系統具有不同的名稱。

? ? ?一個設備工作在哪一層,關鍵看它工作時利用哪一層的數據頭部信息。網橋工作時,是以MAC頭部來決定轉發端口的,因此顯然它是數據鏈路層的設備。

? ? ?具體說:

? ? ?? ? ?物理層:網卡,網線,集線器,中繼器,調制解調器

? ? ?? ? ?數據鏈路層:網橋,交換機

? ? ?? ? ?網絡層:路由器

? ? ?? ? ?網關工作在第四層傳輸層及其以上

? ? ?? ? ?tcp/udp在模型的傳輸層

? ? ?更詳細的可參考:OSI七層模型詳解?

? ? ?這里我們只需要知道:HTTP、WebSocket 等協議都是處于 OSI 模型的最高層:?應用層?。而 IP 協議工作在網絡層(第3層),TCP 協議、UDP協議工作在傳輸層(第4層)。

2.TCP與UDP的區別

? ? 2.1. TCP與UDP及其優缺點:

3.TCP長連接、短連接

? ? 3.1 TCP長連接

? ? ? ? ? 所謂長連接,指在一個TCP連接上可以連續發送多個數據包,在TCP連接保持期間,如果沒有數據包發送,需要雙方發檢測包以維持此連接,一般需要自己做在線維持(不發生RST包和四次揮手)。 ? ? ?

? ? ? ? ? 整個過程:連接→數據傳輸→保持連接(心跳)→數據傳輸→保持連接(心跳)→……→關閉連接(一個TCP連接通道多個讀寫通信);?

? ? ? ? ?這就要求長連接在沒有數據通信時,定時發送數據包(心跳),以維持連接狀態;

? ? ? ? ?TCP保活功能,保活功能主要為服務器應用提供,服務器應用希望知道客戶主機是否崩潰,從而可以代表客戶使用資源。如果客戶已經消失,使得服務器上保留一個半開放的連接,而服務器又在等待來自客戶端的數據,則服務器將應遠等待客戶端的數據,保活功能就是試圖在服務器端檢測到這種半開放的連接。

? ? ? ? ?如果一個給定的連接在兩小時內沒有任何的動作,則服務器就向客戶發一個探測報文段,客戶主機必須處于以下4個狀態之一:

客戶主機依然正常運行,并從服務器可達。客戶的TCP響應正常,而服務器也知道對方是正常的,服務器在兩小時后將保活定時器復位。

客戶主機已經崩潰,并且關閉或者正在重新啟動。在任何一種情況下,客戶的TCP都沒有響應。服務端將不能收到對探測的響應,并在75秒后超時。服務器總共發送10個這樣的探測 ,每個間隔75秒。如果服務器沒有收到一個響應,它就認為客戶主機已經關閉并終止連接。

客戶主機崩潰并已經重新啟動。服務器將收到一個對其保活探測的響應,這個響應是一個復位,使得服務器終止這個連接。

客戶機正常運行,但是服務器不可達,這種情況與2類似,TCP能發現的就是沒有收到探查的響應。

在長連接中一般是沒有條件能夠判斷讀寫什么時候結束,所以必須要加長度報文頭。讀函數先是讀取報文頭的長度,再根據這個長度去讀相應長度的報文。

? ? ?3.2. TCP短連接

短連接是指通信雙方有數據交互時,就建立一個TCP連接,數據發送完成后,則斷開此TCP連接(管理起來比較簡單,存在的連接都是有用的連接,不需要額外的控制手段);

? ? ? ? ? ? ? 整個過程:連接→數據傳輸→關閉連接;

? ? ?3.3 TCP長連接和短連接的優缺點:

?3.3 TCP長連接和短連接的應用場景:

? ? ? ? ? ? ?長連接多用于操作頻繁(讀寫),點對點的通訊,而且連接數不能太多情況,。每個TCP連接都需要三步握手,這需要時間,如果每個操作都是先連接,再操作的話那么處理速度會降低很多,所以每個操作完后都不斷開,次處理時直接發送數據包就OK了,不用建立TCP連接。例如:數據庫的連接用長連接, 如果用短連接頻繁的通信會造成socket錯誤,而且頻繁的socket 創建也是對資源的浪費。

? ? ? ? ? ? ?而像WEB網站的http服務一般都用短鏈接(http1.0只支持短連接,1.1keep alive 帶時間,操作次數限制的長連接),因為長連接對于服務端來說會耗費一定的資源,而像WEB網站這么頻繁的成千上萬甚至上億客戶端的連接用短連接會更省一些資源,如果用長連接,而且同時有成千上萬的用戶,如果每個用戶都占用一個連接的話,那可想而知吧。所以并發量大,但每個用戶無需頻繁操作情況下需用短連好;

二、TCP的三次握手和四次揮手

上面說到過:TCP 協議、UDP協議工作在傳輸層(第4層)。從最上面的圖中,我們也可以看到,HTTP、WebSocket 等應用層協議,都是基于 TCP 協議來傳輸數據的。我們可以把這些高級協議理解成對 TCP 的封裝。

? ? 既然大家都使用 TCP 協議,那么大家的連接和斷開,都要遵循?TCP 協議中的三次握手(建立連接)和四次握手(斷開連接) ,只是在連接之后發送的內容不同,或者是斷開的時間不同。

1.TCP的三次握手(用于建立連接)

? ? ? 首先Client端發送連接請求報文,Server段接受連接后回復ACK報文,并為這次連接分配資源。Client端接收到ACK報文后也向Server段發生ACK報文,并分配資源,這樣TCP連接就建立了。

在TCP/IP協議中,TCP協議通過三次握手建立一個可靠的連接

2.TCP的四次握手(用于斷開連接)

?當客戶端和服務器通過三次握手建立了TCP連接以后,當數據傳送完畢,肯定是要斷開TCP連接的啊。那對于TCP的斷開連接,這里就有了神秘的“四次揮手”。

第一次揮手:主機1(可以使客戶端,也可以是服務器端),設置Sequence Number和Acknowledgment Number,向主機2發送一個FIN報文段;此時,主機1進入FIN_WAIT_1狀態;這表示主機1沒有數據要發送給主機2了;

第二次揮手:主機2收到了主機1發送的FIN報文段,向主機1回一個ACK報文段,Acknowledgment Number為Sequence Number加1;主機1進入FIN_WAIT_2狀態;主機2告訴主機1,我“同意”你的關閉請求;

第三次揮手:主機2向主機1發送FIN報文段,請求關閉連接,同時主機2進入LAST_ACK狀態;

第四次揮手:主機1收到主機2發送的FIN報文段,向主機2發送ACK報文段,然后主機1進入TIME_WAIT狀態;主機2收到主機1的ACK報文段以后,就關閉連接;此時,主機1等待2MSL后依然沒有收到回復,則證明Server端已正常關閉,那好,主機1也可以關閉連接了。

【注意】?在TIME_WAIT狀態中,如果TCP client端最后一次發送的ACK丟失了,它將重新發送。TIME_WAIT狀態中所需要的時間是依賴于實現方法的。典型的值為30秒、1分鐘和2分鐘。等待之后連接正式關閉,并且所有的資源(包括端口號)都被釋放。

? ??【問題】為什么TIME_WAIT狀態需要經過2MSL(最大報文段生存時間)才能返回到CLOSE狀態?

? ? ? 答:雖然按道理,四個報文都發送完畢,我們可以直接進入CLOSE狀態了,但是我們必須假象網絡是不可靠的,有可以最后一個ACK丟失。所以TIME_WAIT狀態就是用來重發可能丟失的ACK報文。

3.為什么要四次握手(用于斷開連接)

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

FIN_WAIT_1: 這個狀態要好好解釋一下,其實FIN_WAIT_1和FIN_WAIT_2狀態的真正含義都是表示等待對方的FIN報文。而這兩種狀態的區別是:FIN_WAIT_1狀態實際上是當SOCKET在ESTABLISHED狀態時,它想主動關閉連接,向對方發送了FIN報文,此時該SOCKET即進入到FIN_WAIT_1狀態。而當對方回應ACK報文后,則進入到FIN_WAIT_2狀態,當然在實際的正常情況下,無論對方何種情況下,都應該馬上回應ACK報文,所以FIN_WAIT_1狀態一般是比較難見到的,而FIN_WAIT_2狀態還有時常常可以用netstat看到。(主動方)

FIN_WAIT_2:上面已經詳細解釋了這種狀態,實際上FIN_WAIT_2狀態下的SOCKET,表示半連接,也即有一方要求close連接,但另外還告訴對方,我暫時還有點數據需要傳送給你(ACK信息),稍后再關閉連接。(主動方)

CLOSE_WAIT:這種狀態的含義其實是表示在等待關閉。怎么理解呢?當對方close一個SOCKET后發送FIN報文給自己,你系統毫無疑問地會回應一個ACK報文給對方,此時則進入到CLOSE_WAIT狀態。接下來呢,實際上你真正需要考慮的事情是察看你是否還有數據發送給對方,如果沒有的話,那么你也就可以 close這個SOCKET,發送FIN報文給對方,也即關閉連接。所以你在CLOSE_WAIT狀態下,需要完成的事情是等待你去關閉連接。(被動方)

LAST_ACK: 這個狀態還是比較容易好理解的,它是被動關閉一方在發送FIN報文后,最后等待對方的ACK報文。當收到ACK報文后,也即可以進入到CLOSED可用狀態了。(被動方)

TIME_WAIT: 表示收到了對方的FIN報文,并發送出了ACK報文,就等2MSL后即可回到CLOSED可用狀態了。如果FINWAIT1狀態下,收到了對方同時帶FIN標志和ACK標志的報文時,可以直接進入到TIME_WAIT狀態,而無須經過FIN_WAIT_2狀態。(主動方)

CLOSED: 表示連接中斷。

4.為什么連接的時候是三次握手,關閉的時候卻是四次握手?

? ??因為當Server端收到Client端的SYN連接請求報文后,可以直接發送SYN+ACK報文。其中ACK報文是用來應答的,SYN報文是用來同步的。但是關閉連接時,當Server端收到FIN報文時,很可能并不會立即關閉SOCKET,所以只能先回復一個ACK報文,告訴Client端,"你發的FIN報文我收到了"。只有等到我Server端所有的報文都發送完了,我才能發送FIN報文,因此不能一起發送。故需要四步握手。

5. TCP斷開由誰發起?

? ??中斷連接端可以是Client端,也可以是Server端。

? ??假設Client端發起中斷連接請求,也就是發送FIN報文。Server端接到FIN報文后,意思是說"我Client端沒有數據要發給你了",但是如果你還有數據沒有發送完成,則不必急著關閉Socket,可以繼續發送數據。所以你先發送ACK,"告訴Client端,你的請求我收到了,但是我還沒準備好,請繼續你等我的消息"。這個時候Client端就進入FIN_WAIT狀態,繼續等待Server端的FIN報文。當Server端確定數據已發送完成,則向Client端發送FIN報文,"告訴Client端,好了,我這邊數據發完了,準備好關閉連接了"。Client端收到FIN報文后,"就知道可以關閉連接了,但是他還是不相信網絡,怕Server端不知道要關閉,所以發送ACK后進入TIME_WAIT狀態,如果Server端沒有收到ACK則可以重傳。“,Server端收到ACK后,"就知道可以斷開連接了"。Client端等待了2MSL后依然沒有收到回復,則證明Server端已正常關閉,那好,我Client端也可以關閉連接了。Ok,TCP連接就這樣關閉了!

? ??整個過程Client端所經歷的狀態如下:

而Server端所經歷的過程如下:

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容