在網絡的傳輸層協議中, 存在着兩大悍將: TCP
和 UDP
. 從前, 我傻傻的覺得本身對他們雖談不上精通, 但仍是知道的, 可是, 我錯了, 我被本身問住了, 我傻了. 啥也不是.安全
(這裏爲了介紹簡單, 就不提數據在傳輸過程當中的失真(糾錯碼)等狀況了. 簡單介紹一下, TCP
纔是今天的主角)服務器
UDP 就是, 我把數據發給你了, 我無論你有沒有收到, 反正我發出去了, 任性. 就好比我要給個人女神表白, 可是我又很差意思, 因此我託個人好兄弟馬六幫我給女神帶句話, 可是這個馬六也臉皮薄, 他又找週三轉達, 就這樣雖然歷經波折, 但最後仍是順利的將話帶到了女神那裏. 在這個過程當中我作了什麼? 我只是將消息送出去了, 僅此而已. 最後我滿心歡喜的等待着女神的回覆, 可能換回一句: 咱們仍是作朋友吧. 但還有一種可能, 那就是最終根本就沒有送到女神那裏, 中間轉到週三的時候, 他由於本身的事情, 把這事給忘了, 可憐的我還苦苦的等...網絡
UDP
雖然省事, 高效, 可是卻不可靠. 由於我僅僅是發出去了, 可是我不肯定你有沒有收到. 不可靠有什麼問題麼? 上面就是個例子. 再好比, 咱倆聊天, 我給你發了一段話: 123456
, 結果中間4丟了, 你收到的信息是: 12356
. 這種還好, 若是快過年了, 我發給你這樣一段話: 明天把你的豬宰了吧
, 哎, 中間 的豬
丟了, 那估計免不了一番腥風血雨.tcp
那如此不可靠的UDP
協議, 有什麼用呢? 還真有, 雖然不可靠, 可是他快啊. 在一些對數據的可靠性要求不高, 可是實時性很強的地方就有了用武之地, 好比視頻電話(我也不知道底層是否是 UDP, 舉個例子), 打視頻電話的時候, 視頻要保證其連續性, 並且中間若是丟了一幀也不會有什麼影響.測試
可是在大多數場景下, 數據的可靠性仍是要有保證的, 你從網上下載一個程序的安裝包, 若是中間丟了一個字節的數據, 那可能就致使一個200mb 的文件廢了, 根本不能執行.code
爲了保證傳輸數據的可靠性, TCP
誕生了. 還記得剛纔我給女神表白的時候, 問題出在哪裏嗎? 沒錯, 就是由於我到最後苦苦等待, 結果她悲劇的沒有收到個人心意, 傷心. 怎麼辦呢? 此次我想通了, 求人不如求己, 我要鼓起勇氣, 我到她面前當面告訴她, 即便我多了一個朋友(沒辦法, 咱就喜歡交朋友), 也好過她收不到消息的好. 這下可靠了, 我確信她收到了.視頻
區別在哪裏? 不是我到他面前, 而是無論她是否願意, 至少給爺們回句話吧. 沒錯, 就是回句話.內存
若是有這樣一種機制, 每次我發出去的數據, 若是對方收到了, 就給我回句話, 告訴我收到了, 那消息就變得可靠了. 我發出去的全部消息, 均可以確信對方已經收到了.資源
一個來自靈魂的提問, 如今的數據發送可靠嗎? 我以爲是不可靠的, 如今僅僅可以保證一個數據包, 我百分百的確信對方已經收到了. 那什麼樣的鏈接纔是可靠的呢?開發
我要發你100個數據包, 那這100個數據包你每個都要可以收到, 而且要按照順序將他們再拼裝起來, 我以爲這樣的鏈接才能稱得上可靠. 這裏面涉及到了兩個概念, 確保收到
和 順序
. 確保收到咱們已經作到了, 如何保證包的順序呢? 我把要發的數據排排隊, 一個一個發就好了? 天真, 若是有包1在網絡中某個地方喝了杯茶, 睡了一覺, 結果接收方先收到了包2後收到包1, 順序就亂了. 保證順序的方式其實很簡單, 在每個包上, 都加上一個序號, 接收方按照序號從小到大把收到的包組裝起來就行了.
通過改造, 如今已經基本可以保證傳輸的可靠性了, 到這裏, 有沒有發現什麼? 如今和TCP
的區別就是少了三次握手
和四次揮手
(不只僅是). 那三次握手
的意義何在?
今天在接收了身邊大神的一些思想以後, 我仍是沒有太明白. 不過如今, 我貌似明白了些什麼. 要想知道三次握手有什麼用, 就須要知道三次握手都作了什麼事情.
1. 確保對方可以正常接收數據, 測試鏈接
仍是上面的例子, 我去女神面前表白, 但不湊巧, 女神正在午休, 我站着旁邊傻傻的表白, 仍是沒有用. 因此, 在開始以前, 我要先確保女神可以聽到我說的話, 我得把她叫醒, 莊重的告訴她. 而這, 就是握手的意義.
2.創建系統開銷
在發送 UDP 包的時候, 由於其不可靠性, 因此基本不會用其發送很大的文件, 由於將較大的數據拆分後發出, 中間丟了幾個數據包就尷尬了. 並且 UDP 也不可以保證包的順序, 仍是同樣的緣由. 可是 TCP 就不同了, 它是可靠的啊, 你能夠將多個數據包分開發給我, 到我這裏, 我再把他們按順序排列好就好了. 而這個按順序排列的操做就須要專門開闢內存空間來保存收到的數據包了, 當握手成功後, 我就會爲你留下用於保存數據包的內存空間及其餘一些系統資源.
而若是沒有三次握手呢? 客戶端發送的數據包, 可能由於某些緣由(好比路很差走), 在網絡中待的久了一些, 客戶端由於沒有收到回覆, 已經放棄鏈接了, 但這時候, 服務器收到了這個數據包, 開闢系統資源, 返回確認包, 而後就沒有而後了. 客戶端已經放棄了, 根本不搭理你的回覆. 系統的相關資源就白白浪費了.
3. 測試超時時間
上面說了, 當我長時間沒有收到你的回覆時, 我就認爲你沒有收到我發出的數據, 那我就須要從新發送了. 那這個長時間是多久呢? 能夠在握手期間進行測試, 測量請求包的往返時間,並依此計算重傳的超時時間.
4.安全性
這個確實是我沒有想到的. 由於 TCP 會將數據拆分後發送, 爲了保證數據的有序, 就要給每一個數據包進行編號. 而後接收方根據編號的順序對收到的包進行重組, 保證了數據的有序.
若是隻是簡單的123456, 那你們都知道了, 我黑客小黑, 也給你發一個編號爲1的數據包, 不就把你真實的數據包給偷偷替換了麼? 爲了防止序列號被猜到, 就要讓每次發送數據的序列號不一樣, 在進行握手的時候會對數據的初始序列號進行交換. 客戶端第一次發送握手信息的時候, 會連着本身的初始序列號一塊兒發過去, 服務器收到以後, 返回第二個握手信息的時候, 除了返回握手確認, 也會連着本身的初始序列號一塊兒發回來. 這在必定程度上保證了數據的安全傳輸. 固然這種防禦措施很弱.
這個隨機的序列號其實還有另一個做用, 我以爲這纔是它最主要的做用. 若是咱們上一次鏈接的其中一個數據包3, 在網絡中傲遊了一會, 鏈接已經斷開了, 咱們又開始了新的一次數據鏈接, 這個時候我收到了數據包3, 就會致使生成了錯誤的數據序列, 而隨機序列號則避免了這個問題,
三次握手
確實是有些做用, 那四次揮手
有什麼用呢?
1.釋放系統資源
在三次握手的時候, 爲了接收數據並進行序列重組, 開闢了一些系統資源, 當數據發送完了, 就不用一直佔着了, 早些釋放, 留給別人.
額, 應該還有其餘做用吧...
綜上, 你說若是沒有握手
和揮手
的過程, 能不能實現一個可靠的鏈接呢? 能夠, 只不過會有問題. 我的簡單將握手的做用總結爲如下幾點: