成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

為什么 TFO 可以將 TCP 降低到 0 次握手?

網絡
因為 TCP 協議棧不同版本間存在差異,所以本文的前提是 TCP 三次握手時不傳輸數據,也就是傳統的 TCP 三次握手。

一、概述

在之前的文章 為什么 TCP 建立連接需要三次握手 中,關于下面 3 個問題給出了簡單的回答:

  • 第一次握手時可以攜帶應用數據嗎?
  • 第二次握手時可以攜帶應用數據嗎?
  • 第三次握手時可以攜帶應用數據嗎?

簡單來說,傳統的 TCP 建立連接時需要三次握手,而且這三次握手只發送簡單的 SYN 和 ACK 報文。

從網絡帶寬的資源利用的角度來看,傳輸層的 TCP 頭部 + 網絡層的 IP 頭部,最少有 40 個字節,為了發送幾個字節的報文數據包,而額外組裝了 40 個字節的頭部,這有點類似前面講 TCP 滑動窗口時,所謂的 “糊涂窗口綜合癥”。

從應用優化的角度來看,因為要等到 TCP 經過三次握手建立連接之后才能發送應用層數據,所以會造成應用程序首次發送數據時存在一定的延遲,尤其是短連接、移動設備等場景中,這種副作用會加劇。

那么這種問題如何解決呢?使用 TFO 解決方案。

?? PS: 因為 TCP 協議棧不同版本間存在差異,所以本文的前提是 TCP 三次握手時不傳輸數據,也就是傳統的 TCP 三次握手,事實上,很多云計算服務商提供的 Linux 發行版本都對網絡協議棧進行了優化,會在 TCP 第三次握手時直接發送數據,讀者自己抓包驗證時,可能會和本文結果存在一定差異。

二、TFO

TCP Fast Open (TFO) 是在傳統的三次握手基礎上進行優化,允許在握手過程中發送數據,從而減少首次發送數據的延遲,提升網絡應用性能。

1.實現原理:

TFO 的核心原理是在發送方和接收方通信中,引入 1 個 Cookie 機制,這樣使發送方在后續重連接收方時,能夠簡化 TCP 三次握手。

顧名思義,TFO Cookie 中的 Cookie 和 Web 應用層 中的 Cookie 機制一樣,第一次訪問時,需要登錄驗證,然后由服務端驗證后,后續訪問中可以直接攜帶,無需再次登錄。

(1) 首次連接

  • 當發送方第一次和接收方建立 TCP 連接時,發送 1 個 SYN 報文
  • 接收方返回 SYN-ACK 報文的同時,附帶一個隨機生成的名為 TFO Cookie 的標識符給發送方
  • 發送方收到 SYN-ACK 報文后,保存 TFO Cookie,發送 ACK 報文給接收方,完成三次握手,開始傳輸數據

(2) 后續連接

  • 當發送方再次連接同一個接收方時,可以在 SYN 報文中攜帶上次保存的 TFO Cookie,同時在 SYN 報文中附帶應用層數據 (也就是第一次握手時就直接發送數據)
  • 接收方驗證發送方的 TFO Cookie 后,將數據發送給應用層處理,并返回 SYN-ACK 報文 (同時也可以發送數據)
  • 發送方收到 SYN-ACK 報文后,發送 ACK 報文給接收方,完成三次握手

2.優點

通過 TFO,發送方在發送 SYN 報文時就可以直接攜帶數據,接收方可以在第一次握手時直接處理數據,并且在第二次握手時直接發送數據,最終:

  • 發送方第一次發送數據,減少了 1.5 個 RTT 延遲
  • 接收方第一次發送數據,減少了 1 個 RTT 延遲

發送方第一次發送數據,減少了 1.5 個 RTT 延遲

接收方第一次發送數據,減少了 1 個 RTT 延遲

3.局限性

(1) 兼容性

需要通信雙方都支持 TFO, 如果其中一方不支持,連接自動回退到傳統的 TCP 連接建立過程,此外,通信鏈路中的轉發設備 (NAT, 防火墻) 也會執行這個兼容性機制。

(2) 安全性

雖然 TFO 的 Cookie 是由接收方生成并發送給發送方的,并且每個 Cookie 都與發送方關聯,但是增加了接收方的安全攻擊面,可能引發諸如 “TCP SYN Flood” 放大攻擊 等安全風險。

如果攻擊者從被入侵主機獲取到有效的 TFO Cookie,進而偽造了大量的攜帶數據報文,那么接收方就需要大量的內存來臨時存儲應用數據,最終導致內存耗盡。

(3) 部署環境要求

對內核版本有要求,且需要修改內核參數。

(4) 應用數據過大

如果發送方第一次要發送的數據大于 TCP 的 MSS, 依然需要拆包進行多次發送,當應用數據過大時,TCP Fast Open 帶來的優勢 (RTT 減少) 幾乎可以忽略。

三、模擬環境

