TCP的連接

TCP 三次握手過程是怎樣的?

TCP 是面向連接的協議,所以使用 TCP 前必須先建立連接,而建立連接是通過三次握手來進行的。三次握手的過程如下圖:

一開始,客戶端和服務端都處于?CLOSE?狀態。先是服務端主動監聽某個端口,處于?LISTEN?狀態

客戶端會隨機初始化序號(client_isn),將此序號置于 TCP 首部的「序號」字段中,同時把?SYN標志位置為?1,表示?SYN?報文。接著把第一個 SYN 報文發送給服務端,表示向服務端發起連接,該報文不包含應用層數據,之后客戶端處于?SYN-SENT?狀態。

服務端收到客戶端的?SYN?報文后,首先服務端也隨機初始化自己的序號(server_isn),將此序號填入 TCP 首部的「序號」字段中,其次把 TCP 首部的「確認應答號」字段填入?client_isn + 1,接著把?SYN?和?ACK?標志位置為?1。最后把該報文發給客戶端,該報文也不包含應用層數據,之后服務端處于?SYN-RCVD?狀態。

客戶端收到服務端報文后,還要向服務端回應最后一個應答報文,首先該應答報文 TCP 首部?ACK?標志位置為?1?,其次「確認應答號」字段填入?server_isn + 1?,最后把報文發送給服務端,這次報文可以攜帶客戶到服務端的數據,之后客戶端處于?ESTABLISHED?狀態。

服務端收到客戶端的應答報文后,也進入?ESTABLISHED?狀態。

從上面的過程可以發現第三次握手是可以攜帶數據的,前兩次握手是不可以攜帶數據的,一旦完成三次握手,雙方都處于?ESTABLISHED?狀態,此時連接就已建立完成,客戶端和服務端就可以相互發送數據了。

如何在 Linux 系統中查看 TCP 狀態?

TCP 的連接狀態查看,在 Linux 可以通過?netstat -napt?命令查看。

為什么是三次握手?不是兩次、四次?

相信大家比較常回答的是:“因為三次握手才能保證雙方具有接收和發送的能力。”

這回答是沒問題,但這回答是片面的,并沒有說出主要的原因。

在前面我們知道了什么是?TCP 連接

用于保證可靠性和流量控制的某些狀態信息,這些信息包括Socet,序列號,窗口大小。

所以,重要的是為什么三次握手才可以初始化 Socket、序列號和窗口大小并建立 TCP 連接。

接下來,以三個方面分析三次握手的原因:

  • 三次握手才可以阻止重復歷史連接的初始化(主要原因)
  • 三次握手才可以同步雙方的初始序列號
  • 次握手才可以避免資源浪費

原因一:阻止重復歷史連接的初始化

?RFC 793 指出的 TCP 連接使用三次握手的首要原因:三次握手的首要原因是為了防止舊的重復連接初始化造成混亂。

我們考慮一個場景,客戶端先發送了 SYN(seq = 90)報文,然后客戶端宕機了,而且這個 SYN 報文還被網絡阻塞了,服務端并沒有收到,接著客戶端重啟后,又重新向服務端建立連接,發送了 SYN(seq =100)報文(注意!不是重傳 SYN,重傳的 SYN 的序列號是一樣的)。

客戶端連續發送多次 SYN(都是同一個四元組)建立連接的報文,在網絡擁堵情況下:

一個「舊 SYN 報文」比「最新的 SYN」 報文早到達了服務端,那么此時服務端就會回一個?SYN +ACK?報文給客戶端,此報文中的確認號是 91(90+1)。

客戶端收到后,發現自己期望收到的確認號應該是 100 + 1,而不是 90 + 1,于是就會回 RST 報文。

服務端收到 RST 報文后,就會釋放連接。

上述中的「舊 SYN 報文」稱為歷史連接,TCP 使用三次握手建立連接的最主要原因就是防止「歷史連接」初始化了連接

原因二:同步雙方初始序列號

TCP 協議的通信雙方, 都必須維護一個「序列號」, 序列號是可靠傳輸的一個關鍵因素,它的作用:

  • 接收方可以去除重復的數據;
  • 接收方可以根據數據包的序列號按序接收;
  • 可以標識發送出去的數據包中, 哪些是已經被對方收到的(通過 ACK 報文中的序列號知道);

