TCP的建立連接,包重傳,關閉連接

佛家喜歡講緣起,確實很多事情都不是無緣無故發生,這篇文章就是今天早上跟朋友聊天時提到谷歌的BBR,然後我意識到自己網絡方面的知識很匱乏,帶着疑問去搜索答案,在搜索的過程中產生新的疑問,然後再尋找答案。最後就有了這篇文章。

傳輸層主要有兩個協議:TCP和UDP,TCP是面向連接的,是可靠的。UDP只管發送數據報(datagram),不管發送出去會發生什麼,這種人活得很輕鬆,對自己的消耗很少,Facebook的傳輸層協議就是UDP,可靠性就由應用層的應用來負責。

TCP的連接

我們說TCP是面向連接的,那麼這個連接指的是什麼呢,我的理解是這樣,A連接到B就意味着A可以向B發送數據,而且A知道它可以向B發送數據,在UDP中雖然A也可以向B發送數據,但是A不知道它到底能不能向B發送數據,它不關心這個。

TCP的連接是全雙工連接,也就是雙向的,A到B有連接,B到A也有連接。
我們來看一下建立TCP連接的三次握手過程。假設A是連接的發起方。

  1. SYN:A向B發送SYN,表示自己想和B建立連接。並且用一個隨機數字作爲segment number(傳輸層會把應用層的數據分段後再傳輸,所以傳輸層的數據單位是TCP segment,網絡層的單位是IP datagram,數據鏈路層的單位是frame),比如說這個數字是x.
  2. SYN-ACK:B接受到A發送的包之後,明白了A想和它建立連接,因爲TCP是全雙工的,所以B也需要和A建立連接,B向A發送SYN,表示自己想和A建立連接,然後把ACK字段設置成x+1,這表示自己成功地接收到了A發給它的數據,A和自己的連接建立成功,用一個隨機數y作爲segment number。
  3. ACK:A收到B發送過來的數據包之後,發現ACK是x+1,知道它和B的連接建立起來了,發現有SYN,知道B想和它建立連接,發現segment number是y,然後它向B發送數據包,把ACK設置爲y+1,向B證明B到A的連接建立成功。這時候雙向連接都建立成功。
TCP的可靠性

TCP的可靠性主要是指重傳丟失的包,因爲網絡環境很複雜,丟包是難免的,所以如何處理丟包就顯得很重要。

發送方重傳丟失的包,第一步就是它應該知道哪些包在網絡中丟了,有兩種思路,第一種就是知道哪些包沒丟,正確地送達了(在規定時間內正確地送達了,因爲發送方不可能一直去等待所有包正確送達的消息,死亡確認要能找到屍體,丟的包不能這樣),沒送達的那就是丟失了;第二種就是知道哪些包丟失了,需要重傳,這種方法不需要等待最大等待時間,可以直接重傳,所以用在快速重傳機制裏。

如果一次發送一個包,然後等待確認,之後再發送一個包,等待確認,這樣子對下層的網絡層和數據鏈路層資源是極大的浪費,本來可以有更大的出入流量。爲了解決這個問題,TCP協議使用了滑動窗口協議
比如接受方可以把ACK的窗口大小設置成100,發給發送方的數據包裏面填上“我需要0-99這100個segment”-------發送方接受到之後給接收方就可以一下子發送100個段,-------接收方拿到手裏發現缺第50個段,這時候它會把ACK的窗口大小設置成1,發給發送方的數據包裏面填上“我需要50這一個段”,-------發送方重傳50這個段,-------接收方拿到之後發現是自己想要的,這時候它再把ACK的窗口大小設置成100,發給發送方的數據包裏面會填上“我需要100到199這100個段”,-------發送方接受到之後會知道上次的傳送成功了,會再一下子傳100個相應的段過去。

TCP連接的關閉過程

TCP連接的關閉過程也體現着可靠,兩個遠程主機對彼此可靠就意味着兩個人對他們之間發生的事情有個協商的機制,只有UDP這種渣男纔不管對方怎麼想。

四次揮手。假設A主動斷開連接

  1. FIN:A向B發送FIN,表示自己想斷開連接
  2. ACK:B向A發送ACK,表示自己知道A想斷開連接了,但是先等一等,我暫時還不想斷開連接(這就是協商)
  3. FIN:B向A發送FIN,表示自己現在也想斷開連接了。
  4. ACK:A向B發送ACK,表示自己知道B也想斷開連接了,既然雙方都同意斷了聯繫,那就斷了聯繫吧。

可以看到其實和建立連接的過程很相似,只不過建立連接時另一方會馬上接受,並且表達自己想和發起方建立連接的意願,哎,這是多飢渴。

總結

很煩是不是,確實很煩,什麼都要商量着來。好人不好當。也很累。
TCP中的ACK很重要。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章