TFO 需要發送方和接收方同時支持,如果任意一方不支持 TFO,連接會自動回退到傳統的三次握手方式。

為了演示效果,筆者使用了 2 個 Linux 服務器作為通信發送方和接收方,對應的發行版本和內核版本參數如下。

1.TFO 對 Linux 內核版本要求: >= 3.7。

# 發送方

## 發行版本 (WSL2 環境)
$ cat /etc/os-release 

PRETTY_NAME="Debian GNU/Linux 11 (bullseye)"
NAME="Debian GNU/Linux"
VERSION_ID="11"
VERSION="11 (bullseye)"
VERSION_CODENAME=bullseye
ID=debian

## 內核版本
$ uname -r

5.10.0-21-amd64

# 接收方

## 發行版本
$ cat /etc/os-release

NAME="CentOS Linux"
VERSION="7 (Core)"
ID="centos"
ID_LIKE="rhel fedora"
VERSION_ID="7"
PRETTY_NAME="CentOS Linux 7 (Core)"

## 內核版本
$ uname -r

3.10.0-1160.53.1.el7.x86_64

2.內核參數調整

TFO 啟用需要修改默認內核參數:

  • 0:關閉 TFO
  • 1:啟用發送方模式 TFO
  • 2:啟用接收方模式 TFO
  • 3:同時啟用發送方和接收方模式 TFO
# 發送方啟用 TFO
$ echo 1 | sudo tee /proc/sys/net/ipv4/tcp_fastopen

# 接收方啟用 TFO
# 寫入 3 表示既啟用發送方 TFO 也啟用接收方 TFO
$ echo 3 | sudo tee /proc/sys/net/ipv4/tcp_fastopen

作為模擬實驗,筆者只是臨時修改了參數,可以采用如下步驟進行配置永久生效:

(1) 編輯 /etc/sysctl.conf 文件,添加配置項

net.ipv4.tcp_fastopen=3

(2) 運行 sysctl -p 命令生效,重啟之后仍然有效

四、程序代碼

如果讀者使用主機的 curl 版本較高,可以直接使用如下方式直接開啟 TFO 機制方式訪問:

$ curl --tcp-fastopen http://example.com

# 可以使用如下方式確認 curl 版本是否支持 TFO
$ curl -V | grep -i TFO

因為筆者所使用的服務器中的 curl 版本較低,所以這里編寫 Python 腳本代碼,核心代碼其實就是 2 個套接字的參數的設置而已。

1.接收方 (服務端) 代碼

將接收方作為服務端程序的方式來實現,綁定/監聽指定端口,然后接收來自發送方 (客戶端) 的 TCP 連接。

# service.py

import socket

def listen():
    # 初始化服務端監聽對象
    listener = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    # 參數 32 表示 TCP 協議棧
    # 未完成的 Fast Open 隊列長度
    listener.setsockopt(socket.SOL_TCP, socket.TCP_FASTOPEN, 32)

    # 監聽 12345 端口號
    # 為了模擬,所以不用主流端口號了 :-)
    listener.bind(('0.0.0.0', 12345))
    # 最大連接數設置為 1024
    listener.listen(1024)

    print("Server is listening on port 12345...")

    # 輪詢接收新的 TCP 連接
    while True:
        conn, addr = listener.accept()
        print(f"Accepted connection from {addr}")
        print(f"Received data: {conn.recv(1024)}")

        conn.send(b"Hello, Client")
        conn.close()

        print(f"Closed connection with {addr}")


if __name__ == "__main__":
    try:
        # 啟動監聽
        listen()
    except KeyboardInterrupt:
        # 捕獲 Ctrl + C 終止程序
        print("Server shutting down...")

2.發送方 (客戶端) 代碼

# client.py

import socket

# 初始化客戶端監聽對象
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 參數 32 表示 TCP 協議棧
# 未完成的 Fast Open 隊列長度
sock.setsockopt(socket.SOL_TCP, socket.TCP_FASTOPEN, 32)

# 向服務端發送數據時
# 設置 Fast Open 選項
sock.sendto(b"Hello, Server", socket.MSG_FASTOPEN, ("104.21.71.166", 12345))

print(f"Received data: {conn.recv(1024)}")

sock.close()

五、運行程序實驗

程序核心代碼 (總共 2 行) 準備就緒,接下來開始運行程序,驗證 TCP Fast Open 過程。

服務端公網 IP: 104.21.71.166

1. 啟動服務端程序,并確認監聽狀態

# 在 1 個終端啟動服務端程序

$ python3 server.py

# 在另外 1 個終端查看程序監聽狀態是否正常

$ netstat -ant | grep 12345 | grep LISTEN

tcp        0      0 0.0.0.0:12345            0.0.0.0:*               LISTEN

2. 客戶端開始抓包

打開 WireShark, 監聽對應的網卡設備。

3. 運行客戶端程序

# 為了驗證效果,這里可以連續運行幾次
# 每次運行間隔 3 - 5 秒即可
$ python3 client.py