兩次握手只保證了一方的初始序列號能被對方成功接收,沒辦法保證雙方的初始序列號都能被確認接收。

初始序列號 ISN 是如何隨機產生的?

起始?ISN?是基于時鐘的,每 4 微秒 + 1,轉一圈要 4.55 個小時。

RFC793 提到初始化序列號 ISN 隨機生成算法:ISN = M + F(localhost, localport, remotehost,remoteport)。

  • M?是一個計時器,這個計時器每隔 4 微秒加 1。
  • F?是一個 Hash 算法,根據源 IP、目的 IP、源端口、目的端口生成一個隨機數值。

以看到,隨機數是會基于時鐘計時器遞增的,基本不可能會隨機成一樣的初始化序列號。

既然 IP 層會分片,為什么 TCP 層還需要 MSS 呢?

  • MTU:一個網絡包的最大長度,以太網中一般為?1500?字節;
  • MSS:除去 IP 和 TCP 頭部之后,一個網絡包所能容納的 TCP 數據的最大長度;

原因

  • 性能開銷大:IP 分片需在路由器拆分數據包并添加額外頭部,接收端需緩存所有分片并重組,消耗網絡和主機資源。
  • 可靠性低:分片丟失會導致整個原始數據包失效,需重傳全部數據,而非僅丟失的片段。

TCP 通過三次握手協商 MSS,直接限制數據段大小,從源頭避免分片,減少網絡負擔。,如果一個 TCP 分片丟失后,進行重發時也是以 MSS 為單位,而不用重傳所有的分片,大大增加了重傳的效率。

第一次握手丟失了,會發生什么?

當客戶端想和服務端建立 TCP 連接的時候,首先第一個發的就是 SYN 報文,然后進入到?SYN_SENT?狀態。因為丟失了,所以服務器收不到SYN報文,客戶端就無法得到回應,就會一直發送。重傳的 SYN 報文的序列號都是一樣的

間隔一段時間,發一次。不同版本的操作系統可能超時時間不同,有的 1 秒的,也有 3 秒的,這個超時時間是寫死在內核里的,一般是5次

第二次握手丟失了,會發生什么?

客戶端發SYN 報文給服務器,服務器回復ACK和SYN報文,但是它丟失了,這就導致客戶端收不到回應,就一直發SYN,服務端也不知道未發出去,得不到客戶端的ACK,服務端也重發ACK和SYN,所以他們就全部重新發送

第三次握手丟失了,會發生什么?

第三握手丟失,服務器得不到客戶端的ACK,因為單獨的ACK不會重傳,

  • 重傳 ACK 無意義(數據重傳會自然觸發新的 ACK);

當服務端超時重傳 2 次 SYN-ACK 報文后,由于 tcp_synack_retries 為 2,已達到最大重傳次數,于是再等待一段時間(時間為上一次超時時間的 2 倍),如果還是沒能收到客戶端的第三次握手,那么服務端就會斷開連接。

什么是 SYN 攻擊?如何避免 SYN 攻擊?

我們都知道 TCP 連接建立是需要三次握手,假設攻擊者短時間偽造不同 IP 地址的?SYN?報文,服務端每接收到一個?SYN?報文,就進入SYN_RCVD?狀態,但服務端發送出去的?ACK + SYN?報文,無法得到未知IP 主機的?ACK?應答,久而久之就會占滿服務端的半連接隊列,使得服務端不能為正常用戶服務。

在 TCP 三次握手的時候,Linux 內核會維護兩個隊列,分別是:

  • 半連接隊列,也稱 SYN 隊列;
  • 全連接隊列,也稱 accept 隊列;

正常流程:

1、當服務端接收到客戶端的 SYN 報文時,會創建一個半連接的對象,然后將其加入到內核的「 SYN 隊列」;

2、接著發送 SYN + ACK 給客戶端,等待客戶端回應 ACK 報文;

3、服務端接收到 ACK 報文后,從「 SYN 隊列」取出一個半連接對象,然后創建一個新的連接對象放入到「 Accept 隊列」;

4、應用通過調用?accpet()?socket 接口,從「 Accept 隊列」取出連接對象。

SYN 攻擊方式最直接的表現就會把 TCP 半連接隊列打滿,這樣當 TCP 半連接隊列滿了,后續再在收到SYN 報文就會丟棄,導致客戶端無法和服務端建立連接。

