計算機網絡——TCP 協議的三次握手 / 四次揮手

簡述

TCP / UDP 協議都是傳輸層的協議。

UDP 是面向無連接的協議,就是說發送端不在乎消息數據是否傳輸到接收端了,所以會出現數據丟失的情況,所以可靠性也不高。

TCP 是面向連接的、可靠的、基于字節流的傳輸層協議。所謂面向連接的,就是必須發送端和接收端必須處于連接狀態才能發送數據。可靠的就是無論網路鏈路出現的什么變化,都可以保證一個報文能夠到達接收端。

字節流:用戶消息通過 TCP 協議傳輸時,消息可能會被操作系統分組成多個 TCP 報文,如果接收方的程序如果不知道消息的邊界,是無法讀出一個有效的用戶消息的。

TCP 建立連接

TCP 是面向連接的,所以傳輸數據前需要和接收端建立連接,通過三次握手來進行。過程如下圖:

圖片來源: 小林coding

簡單描述一下三次握手:

1. 客戶端首先初始化自己的序列號,發送帶有 SYN 標識的報文給服務端,表示向服務端發起連接。客戶端進入?SYN-SEND 狀態。

2. 服務端接收到報文之后,同樣初始化自己的序列號,同時將確認應答的序列號,也就是收到的客戶端的序列號 + 1,返回給客戶端發送帶有 SYN + ACK 標識的報文,表示我接收到了你的連接請求,并同意連接。服務端進入?SYN-RCVD?狀態。

3. 客戶端接收到了服務端發來的應答,將收到的客戶端的序列號 + 1,再次向服務端發送帶有 ACK 表示的報文,表示我接收到你發的應答了,確認進入連接狀態。這次握手是可以攜帶客戶端到服務端的數據。客戶端進入?ESTABLISHED?狀態,在服務端收到客戶端的應答之后也進入?ESTABLISHED?狀態。

用一個例子來描述三次握手的情況。

為什么是三次握手

主要原因:三次握手是為了阻止重復歷史連接的初始化。

設想一個場景,當客戶端向服務端發送一個請求連接的報文之后宕機了,報文在到達服務器前被網絡阻塞了,此時服務器并沒有收到連接請求,狀態沒有變化。然后客戶端重啟之后,再次向服務端發送連接的報文。會出現下面的情況。

假設此時舊的請求報文比新的先到達服務端,然后向客戶端發送應答報文,都知道,報文里是包含了客戶端的序列號的,假設初始序列號是10,而服務端返回的是11(10+1),而客戶端在重啟之后發送的序列號是20,所以客戶端現在期望收到的報文序列號應該是21(20+1),但是此時收到的是11,那么就會向服務端發送 RST 請求報文, 表示出現了歷史連接,此次連接中止。(有內鬼,中止交易)。

而后一段時間之后,新發送的連接請求報文到達服務端,之后就會進行正常的 TCP 連接。用一個圖來簡單描述一下。

那么兩次握手能不能解決歷史連接的問題呢。

假設兩次握手,那么第一次握手服務端收到客戶端的SYN 之后,就進入到了 ESTABLISHED 狀態,此時服務端是可以向客戶端發送數據了,但是這個時候客戶端還沒有進入到?ESTABLISHED 狀態。服務端向客戶端發送 SYN+ACK 的報文之后,客戶端如果判斷此次是歷史連接,那么會回復 RST 中斷連接。但在這個期間,如果服務端發送了數據,那么發送的數據可能就丟失了,還浪費了資源。

三次握手之所以能解決歷史連接的問題,就是因為如果這是歷史連接,在第二次握手時服務端并不會進入到?ESTABLISHED 狀態,也就不能發送數據給客戶端,不會白白浪費資源。而是在客戶端確認了不是歷史連接的之后轉變狀態。

其他原因:同步初始序列號,避免浪費資源

1. 第一次握手,客戶端向服務端發送報文。

2. 第二次握手,服務端向客戶端發送報文,確認了客戶端發送正常,服務端接收正常。

3. 第三次握手,客戶端最后向服務端應答報文,確認了服務端發送正常,客戶端接收正常。