# 輸出省略
...

4. 查看客戶端 TCP 連接狀態

netstat -ant | grep 12345 | grep TIME_WAIT

# 輸出如下
# 連續運行了多少次 client.py 
# 就會產生多少 TIME_WAIT 狀態的 TCP 連接
# 10.0.0.53 為客戶端的內網 IP 地址


tcp        0      0 10.0.0.53:38084         104.21.71.166:12345       TIME_WAIT  
tcp        0      0 10.0.0.53:37530         104.21.71.166:12345       TIME_WAIT  
tcp        0      0 10.0.0.53:37528         104.21.71.166:12345       TIME_WAIT  
tcp        0      0 10.0.0.53:38076         104.21.71.166:12345       TIME_WAIT  
tcp        0      0 10.0.0.53:38078         104.21.71.166:12345       TIME_WAIT  

...

一切運行正常,接下來就可以去看 WireShark 的抓包結果了。

六、WireShark 抓包結果

首先使用 tcp.options.tfo 過濾條件,快速篩選出和 TCP Fast Open 有關的 TCP 報文。

下面對 WireShark 抓包結果展開分析一下。

1.第一次建立連接

當發送方第一次和接收方建立 TCP 連接時,發送 1 個 SYN 報文,以及設置 TCP Options 字段 TCP Fast Open 。

此時并沒有發送任何數據,所以 WireShark 抓包結果中的 Len = 0。

接收方返回 SYN-ACK 報文的同時,附帶一個隨機生成的名為 TFO Cookie 的標識符給發送方。

發送方收到 SYN-ACK 報文后,保存 TFO Cookie,發送 ACK 報文給接收方,完成三次握手。

其中 TFO Cookie 的值為: d82d9074a6105a13。

三次握手完成后,開始傳輸數據。

2.后續建立連接

通過截圖可以看到,后續客戶端和服務端建立 TCP 連接時,會在第一次握手時攜帶 FTO Cookie 并且直接發送數據,所以 WireShark 抓包結果中的 Len = 13。

那么這個 13 是什么?就是客戶端發送的數據,正好是 13 個字節。

conn.sendto(b"Hello, Server", ...)

后續 TCP 連接建立 (第一次握手) 時就可以直接發送數據 (篇幅所限,這里只截圖 2 個數據抓包詳情):

每個數據包中的 TFO Cookie 的值都是 d82d9074a6105a13,也就是第一次建立 TCP 連接時,服務端發送 SYN-ACK 報文時攜帶的值。

責任編輯:趙寧寧 來源: 洋芋編程
相關推薦

2023-09-07 16:46:54

TCP數據傳遞

2022-07-25 07:07:35

TCP客戶端服務器

2019-12-12 10:36:43

TCPSYNIP

2021-04-30 13:32:17

TCP三次握手網絡協議

2019-05-14 10:09:06

TCP連接握手

2024-10-16 08:38:37

TCP編號信息

2021-05-28 09:08:20

TCP連接序列號

2019-05-05 05:39:23

TCP三次握手網絡協議

2024-07-10 12:00:42

2021-12-13 06:23:14

TCP三次握手網絡

2019-05-28 10:45:07

TCP3次握手數據傳輸

2021-09-09 08:47:57

TCP三次握手協議

2023-10-24 15:22:09

TCPUDP

2022-07-05 22:18:08

TCP網絡

2019-07-19 06:58:03

TCP三次握手網絡協議

2021-12-02 09:20:33

TCPLinux三次握手

2018-11-14 09:53:48

2024-05-07 08:15:33

TCP四次揮手三次握手

2015-10-13 09:42:52

TCP網絡協議

2019-06-12 11:26:37

TCP三次握手四次揮手
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 欧产日产国产精品视频 | 中文字幕人成乱码在线观看 | 天天插天天操 | 老熟女毛片 | 国产精品久久久久久婷婷天堂 | 国产成人精品免费视频大全最热 | 99这里只有精品视频 | 日韩欧美中文 | 久久精品 | 欧美在线综合 | 国产在线www | 91在线精品视频 | 久久久久久久夜 | 一区二区久久 | 亚洲第1页 | 亚洲九九 | 成人av电影免费在线观看 | 亚洲成av人片在线观看 | 一区二区三区国产好的精 | 亚洲视频三区 | 亚洲成人精品久久久 | 欧美日韩国产一区二区三区不卡 | 亚洲网站在线观看 | 欧美在线a | 国产精品毛片一区二区三区 | 黄色毛片在线播放 | 激情av在线 | 综合婷婷| 91久久精品一区 | 我爱操| 精品96久久久久久中文字幕无 | 日韩在线免费播放 | 久久久亚洲成人 | 亚洲一区二区在线电影 | 国产精品爱久久久久久久 | 一区二区在线看 | 日韩影音 | 狠狠爱网址 | 超碰在线免费公开 | 欧美一区二区三区大片 | 97伦理最新伦理 |