避免 SYN 攻擊方式

方式一:調大 netdev_max_backlog

當網卡接收數據包的速度大于內核處理的速度時,會有一個隊列保存這些數據包。控制該隊列的最大值如下參數,默認值是 1000,我們要適當調大該參數的值,比如設置為 10000

方式二:增大 TCP 半連接隊列

方式三:加cookie身份驗證

方式四:減少 SYN+ACK 重傳次數

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

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

相關文章

Excel的學習

一、熟悉界面 1.功能區 點擊“視圖”,點擊凍結窗格,選擇目標行 2.表格區 3.自定義功能區 在上面的空白編輯欄處,右鍵選擇自定義功能區 4.數據輸入規范 (1)格式不統一(日期格式不規范,姓名亂加空格,亂合并單元格) 姓名對齊:右鍵選擇編輯單元格格式,選擇對齊,…

論文閱讀:HybridTrack: A Hybrid Approach for Robust Multi-Object Tracking

論文地址:2501.01275v2 代碼地址:GitHub - leandro-svg/HybridTrack: [RA-L25/ICRA26] HybridTrack: A Hybrid Approach for Robust Multi-Object Tracking 前言 多目標跟蹤旨在在幀間檢測和關聯所有所需的目標。大多數方法通過明確或隱式地利用強大的線索(即空間和外觀信…

EtherCAT開源主站 SOEM 2.0 最新源碼在嵌入式 Linux 下的移植與編譯

EtherCAT 作為工業自動化領域的主流現場總線協議,因其高實時性和高帶寬被廣泛應用。而 SOEM(Simple Open EtherCAT Master)則是開源社區中最受歡迎的 EtherCAT 主站協議棧之一。本文將以 SOEM 2.0 最新源碼為例,詳細介紹其在嵌入式…

面試150 填充每個節點的下一個右側節點指針Ⅱ

思路 采用層序遍歷的方式來連接二叉樹中同一層的節點。首先將根節點加入隊列,然后按層處理節點:每一層依次從隊列中取出節點,并將其 next 指針指向該層中的下一個節點(即隊列中的下一個節點);若是該層最后一…

Windows 本地 使用mkcert 配置HTTPS 自簽名證書

🧩 場景假設 項目本地運行或通過本地 web 服務器(如 Nginx、http-server、vite)訪問 假設域名為 myadmin.local(可以任意命名) 步驟 1:安裝 mkcert 下載 mkcert: 訪問 https://github.com/Fil…

vue3 ref vs reactive值的修改

ref vs reactive reactive 定義的響應式對象不能直接整體修改(即obj1obj2),如果想要修改,可以使用 Object.assign(obj1,obj2) 上述賦值是淺拷貝,對象地址不變,屬性值被修改了淺拷貝:創建一個新對象,這個對象有著原始對象屬性值的一份精確拷貝。如果屬性值是基本類型…

【Datawhale AI 夏令營】 用AI做帶貨視頻評論分析(一)

引言 以訊飛「基于帶貨視頻評論的用戶洞察挑戰賽」的賽事項目為背景,將電商直播帶貨視頻的碎片化用戶評論轉化為可量化的商業洞察信息。其實本質上在于利用自然語言處理、機器學習或者大模型技術,從海量的文本數據中提取有價值的商業洞察。 主要涉及以下…

Vue中的render()函數

在 Vue 中&#xff0c;render() 是一個用于手動編寫組件渲染邏輯的方法&#xff0c;它直接返回虛擬節點&#xff08;VNode&#xff09;&#xff0c;替代模板語法&#xff08;<template>&#xff09;來描述組件的 UI 結構。以下是關于 render() 方法的詳細解析&#xff1a…

板凳-------Mysql cookbook學習 (十一--------9)

13.2 分組描述統計 mysql> select age, count(score) as n,-> sum(score) as sum,-> min(score) as minimum,-> max(score) as maximum,-> avg(score) as mean,-> stddev_samp(score) as std. dev.,-> var_samp(score) as variance-> from testscore-&…

編寫產品需求文檔:黃歷日歷小程序

整理產品需求文檔&#xff1a;黃歷日歷小程序版本&#xff1a;1.0 更新時間&#xff1a;2025-7-9一、文檔概述1.1 產品背景開發一款融合傳統黃歷文化的日歷工具&#xff0c;提供每日吉兇查詢、神煞展示和個人運勢分析功能。1.2 目標用戶關注傳統歷法的中老年群體婚嫁/搬家等需要…

Spring Boot + MyBatis 實現用戶登錄功能詳解(基礎)

一、項目概述做了幾個項目發現有人問到怎么使用springbootHTMLjsCSS開發一個項目呢所以本文將介紹如何使用Spring Boot和MyBatis實現一個完整的用戶登錄功能。系統包含前端登錄頁面、后端控制器、服務層、數據訪問層以及數據庫交互。二、技術棧Spring Boot 2.xMyBatis 持久層框…

adb 簡介與常用命令

1. adb 簡介adb 的全稱為 Android Debug Bridge&#xff0c;就是起到調試橋的作用。借助 adb 工具&#xff0c;我們可以管理設備或手機模擬器的狀態。還可以進行很多手機操作&#xff0c;如安裝軟件、系統升級、運行 shell 命令等等。其實簡而言說&#xff0c;adb 就是連接 And…

阿里云-跨賬號同步OSS Bucket

說明 阿里云A賬號的OSS BUCKET同步到B賬號的指定OSS BUCKET。 賬號Bucket NamesRAM角色A{源buctket}OSS-SYNCERB{目標buctket} 步驟 在阿里云A,B賬號分別建上表buckets, 最好是相同地域的在A號-RAM控制臺建立角色OSS-SYNCER&#xff0c;并賦權AliyunOSSFullAccess&#xff…

uniapp小程序無感刷新token

request.js // request.js import {getApptoken,getStoredApptoken } from ./tokenRequest // 從合并模塊導入// 全局配置 const MAX_RETRIES 1 // 最大重試次數 const baseURL https://your-api.com// 請求隊列和刷新狀態 let requestsQueue [] let isRefreshing false// …

MySQL優化高手筆記

語雀完整版&#xff1a;https://www.yuque.com/g/mingrun/embiys/dv3btw/collaborator/join?tokenzMBwPzSMfSGINLuv&sourcedoc_collaborator# 《MySQL優化高手筆記》MySQL優化高手一、MySQL架構01 天天寫CRUD,你知道你的系統是如何跟MySQL打交道的嗎通過驅動連接數據庫&am…

Git 詳解:從概念,常用命令,版本回退到工作流

本文將從 Git 的核心概念講起&#xff0c;詳細介紹常用命令、各階段版本回退、分支控制以及企業內常見的 Git 工作流。 Git 與 GitHub 簡介 Git 簡介 Git 是一個開源的分布式版本控制系統&#xff0c;由 Linus Torvalds 于 2005 年開發。它與集中式版本控制系統&#xff08;…

CMSIS(Cortex Microcontroller Software Interface Standard)ARM公司為 Cortex-M 系列處理器

CMSIS&#xff08;Cortex Microcontroller Software Interface Standard&#xff09;是ARM公司為 Cortex-M 系列處理器&#xff08;如 M0/M3/M4/M7/M23/M33 等&#xff09;定義的一套硬件抽象層標準&#xff0c;旨在簡化嵌入式開發&#xff0c;提高代碼的可移植性和復用性。 核…

[特殊字符] 掃描式處理:Python 自動提取 PDF 中關鍵詞相關表格并導出為 Excel

本文演示如何利用 pdfplumber 批量處理指定文件夾下 PDF 文檔&#xff1a;定位關鍵詞&#xff08;如“主要會計數據”&#xff09;出現的頁碼及下一頁&#xff0c;提取其中的表格并保存為獨立 Excel 文件。適用于財務報告、審計表格、統計報表等場景。 1?? 第一步&#xff1a…

python3的返回值能返回多個嗎?

在Python中&#xff0c;函數可以通過返回一個元組&#xff08;tuple&#xff09; 來間接實現返回多個值的效果。以下是具體說明&#xff1a; 實現方式&#xff1a;直接返回逗號分隔的值 Python會自動將這些值打包成一個元組&#xff1a; def multiple_return():a 1b "he…

UE5 Secondary Materials

首先放入材質A材質B放入Secondary Materials兩個效果就能融合到一起了動態設置secondary material