由此確認了客戶端和接收端連接正常。因為握手是會交換序列號的,也就是同步序列號,序列號在傳輸數據時去除重復的數據,可以根據序列號按序接收。

而兩次握手不能確保序列號同步,同時不能確認是否連接正常,假如只有兩次握手,少了第三次握手,那么服務端不知道客戶端的接收是否正常,如果不正常,那么服務端發送的數據就會丟失,浪費了資源。

握手過程中出現了報文丟失怎么辦

當第一次握手丟失了,當客戶端向服務端第一次握手,然后客戶端遲遲收不到服務端的 SYN+ACK 的報文,就會觸發超時重傳,重傳的報文序列號是一樣的。

而超時時間和重傳次數也有限制,不可能一直讓客戶端發送連接請求,浪費資源,在Linux 里,重傳次數是 5 ,而每次超時時間是上一次的兩倍,一般第一次是 1秒,第二次就是2秒,以此類推,5次重傳總耗時就是 1+2+4+8+16+31 = 63秒,大約一分鐘,如果5次都丟失,那么就不會再進行連接了。

第二次握手丟失。第二次握手包含了給客戶端的回應報文 ACK,和服務端發起建立連接的請求報文 SYN ,如果丟失了,客戶端會以為第一次握手丟失了,那么會觸發超時重傳。正常情況下,客戶端接收到第二次握手之后會發送 ACK 響應報文給服務端,但是服務端遲遲都收不到,那么服務端也會觸發超時重傳機制。

第三次握手丟失。第三次握手是客戶端發送給服務端的響應報文,如果丟失了,服務端會認為第二次握手丟失了,所以服務端會觸發超時重傳機制。

TCP 斷開連接的四次揮手

TCP 建立連接時需要發送報文,斷開連接時同樣需要發送報文。

1. 首先客戶端想要斷開連接,會發送一個帶有 FIN 標識的請求報文給服務端。客戶端進入 FIN_WAIT_1 狀態。

2. 服務端接收到報文之后會回復給客戶端一個帶有 ACK 標識的應答報文。服務端進入 CLOSE_WAIT 狀態。客戶端接收到 ACK 報文之后進入 FIN_WAIT_2 狀態。

3. 因為想要斷開連接時服務端可能還有數據沒有處理完,所以需要等待處理完成,處理完成之后會發送帶有 FIN 標識的請求報文給客戶端。服務端進入 LAST_ACK 狀態。

4. 客戶端接收到報文之后最后返回帶有 ACK 標識的應答報文給服務端,客戶端進入 TIME_WAIT? 狀態。服務端接收到ACK 報文之后進入到 CLOSE 狀態。一段時間之后,客戶端會進入 CLOSE 狀態,雙方都關閉連接。

圖片來源 小林coding

可以用打電話的方式來打個比方。

為什么要揮手四次

從每次揮手發送帶有標識的報文可以看出來,關閉連接時,客戶端向服務端發送 FIN 報文,只是代表客戶端已經發送數據完畢了,但是還能接收數據,同樣的服務端也是這樣。

服務端收到 FIN 報文時,回復一個 ACK 應答報文,表示我收到了你的請求,但是你先等等,我還有數據沒處理完,等到我數據處理完了,我再發送客戶端一個 FIN 報文表示我也沒數據需要處理和發送了。

假設少了一次揮手,比如說服務端只發送了 ACK 報文,客戶端就關閉連接的話,會導致還未處理和發送的數據出現錯誤或者丟失。

不過,在特定情況下,可以將四次揮手合并成三次揮手。比如服務端也沒有數據處理和發送時,TCP 存在延遲確認機制且是默認開啟的,那么第二次和第三次就會合并,變成三次揮手。

揮手丟失的話會發生什么

和握手相同,如果握手丟失了,發送方遲遲收不到回應,就會認為剛剛的報丟失了,就會觸發超時重傳機制。同樣的是 ACK 報文是不會重傳的,假如第二次揮手丟失了,那么客戶端收不到 ACK 應答報文,那么就會認為FIN 報文丟失了,那么就會重傳 FIN 報文。

簡單來說,當前最近的 FIN 報文發送方會經常重傳 FIN 報文。

為什么第四次揮手客戶端需要等待 2*MSL(報文最長壽命)時間后才進入 CLOSE?狀態

在第三次揮手時,服務端會發送 FIN 報文給客戶端,關閉連接,但是如果出現了第三次或者第四次揮手丟失的情況,服務端都會觸發超時重傳機制來重新發送 FIN 報文。

MSL 一個片段在網絡中最大的存活時間,2MSL 就是一個發送和一個回復所需的最大時間,如果這個大于這個時間客戶端還沒有收到服務端重新發送的 FIN 報文,那么客戶端就認為服務端已經接收到了自己發送的 ACK 應答報文,然后進行 CLOSE 狀態,代表 TCP 連接完成中斷。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/16142.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/16142.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/16142.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Flink-cdc更好的流式數據集成工具

What’s Flink-cdc? Flink CDC 是基于Apache Flink的一種數據變更捕獲技術,用于從數據源(如數據庫)中捕獲和處理數據的變更事件。CDC技術允許實時地捕獲數據庫中的增、刪、改操作,將這些變更事件轉化為流式數據,并能夠…

Windows平臺C#版RTSP轉RTMP直播推送定制版

技術背景 前幾年我們發布了C版的多路RTMP/RTSP轉RTMP轉發官方定制版。在秉承低延遲、靈活穩定、低資源占用的前提下,客戶無需關注開發細節,只需圖形化配置轉發等各類參數,實現產品快速上線目的。 如監控類攝像機、NVR等,通過廠商…

【啟程Golang之旅】深入解析函數的奧秘與技巧

歡迎來到Golang的世界!在當今快節奏的軟件開發領域,選擇一種高效、簡潔的編程語言至關重要。而在這方面,Golang(又稱Go)無疑是一個備受矚目的選擇。在本文中,帶領您探索Golang的世界,一步步地了…

【全開源】海報在線制作系統源碼(ThinkPHP+FastAdmin+UniApp)

打造個性化創意海報的利器 引言 在數字化時代,海報作為一種重要的宣傳媒介,其設計質量和效率直接影響著宣傳效果。為了滿足廣大用戶對于個性化、高效制作海報的需求,海報在線制作系統源碼應運而生。本文將詳細介紹海報在線制作系統源碼的特…

AbMole - 腫瘤發展與免疫器官的“舞蹈”:一場細胞層面的時間賽跑

在生物醫學領域,腫瘤與免疫系統之間的相互作用一直是研究的熱點話題。腫瘤細胞不是孤立存在的,它們與宿主的免疫系統進行著一場復雜的“舞蹈”。 最近,一項發表在《Molecular & Cellular Proteomics》雜志上的研究,為我們揭開…

【C++】二分查找算法

1.題目 2.算法思路 暴力解法:可以將數組遍歷一遍,就可以找到。時間復雜度為O(n)。不算太差,可以接受。 但是有更優秀的解法: 就是二分查找算法。 算法的特點:我們所查找的“數組”具有二段性。這里的二段性不一定有…

頭歌OpenGauss數據庫-L.應用開發(Python)-選做

第1關:簡單查詢 編程要求 正確使用 psycopg2 ,查詢金融應用場景數據庫 finance 的 client 表(客戶表)中郵箱不為空的客戶信息,列出客戶姓名,郵箱和電話.一個展示結果的示例如下(字體顏色不是編程要求): 注意:你要連接到finance數據庫上(后面第2-6關也是連接這個數據庫)…

【C/C++】詳解關聯容器map的使用

🔗 運行環境:Matlab 🚩 撰寫作者:左手の明天 🥇 精選專欄:《python》 🔥 推薦專欄:《算法研究》 🔐#### 防偽水印——左手の明天 ####🔐 💗 大家…

mpv常用快捷鍵

1 mpv mpv是Linux下的一個開源視頻播放器,使用Manjaro的話安裝方式如下: paru -S mpv2 常用快捷鍵 q:推出w/e:視頻縮放r/t:調整字幕位置u:開啟/關閉ass/ssa字幕覆蓋i:顯示當前播放的視頻信息…

Oracle 并行和 session 數量的

這也就是為什么我們指定parallel為4,而實際并行度為8的原因。 insert create index,發現并行數都是加倍的 Indexes seem always created with parallel degree 1 during import as seen from a sqlfile. The sql file shows content like: CREATE INDE…

求平方數 1 到 N 之間所有正整數的平方數

概念: 平方數的概念: 平方數是指一個數的平方等于另一個數的數,具有正平方數和負平方數,其性質和運用在多領域中具有重要意義,如幾何、自然科學、計算機科學和物理學。平方數的計算和運用在多領域中常見,例…

滑不動窗口的秘密—— “滑動窗口“算法 (Java版)

本篇會加入個人的所謂魚式瘋言 ??????魚式瘋言:??????此瘋言非彼瘋言 而是理解過并總結出來通俗易懂的大白話, 小編會盡可能的在每個概念后插入魚式瘋言,幫助大家理解的. 🤭🤭🤭可能說的不是那么嚴謹.但小編初心是能讓更多人能接…

《python編程從入門到實踐》day39

# 昨日知識點回顧 創建主頁、繼承模版、顯示特定主題頁面 # view.py from django.shortcuts import render# 導入所需數據相關聯的模型 from .models import Topic# Create your views here. def index(request):"""學習筆記的主頁"""#…

Java進階學習筆記13——抽象類

認識抽象類: 當我們在做子類共性功能抽取的時候,有些方法在父類中并沒有具體的體現,這個時候就需要抽象類了。在Java中,一個沒有方法體的方法應該定義為抽象方法,而類中如果有抽象方法,該類就定義為抽象類…

ISCC2024個人挑戰賽WP-迷失之門

&#xff08;非官方解&#xff0c;以下內容均互聯網收集的信息和個人思路&#xff0c;僅供學習參考&#xff09; 迷失之門 方法一&#xff1a; IDA看一下 check函數邏輯 進入到check2函數 R鍵將ascii碼轉字符&#xff0c;寫出逆向腳本 #include <stdio.h> #include &l…

嵌入式0基礎開始學習 Ⅱ 數據結構(7)小結練習

1,如果使用比較高效的算法判斷單鏈表有沒有環的算法中&#xff0c;至少需要幾個指針&#xff1f; A,1 B,2 C,3 D,4 2&#xff0c;以鏈接方式存儲的線性表(X1,X2,...,Xn),當訪問第i個元素的時間復雜度為? A,o(1) B,o(n) C,o(logn) Do(n) 3,下列鏈表中&…

Linux C++ Socket 套接字、select、poll、epoll 實例

文章目錄 1. 概述2. TCP 網絡編程實例2.1 服務器端2.2 客戶端2.3 運行截圖 3. I/O 模型3.1 阻塞式I/O模型3.2 非阻塞I/O模型3.3 I/O 復用模型3.4 信號驅動式I/O3.5 異步I/O模型 4. I/O復用之 select4.1 select 函數描述4.2 服務端代碼4.3 客戶端代碼4.4 運行截圖 5. I/O復用之 …

RocketMq局部順序消息

package com.ldj.rocketmq.producer;import org.apache.rocketmq.client.producer.DefaultMQProducer; import org.apache.rocketmq.common.message.Message;import java.nio.charset.StandardCharsets;/*** User: ldj* Date: 2024/5/26* Time: 15:09* Description: 局部順序消…

【Linux】$()中的內容與不加$()時有什么區別

$()中的內容與不加$()有什么區別&#xff0c;例如$(/usr/local/hadoop/bin/hadoop classpath)與/usr/local/hadoop/bin/hadoop classpath兩者有何區別&#xff1f;&#xff1f;&#xff1f; 關于這個問題&#xff0c;筆者建議可以參考如下文章&#xff1a; Linux—shell中$((…

css卡片翻轉 父元素翻轉子元素不翻轉效果

css卡片翻轉 父元素翻轉子元素不翻轉效果 vue <div class"moduleBox"><div class"headTitle"><span class"headName">大額案例</span></div><div class"moduleItem"><span class"module…