日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

tcp前4字节消息长度_网络基础篇之TCP

發布時間:2023/12/20 编程问答 44 豆豆
生活随笔 收集整理的這篇文章主要介紹了 tcp前4字节消息长度_网络基础篇之TCP 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

?網絡分層

什么是 TCP

TCP 是面向連接的、可靠的、基于字節流的傳輸層通信協議。

- 面向連接:通過三次握手建立一對一的連接( UDP 協議 可以一個主機同時向多個主機發送消息,即一對多);

- 可靠的:通過序號、校驗和、滑動窗口、超時重傳等機制,保證一個報文一定能夠到達接收端;

- 字節流:消息是沒有邊界的,所以無論我們消息有多大都可以進行傳輸。并且消息是有序的,當前一個消息沒有收到的時候,即使它先收到了后面的字節已經收到,那么也不能扔給應用層去處理,同時對重復的報文會自動丟棄。

流式服務&數據報服務

  • 流式服務:TCP的字節流服務體現在,發送端執行的寫操作數和接收端執行的讀操作次數之間沒有任何數量關系,當發送端應用程序連續執行多次寫操作的時,TCP模塊先將這些數據放入TCP發送緩沖區中。當TCP模塊真正開始發送數據的時候,發送緩沖區中這些等待發送的數據可能被封裝成一個或多個TCP報文段發出。
  • UPD的數據報服務:發送端應用程序每執行一次寫操作,UDP模塊就將其封裝成一個UDP數據報并發送之。接收端必須及時針對每一個UDP數據報執行讀操作(通過recvfrom系統調用),否則就會丟包(這經常發生在較慢的服務器上)。并且,如果沒有指定足夠的應用程序緩沖區來讀取UDP數據,則UDP數據將被截斷。


TCP頭部

序列號:在建立連接時由計算機生成的隨機數作為其初始值,通過 SYN 包傳給接收端主機,之后每次發送累加一次該數據字節數的大小。用來解決網絡包亂序問題。

確認應答號:指下一次期望收到的數據的序列號(也就是收到的序列號+1),發送端收到這個確認應答以后可以認為在這個序號以前的數據都已經被正常接收。用來解決不丟包的問題。

控制位:

ACK:該位為 1 時,「確認應答」的字段變為有效,TCP 規定除了最初建立連接時的 SYN 包之外該位必須設置為 1 。

RST:該位為 1 時,表示 TCP 連接中出現異常必須強制斷開連接。

SYC:該位為 1 時,表示希望建立連接,并在其「序列號」的字段進行序列號初始值的設定。

FIN:該位為 1 時,表示今后不會再有數據發送,希望斷開連接。當通信結束希望斷開連接時,通信雙方的主機之間就可以相互交換 FIN 位置為 1 的 TCP 段。

如何唯一確定一個 TCP 連接

TCP 四元組可以唯一的確定一個連接,四元組包括如下:源地址、源端口、目的地址、目的端口。

源地址和目的地址的字段(32位)是在 IP 頭部中,作用是通過 IP 協議發送報文給對方主機。

源端口和目的端口的字段(16位)是在 TCP 頭部中,作用是告訴 TCP 協議應該把報文發給哪個進程。

【 IP 層是不可靠的,它不保證網絡包的交付、不保證網絡包的按序交付、也不保證網絡包中的數據的完整性。如果需要保障網絡數據包的可靠性,那么就需要由上層(傳輸層)的 TCP 協議來負責。】

TCP最大連接數

有一個 IP 的服務器監聽了一個端口,它的 TCP 的最大連接數是多少?

服務器通常固定在某個本地端口上監聽,等待客戶端的連接請求。

因此,客戶端 IP 和 端口是可變的,其理論值計算公式如下:

對 IPv4,客戶端的 IP 數最多為 2 的 32 次方,客戶端的端口數最多為 2 的 16 次方,也就是服務端單機最大 TCP 連接數,約為 2 的 48 次方。

當然,服務端最大并發 TCP 連接數遠不能達到理論上限。

  • 首先主要是文件描述符限制,Socket 都是文件,所以首先要通過 ulimit 配置文件描述符的數目;
  • 另一個是內存限制,每個 TCP 連接都要占用一定內存,操作系統是有限的。

UDP 和 TCP 區別及應用場景

UDP 不提供復雜的控制機制,利用 IP 提供面向無連接的通信服務。

UDP 頭部格式如下:

目標和源端口:主要是告訴 UDP 協議應該把報文發給哪個進程。

包長度:該字段保存了 UDP 首部的長度跟數據的長度之和。

校驗和:校驗和是為了提供可靠的 UDP 首部和數據而設計。

TCP 和 UDP 區別:

  • 連接方式

TCP需要三次握手建立連接。

UDP不需要連接直接傳輸數據。

  • 首部開銷

TCP 首部長度較長,會有一定的開銷,首部在沒有使用選項字段時是 20 個字節,如果使用了選項字段則會變長的。

UDP 首部只有 8 個字節,并且是固定不變的,開銷較小。

  • 服務對象

TCP是一對一;UDP支持一對一、一對多、多對多通信。

  • 可靠性

TCP 是可靠交付數據的,數據可以無差錯、不丟失、不重復、按需到達。

UDP 是盡最大努力交付,不保證可靠交付數據。

  • 擁塞控制、流量控制

TCP 有擁塞控制和流量控制機制,保證數據傳輸的安全性。

UDP 則沒有,即使網絡非常擁堵了,也不會影響 UDP 的發送速率。

TCP 和 UDP 應用場景:

由于 TCP 是面向連接,能保證數據的可靠性交付,因此經常用于:

- FTP 文件傳輸

- HTTP / HTTPS

由于 UDP 面向無連接,它可以隨時發送數據,再加上UDP本身的處理既簡單又高效,因此經常用于:

- 包總量較少的通信,如 DNS 、SNMP 等

- 視頻、音頻等多媒體通信

- 廣播通信

為什么 UDP 頭部沒有「首部長度」字段,而 TCP 頭部有「首部長度」字段呢?

原因是 TCP 有可變長的「選項」字段,而 UDP 頭部長度則是不會變化的,無需多一個字段去記錄 UDP 的首部長度。

為什么 UDP 頭部有「包長度」字段,而 TCP 頭部則沒有「包長度」字段呢?

TCP 計算負載數據長度:

其中 IP 總長度 和 IP 首部長度,在 IP 首部格式是已知的。TCP 首部長度,則是在 TCP 首部格式已知的,所以就可以求得 TCP 數據的長度。

大家這時就奇怪了問:“ UDP 也是基于 IP 層的呀,那 UDP 的數據長度也可以通過這個公式計算呀?為何還要有包長度呢?”

這么一問,確實感覺 UDP 「包長度」是冗余的。

因為為了網絡設備硬件設計和處理方便,首部長度需要是 4字節的整數倍。

如果去掉 UDP 「包長度」字段,那 UDP 首部長度就不是 4 字節的整數倍了,所以小林覺得這可能是為了補全 UDP 首部長度是 4 字節的整數倍,才補充了「包長度」字段。

TCP 連接建立

TCP 三次握手過程和狀態變遷

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

一開始,客戶端和服務端都處于 CLOSED 狀態。先是服務端主動監聽某個端口,處于 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 三次握手是如何避免的呢?

客戶端連續發送多次 SYN 建立連接的報文,在網絡擁堵等情況下:

一個「舊 SYN 報文」比「最新的 SYN 」 報文早到達了服務端;

那么此時服務端就會回一個 SYN + ACK 報文給客戶端;

客戶端收到后可以根據自身的上下文,判斷這是一個歷史連接(序列號過期或超時),那么客戶端就會發送 RST 報文給服務端,表示中止這一次連接。

如果是兩次握手連接,就不能判斷當前連接是否是歷史連接,三次握手則可以在客戶端(發送方)準備發送第三次報文時,客戶端因有足夠的上下文來判斷當前連接是否是歷史連接:

如果是歷史連接(序列號過期或超時),則第三次握手發送的報文是 RST 報文,以此中止歷史連接;

如果不是歷史連接,則第三次發送的報文是 ACK 報文,通信雙方就會成功建立連接;

所以, TCP 使用三次握手建立連接的最主要原因是防止歷史連接初始化了連接。

  • 同步雙方初始序列號

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

接收方可以去除重復的數據;

接收方可以根據數據包的序列號按序接收;

可以標識發送出去的數據包中, 哪些是已經被對方收到的;

可見,序列號在 TCP 連接中占據著非常重要的作用,所以當客戶端發送攜帶「初始序列號」的 SYN 報文的時候,需要服務端回一個 ACK 應答報文,表示客戶端的 SYN 報文已被服務端成功接收,那當服務端發送「初始序列號」給客戶端的時候,依然也要得到客戶端的應答回應,這樣一來一回,才能確保雙方的初始序列號能被可靠的同步。

四次握手其實也能夠可靠的同步雙方的初始化序號,但由于第二步和第三步可以優化成一步,所以就成了「三次握手」。

  • 避免資源浪費

如果只有「兩次握手」,當客戶端的 SYN 請求連接在網絡中阻塞,客戶端沒有接收到 ACK 報文,就會重新發送 SYN ,由于沒有第三次握手,服務器不清楚客戶端是否收到了自己發送的建立連接的 ACK 確認信號,所以每收到一個 SYN 就只能先主動建立一個連接,這會造成什么情況呢?

如果客戶端的 SYN 阻塞了,重復發送多次 SYN 報文,那么服務器在收到請求后就會建立多個冗余的無效鏈接,造成不必要的資源浪費。

即兩次握手會造成消息滯留情況下,服務器重復接受無用的連接請求 SYN 報文,而造成重復分配資源。

為什么客戶端和服務端的初始序列號 ISN 是不相同的?

因為網絡中的報文會延遲、會復制重發、也有可能丟失,這樣會造成的不同連接之間產生互相影響,所以為了避免互相影響,客戶端和服務端的初始序列號是隨機且不同的。

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

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

RFC1948 中提出了一個較好的初始化序列號 ISN 隨機生成算法。

ISN = M + F (localhost, localport, remotehost, remoteport)

M 是一個計時器,這個計時器每隔 4 毫秒加 1。

F 是一個 Hash 算法,根據源 IP、目的 IP、源端口、目的端口生成一個隨機數值。要保證 Hash 算法不能被外部輕易推算得出,用 MD5 算法是一個比較好的選擇。

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

我們先來認識下 MTU 和 MSS

- MTU:一個網絡包的最大長度,以太網中一般為 1500 字節;

- MSS:除去 IP 和 TCP 頭部之后,一個網絡包所能容納的 TCP 數據的最大長度;

如果TCP 的整個報文(頭部 + 數據)交給 IP 層進行分片,會有什么異常呢?

當 IP 層有一個超過 MTU 大小的數據(TCP 頭部 + TCP 數據)要發送,那么 IP 層就要進行分片,把數據分片成若干片,保證每一個分片都小于 MTU。把一份 IP 數據報進行分片以后,由目標主機的 IP 層來進行重新組裝后,在交給上一層 TCP 傳輸層。

這看起來井然有序,但這存在隱患的,那么當如果一個 IP 分片丟失,整個 IP 報文的所有分片都得重傳。

因為 IP 層本身沒有超時重傳機制,它由傳輸層的 TCP 來負責超時和重傳。

當接收方發現 TCP 報文(頭部 + 數據)的某一片丟失后,則不會響應 ACK 給對方,那么發送方的 TCP 在超時后,就會重發「整個 TCP 報文(頭部 + 數據)」。

因此,可以得知由 IP 層進行分片傳輸,是非常沒有效率的。

所以,為了達到最佳的傳輸效能 TCP 協議在建立連接的時候通常要協商雙方的 MSS 值,當 TCP 層發現數據超過 MSS 時,則就先會進行分片,當然由它形成的 IP 包的長度也就不會大于 MTU ,自然也就不用 IP 分片了。

經過 TCP 層分片后,如果一個 TCP 分片丟失后,進行重發時也是以 MSS 為單位,而不用重傳所有的分片,大大增加了重傳的效率。

SYN 攻擊

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

  • 避免 SYN 攻擊方式一:通過修改 Linux 內核參數,控制隊列大小和當隊列滿時應做什么處理。

當網卡接收數據包的速度大于內核處理的速度時,會有一個隊列保存這些數據包。控制該隊列的最大值如下參數:net.core.netdev_max_backlog

SYN_RCVD 狀態連接的最大個數:net.ipv4.tcp_max_syn_backlog

超出處理能時,對新的 SYN 直接回 RST,丟棄連接:net.ipv4.tcp_abort_on_overflow

  • 避免 SYN 攻擊方式二:tcp_syncookies 的方式

我們先來看下Linux 內核的 SYN (未完成連接建立)隊列與 Accpet (已完成連接建立)隊列是如何工作的?

正常流程:

- 當服務端接收到客戶端的 SYN 報文時,會將其加入到內核的「 SYN 隊列」;

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

- 服務端接收到 ACK 報文后,從「 SYN 隊列」移除放入到「 Accept 隊列」;

- 應用通過調用 accpet() socket 接口,從「 Accept 隊列」取出的連接。

應用程序過慢:

如果應用程序過慢時,就會導致「 Accept 隊列」被占滿。

受到 SYN 攻擊:

如果不斷受到 SYN 攻擊,就會導致「 SYN 隊列」被占滿。

tcp_syncookies 的方式可以應對 SYN 攻擊的方法:net.ipv4.tcp_syncookies = 1

- 當 「 SYN 隊列」滿之后,后續服務器收到 SYN 包,不進入「 SYN 隊列」;

- 計算出一個 cookie 值,再以 SYN + ACK 中的「序列號」返回客戶端,

- 服務端接收到客戶端的應答報文時,服務器會檢查這個 ACK 包的合法性。如果合法,直接放入到「 Accept 隊列」。

- 最后應用通過調用 accpet() socket 接口,從「 Accept 隊列」取出的連接。

TCP 連接斷開

TCP 四次揮手過程和狀態變遷

天下沒有不散的宴席,對于 TCP 連接也是這樣, TCP 斷開連接是通過四次揮手方式。

雙方都可以主動斷開連接,斷開連接后主機中的「資源」將被釋放。

- 客戶端打算關閉連接,此時會發送一個 TCP 首部 FIN 標志位被置為 1 的報文,也即 FIN 報文,之后客戶端進入 FIN_WAIT_1 狀態。

- 服務端收到該報文后,就向客戶端發送 ACK 應答報文,接著服務端進入 CLOSED_WAIT 狀態。

- 客戶端收到服務端的 ACK 應答報文后,之后進入 FIN_WAIT_2 狀態。

- 等待服務端處理完數據后,也向客戶端發送 FIN 報文,之后服務端進入 LAST_ACK 狀態。

- 客戶端收到服務端的 FIN 報文后,回一個 ACK 應答報文,之后進入 TIME_WAIT 狀態

- 服務器收到了 ACK 應答報文后,就進入了 CLOSE 狀態,至此服務端已經完成連接的關閉。

- 客戶端在經過 2MSL 一段時間后,自動進入 CLOSE 狀態,至此客戶端也完成連接的關閉。

你可以看到,每個方向都需要一個 FIN 和一個 ACK,因此通常被稱為四次揮手。

這里一點需要注意是:主動關閉連接的,才有 TIME_WAIT 狀態。

為什么揮手需要四次?

- 關閉連接時,客戶端向服務端發送 FIN 時,僅僅表示客戶端不再發送數據了但是還能接收數據。

- 服務器收到客戶端的 FIN 報文時,先回一個 ACK 應答報文,而服務端可能還有數據需要處理和發送,等服務端不再發送數據時,才發送 FIN 報文給客戶端來表示同意現在關閉連接。

從上面過程可知,服務端通常需要等待完成數據的發送和處理,所以服務端的 ACK 和 FIN 一般都會分開發送,從而比三次握手導致多了一次。

為什么 TIME_WAIT 等待的時間是 2MSL?

MSL 是 Maximum Segment Lifetime,報文最大生存時間,它是任何報文在網絡上存在的最長時間,超過這個時間報文將被丟棄。因為 TCP 報文基于是 IP 協議的,而 IP 頭中有一個 TTL 字段,是 IP 數據報可以經過的最大路由數,每經過一個處理他的路由器此值就減 1,當此值為 0 則數據報將被丟棄,同時發送 ICMP 報文通知源主機。

MSL 與 TTL 的區別:MSL 的單位是時間,而 TTL 是經過路由跳數。所以 MSL 應該要大于等于 TTL 消耗為 0 的時間,以確保報文已被自然消亡。

TIME_WAIT 等待 2 倍的 MSL,比較合理的解釋是:網絡中可能存在來自發送方的數據包,當這些發送方的數據包被接收方處理后又會向對方發送響應,所以一來一回需要等待 2 倍的時間。

比如,如果被動關閉方沒有收到斷開連接的最后的 ACK 報文,就會觸發超時重發 Fin 報文,另一方接收到 FIN 后,會重發 ACK 給被動關閉方, 一來一去正好 2 個 MSL。

2MSL 的時間是從客戶端接收到 FIN 后發送 ACK 開始計時的。如果在 TIME-WAIT 時間內,因為客戶端的 ACK 沒有傳輸到服務端,客戶端又接收到了服務端重發的 FIN 報文,那么 2MSL 時間將重新計時。

在 Linux 系統里 2MSL 默認是 60 秒,那么一個 MSL 也就是 30 秒。Linux 系統停留在 TIME_WAIT 的時間為固定的 60 秒。

其定義在 Linux 內核代碼里的名稱為 TCP_TIMEWAIT_LEN:

#define TCP_TIMEWAIT_LEN (60*HZ) /* how long to wait to destroy TIME-WAIT state, about 60 seconds */

如果要修改 TIME_WAIT 的時間長度,只能修改 Linux 內核代碼里 TCP_TIMEWAIT_LEN 的值,并重新編譯 Linux 內核。

為什么需要 TIME_WAIT 狀態?

主動發起關閉連接的一方,才會有 TIME-WAIT 狀態。

需要 TIME-WAIT 狀態,主要是兩個原因:

原因一:防止舊連接的數據包

假設 TIME-WAIT 沒有等待時間或時間過短,被延遲的數據包抵達后會發生什么呢?

- 如上圖黃色框框服務端在關閉連接之前發送的 SEQ = 301 報文,被網絡延遲了。

- 這時有相同端口的 TCP 連接被復用后,被延遲的 SEQ = 301 抵達了客戶端,那么客戶端是有可能正常接收這個過期的報文,這就會產生數據錯亂等嚴重的問題。

所以,TCP 就設計出了這么一個機制,經過 2MSL 這個時間,足以讓兩個方向上的數據包都被丟棄,使得原來連接的數據包在網絡中都自然消失,再出現的數據包一定都是新建立連接所產生的。

原因二:保證連接正確關閉

也就是說,TIME-WAIT 作用是等待足夠的時間以確保最后的 ACK 能讓被動關閉方接收,從而幫助其正常關閉。

假設 TIME-WAIT 沒有等待時間或時間過短,斷開連接會造成什么問題呢?

- 如上圖紅色框框客戶端四次揮手的最后一個 ACK 報文如果在網絡中被丟失了,此時如果客戶端 TIME-WAIT 過短或沒有,則就直接進入了 CLOSE 狀態了,那么服務端則會一直處在 LASE-ACK 狀態。

- 當客戶端發起建立連接的 SYN 請求報文后,服務端會發送 RST 報文給客戶端,連接建立的過程就會被終止。

如果 TIME-WAIT 等待足夠長的情況就會遇到兩種情況:

- 服務端正常收到四次揮手的最后一個 ACK 報文,則服務端正常關閉連接。

- 服務端沒有收到四次揮手的最后一個 ACK 報文時,則會重發 FIN 關閉連接報文并等待新的 ACK 報文。

所以客戶端在 TIME-WAIT 狀態等待 2MSL 時間后,就可以保證雙方的連接都可以正常的關閉。

TIME_WAIT 過多有什么危害?

如果服務器有處于 TIME-WAIT 狀態的 TCP,則說明是由服務器方主動發起的斷開請求。

過多的 TIME-WAIT 狀態主要的危害有兩種:

- 第一是內存資源占用;

- 第二是對端口資源的占用,一個 TCP 連接至少消耗一個本地端口;

第二個危害是會造成嚴重的后果的,要知道,端口資源也是有限的,一般可以開啟的端口為 32768~61000,也可以通過如下參數設置指定

net.ipv4.ip_local_port_range

如果服務端 TIME_WAIT 狀態過多,占滿了所有端口資源,則會導致無法創建新連接。

如何優化 TIME_WAIT?

這里給出優化 TIME-WAIT 的幾個方式,都是有利有弊:

方式一:net.ipv4.tcp_tw_reuse 和 tcp_timestamps

如下的 Linux 內核參數開啟后,則可以復用處于 TIME_WAIT 的 socket 為新的連接所用。

net.ipv4.tcp_tw_reuse = 1

使用這個選項,還有一個前提,需要打開對 TCP 時間戳的支持,即

net.ipv4.tcp_timestamps=1(默認即為 1)

這個時間戳的字段是在 TCP 頭部的「選項」里,用于記錄 TCP 發送方的當前時間戳和從對端接收到的最新時間戳。

由于引入了時間戳,我們在前面提到的 2MSL 問題就不復存在了,因為重復的數據包會因為時間戳過期被自然丟棄。

溫馨提醒:net.ipv4.tcp_tw_reuse要慎用,因為使用了它就必然要打開時間戳的支持 net.ipv4.tcp_timestamps,當客戶端與服務端主機時間不同步時,客戶端的發送的消息會被直接拒絕掉。小林在工作中就遇到過。。。排查了非常的久

方式二:net.ipv4.tcp_max_tw_buckets

這個值默認為 18000,當系統中處于 TIME_WAIT 的連接一旦超過這個值時,系統就會將所有的 TIME_WAIT 連接狀態重置。

這個方法過于暴力,而且治標不治本,帶來的問題遠比解決的問題多,不推薦使用。

方式三:程序中使用 SO_LINGER

我們可以通過設置 socket 選項,來設置調用 close 關閉連接行為。

struct linger so_linger;

so_linger.l_onoff = 1;

so_linger.l_linger = 0;

setsockopt(s, SOL_SOCKET, SO_LINGER, &so_linger,sizeof(so_linger));

如果l_onoff為非 0, 且l_linger值為 0,那么調用close后,會立該發送一個RST標志給對端,該 TCP 連接將跳過四次揮手,也就跳過了TIME_WAIT狀態,直接關閉。

但這為跨越TIME_WAIT狀態提供了一個可能,不過是一個非常危險的行為,不值得提倡。

如果已經建立了連接,但是客戶端突然出現故障了怎么辦?

TCP 有一個機制是保活機制。這個機制的原理是這樣的:

定義一個時間段,在這個時間段內,如果沒有任何連接相關的活動,TCP 保活機制會開始作用,每隔一個時間間隔,發送一個探測報文,該探測報文包含的數據非常少,如果連續幾個探測報文都沒有得到響應,則認為當前的 TCP 連接已經死亡,系統內核將錯誤信息通知給上層應用程序。

在 Linux 內核可以有對應的參數可以設置保活時間、保活探測的次數、保活探測的時間間隔,以下都為默認值:

net.ipv4.tcp_keepalive_time=7200

net.ipv4.tcp_keepalive_intvl=75

net.ipv4.tcp_keepalive_probes=9

tcp_keepalive_time=7200:表示保活時間是 7200 秒(2小時),也就 2 小時內如果沒有任何連接相關的活動,則會啟動保活機制

tcp_keepalive_intvl=75:表示每次檢測間隔 75 秒;

tcp_keepalive_probes=9:表示檢測 9 次無響應,認為對方是不可達的,從而中斷本次的連接。

也就是說在 Linux 系統中,最少需要經過 2 小時 11 分 15 秒才可以發現一個「死亡」連接。

這個時間是有點長的,我們也可以根據實際的需求,對以上的保活相關的參數進行設置。

如果開啟了 TCP 保活,需要考慮以下幾種情況:

第一種,對端程序是正常工作的。當 TCP 保活的探測報文發送給對端, 對端會正常響應,這樣 TCP 保活時間會被重置,等待下一個 TCP 保活時間的到來。

第二種,對端程序崩潰并重啟。當 TCP 保活的探測報文發送給對端后,對端是可以響應的,但由于沒有該連接的有效信息,會產生一個 RST 報文,這樣很快就會發現 TCP 連接已經被重置。

第三種,是對端程序崩潰,或對端由于其他原因導致報文不可達。當 TCP 保活的探測報文發送給對端后,石沉大海,沒有響應,連續幾次,達到保活探測次數后,TCP 會報告該 TCP 連接已經死亡。

Socket 編程

針對 TCP 應該如何 Socket 編程?

服務端和客戶端初始化 socket,得到文件描述符;

服務端調用 bind,將綁定在 IP 地址和端口;

服務端調用 listen,進行監聽;

服務端調用 accept,等待客戶端連接;

客戶端調用 connect,向服務器端的地址和端口發起連接請求;

服務端 accept 返回用于傳輸的 socket 的文件描述符;

客戶端調用 write 寫入數據;服務端調用 read 讀取數據;

客戶端斷開連接時,會調用 close,那么服務端 read 讀取數據的時候,就會讀取到了 EOF,待處理完數據后,服務端調用 close,表示連接關閉。

這里需要注意的是,服務端調用 accept 時,連接成功了會返回一個已完成連接的 socket,后續用來傳輸數據。

所以,監聽的 socket 和真正用來傳送數據的 socket,是「兩個」 socket,一個叫作監聽 socket,一個叫作已完成連接 socket。

成功連接建立之后,雙方開始通過 read 和 write 函數來讀寫數據,就像往一個文件流里面寫東西一樣。

listen 時候參數 backlog 的意義?

Linux內核中會維護兩個隊列:

未完成連接隊列(SYN 隊列):接收到一個 SYN 建立連接請求,處于 SYN_RCVD 狀態;

已完成連接隊列(Accpet 隊列):已完成 TCP 三次握手過程,處于 ESTABLISHED 狀態;

int listen (int socketfd, int backlog)

- 參數一 socketfd 為 socketfd 文件描述符

- 參數二 backlog,這參數在歷史有一定的變化

在早期 Linux 內核 backlog 是 SYN 隊列大小,也就是未完成的隊列大小。

在 Linux 內核 2.2 之后,backlog 變成 accept 隊列,也就是已完成連接建立的隊列長度,所以現在通常認為 backlog 是 accept 隊列。

accept 發送在三次握手的哪一步?

我們先看看客戶端連接服務端時,發送了什么?

- 客戶端的協議棧向服務器端發送了 SYN 包,并告訴服務器端當前發送序列號 client_isn,客戶端進入 SYNC_SENT 狀態;

- 服務器端的協議棧收到這個包之后,和客戶端進行 ACK 應答,應答的值為 client_isn+1,表示對 SYN 包 client_isn 的確認,同時服務器也發送一個 SYN 包,告訴客戶端當前我的發送序列號為 server_isn,服務器端進入 SYNC_RCVD 狀態;

- 客戶端協議棧收到 ACK 之后,使得應用程序從 connect 調用返回,表示客戶端到服務器端的單向連接建立成功,客戶端的狀態為 ESTABLISHED,同時客戶端協議棧也會對服務器端的 SYN 包進行應答,應答數據為 server_isn+1;

- 應答包到達服務器端后,服務器端協議棧使得 accept 阻塞調用返回,這個時候服務器端到客戶端的單向連接也建立成功,服務器端也進入 ESTABLISHED 狀態。

從上面的描述過程,我們可以得知客戶端 connect 成功返回是在第二次握手,服務端 accept 成功返回是在三次握手成功之后。

客戶端調用 close 了,連接斷開的流程是什么?

- 客戶端調用 close,表明客戶端沒有數據需要發送了,則此時會向服務端發送 FIN 報文,進入 - FIN_WAIT_1 狀態;

- 服務端接收到了 FIN 報文,TCP 協議棧會為 FIN 包插入一個文件結束符 EOF 到接收緩沖區中,應用程序可以通過 read 調用來感知這個 FIN 包。這個 EOF 會被放在已排隊等候的其他已接收的數據之后,這就意味著服務端需要處理這種異常情況,因為 EOF 表示在該連接上再無額外數據到達。此時,服務端進入 CLOSE_WAIT 狀態;

- 接著,當處理完數據后,自然就會讀到 EOF,于是也調用 close 關閉它的套接字,這會使得會發出一個 FIN 包,之后處于 LAST_ACK 狀態;

- 客戶端接收到服務端的 FIN 包,并發送 ACK 確認包給服務端,此時客戶端將進入 TIME_WAIT 狀態;

- 服務端收到 ACK 確認包后,就進入了最后的 CLOSE 狀態;

- 客戶端進過 2MSL 時間之后,也進入 CLOSED 狀態;

重傳機制

在錯綜復雜的網絡環境中,萬一數據在傳輸過程中丟失,TCP針對這種情況用重傳機制解決。常見的重傳機制:

- 超時重傳

- 快速重傳

- SACK

- D-SACK

超時重傳

發送數據是設定一個定時器,當超過指定時間沒有收到對方的確認報文,就會重發該數據。TCP會在一下兩種情況發生超時重傳:

- 數據包丟失

- 確認應答丟失

超時時間設置為多少呢?

RTT(Round-Trip Time 往返時延)

RTT 就是數據從網絡一端傳送到另一端并收到應答所需的時間,也就是包的往返時間。超時重傳時間是以 RTO (Retransmission Timeout 超時重傳時間)表示。

假設在重傳的情況下,超時時間 RTO 「較長或較短」時,會發生什么事情呢?

上圖中有兩種超時時間不同的情況:

- 當超時時間 RTO 較大時,重發就慢,丟了老半天才重發,沒有效率,性能差;

- 當超時時間 RTO 較小時,會導致可能并沒有丟就重發,于是重發的就快,會增加網絡擁塞,導致更多的超時,更多的超時導致更多的重發。

精確的測量超時時間 RTO 的值是非常重要的,這可讓我們的重傳機制更高效。

根據上述的兩種情況,我們可以得知,超時重傳時間 RTO 的值應該略大于報文往返 RTT 的值。

至此,可能大家覺得超時重傳時間 RTO 的值計算,也不是很復雜嘛。

好像就是在發送端發包時記下 t0 ,然后接收端再把這個 ack 回來時再記一個 t1,于是 RTT = t1 – t0。沒那么簡單,這只是一個采樣,不能代表普遍情況。

實際上「報文往返 RTT 的值」是經常變化的,因為我們的網絡也是時常變化的。也就因為「報文往返 RTT 的值」 是經常波動變化的,所以「超時重傳時間 RTO 的值」應該是一個動態變化的值。

我們來看看 Linux 是如何計算 RTO 的呢?

估計往返時間,通常需要采樣以下兩個:

需要 TCP 通過采樣 RTT 的時間,然后進行加權平均,算出一個平滑 RTT 的值,而且這個值還是要不斷變化的,因為網絡狀況不斷地變化。

除了采樣 RTT,還要采樣 RTT 的波動范圍,這樣就避免如果 RTT 有一個大的波動的話,很難被發現的情況。

RFC6289 建議使用以下的公式計算 RTO:

其中 SRTT 是計算平滑的RTT ,DevRTR 是計算平滑的RTT 與 最新 RTT 的差距。

在 Linux 下,α = 0.125,β = 0.25, μ = 1,? = 4。別問怎么來的,問就是大量實驗中調出來的。

如果超時重發的數據,再次超時的時候,又需要重傳的時候,TCP 的策略是超時間隔加倍。

也就是每當遇到一次超時重傳的時候,都會將下一次超時時間間隔設為先前值的兩倍。兩次超時,就說明網絡環境差,不宜頻繁反復發送。

超時觸發重傳存在的問題是,超時周期可能相對較長。那是不是可以有更快的方式呢?

于是就可以用「快速重傳」機制來解決超時重發的時間等待。

快速重傳

TCP 還有另外一種快速重傳(Fast Retransmit)機制,它不以時間為驅動,而是以數據驅動重傳。

快速重傳機制,是如何工作的呢?其實很簡單,一圖勝千言。

在上圖,發送方發出了 1,2,3,4,5 份數據:

第一份 Seq1 先送到了,于是就 Ack 回 2;

結果 Seq2 因為某些原因沒收到,Seq3 到達了,于是還是 Ack 回 2;

后面的 Seq4 和 Seq5 都到了,但還是 Ack 回 2,因為 Seq2 還是沒有收到;

發送端收到了三個 Ack = 2 的確認,知道了 Seq2 還沒有收到,就會在定時器過期之前,重傳丟失的 Seq2。

最后,接收到收到了 Seq2,此時因為 Seq3,Seq4,Seq5 都收到了,于是 Ack 回 6 。

所以,快速重傳的工作方式是當收到三個相同的 ACK 報文時,會在定時器過期之前,重傳丟失的報文段。

快速重傳機制只解決了一個問題,就是超時時間的問題,但是它依然面臨著另外一個問題。就是重傳的時候,是重傳之前的一個,還是重傳所有的問題。

比如對于上面的例子,是重傳 Seq2 呢?還是重傳 Seq2、Seq3、Seq4、Seq5 呢?因為發送端并不清楚這連續的三個 Ack 2 是誰傳回來的。

根據 TCP 不同的實現,以上兩種情況都是有可能的。可見,這是一把雙刃劍。

為了解決不知道該重傳哪些 TCP 報文,于是就有 SACK 方法。

SACK( Selective Acknowledgment 選擇性確認)

這種方式需要在 TCP 頭部「選項」字段里加一個 SACK 的東西,它可以將緩存的地圖發送給發送方,這樣發送方就可以知道哪些數據收到了,哪些數據沒收到,知道了這些信息,就可以只重傳丟失的數據。

如下圖,發送方收到了三次同樣的 ACK 確認報文,于是就會觸發快速重發機制,通過 SACK 信息發現只有 200~299 這段數據丟失,則重發時,就只選擇了這個 TCP 段進行重復。

如果要支持 SACK,必須雙方都要支持。在 Linux 下,可以通過 net.ipv4.tcp_sack 參數打開這個功能(Linux 2.4 后默認打開)。

D-SACK(Duplicate SACK)

其主要使用了 SACK 來告訴「發送方」有哪些數據被重復接收了。

下面舉例兩個栗子,來說明 D-SACK 的作用。

栗子一號:ACK 丟包

- 「接收方」發給「發送方」的兩個 ACK 確認應答都丟失了,所以發送方超時后,重傳第一個數據包(3000 ~ 3499)

- 于是「接收方」發現數據是重復收到的,于是回了一個 SACK = 3000~3500,告訴「發送方」 3000~3500 的數據早已被接收了,因為 ACK 都到了 4000 了,已經意味著 4000 之前的所有數據都已收到,所以這個 SACK 就代表著 D-SACK。

- 這樣「發送方」就知道了,數據沒有丟,是「接收方」的 ACK 確認報文丟了。

栗子二號:網絡延時

數據包(1000~1499) 被網絡延遲了,導致「發送方」沒有收到 Ack 1500 的確認報文。

而后面報文到達的三個相同的 ACK 確認報文,就觸發了快速重傳機制,但是在重傳后,被延遲的數據包(1000~1499)又到了「接收方」;

所以「接收方」回了一個 SACK=1000~1500,因為 ACK 已經到了 3000,所以這個 SACK 是 D-SACK,表示收到了重復的包。

這樣發送方就知道快速重傳觸發的原因不是發出去的包丟了,也不是因為回應的 ACK 包丟了,而是因為網絡延遲了。

可見,D-SACK 有這么幾個好處:

可以讓「發送方」知道,是發出去的包丟了,還是接收方回應的 ACK 包丟了;

可以知道是不是「發送方」的數據包被網絡延遲了;

可以知道網絡中是不是把「發送方」的數據包給復制了;

在 Linux 下可以通過 net.ipv4.tcp_dsack 參數開啟/關閉這個功能(Linux 2.4 后默認打開)。

滑動窗口

我們都知道 TCP 是每發送一個數據,都要進行一次確認應答。當上一個數據包收到了應答了, 再發送下一個。

這個模式就有點像我和你面對面聊天,你一句我一句。但這種方式的缺點是效率比較低的。

如果你說完一句話,我在處理其他事情,沒有及時回復你,那你不是要干等著我做完其他事情后,我回復你,你才能說下一句話,很顯然這不現實。

所以,這樣的傳輸方式有一個缺點:數據包的往返時間越長,通信的效率就越低。

為解決這個問題,TCP 引入了窗口這個概念。即使在往返時間較長的情況下,它也不會降低網絡通信的效率。

那么有了窗口,就可以指定窗口大小,窗口大小就是指無需等待確認應答,而可以繼續發送數據的最大值。

窗口的實現實際上是操作系統開辟的一個緩存空間,發送方主機在等到確認應答返回之前,必須在緩沖區中保留已發送的數據。如果按期收到確認應答,此時數據就可以從緩存區清除。

假設窗口大小為 3 個 TCP 段,那么發送方就可以「連續發送」 3 個 TCP 段,并且中途若有 ACK 丟失,可以通過「下一個確認應答進行確認」。如下圖

圖中的 ACK 600 確認應答報文丟失,也沒關系,因為可以通話下一個確認應答進行確認,只要發送方收到了 ACK 700 確認應答,就意味著 700 之前的所有數據「接收方」都收到了。這個模式就叫累計確認或者累計應答。

窗口大小由哪一方決定?

TCP 頭里有一個字段叫 Window,也就是窗口大小。

這個字段是接收端告訴發送端自己還有多少緩沖區可以接收數據。于是發送端就可以根據這個接收端的處理能力來發送數據,而不會導致接收端處理不過來。

所以,通常窗口的大小是由接收方的決定的。

發送方發送的數據大小不能超過接收方的窗口大小,否則接收方就無法正常接收到數據。

發送方的滑動窗口

我們先來看看發送方的窗口,下圖就是發送方緩存的數據,根據處理的情況分成四個部分,其中深藍色方框是發送窗口,紫色方框是可用窗口:


在下圖,當發送方把數據「全部」都一下發送出去后,可用窗口的大小就為 0 了,表明可用窗口耗盡,在沒收到 ACK 確認之前是無法繼續發送數據了。


在下圖,當收到之前發送的數據 32~36 字節的 ACK 確認應答后,如果發送窗口的大小沒有變化,則滑動窗口往右邊移動 5 個字節,因為有 5 個字節的數據被應答確認,接下來 52~56 字節又變成了可用窗口,那么后續也就可以發送 52~56 這 5 個字節的數據了。

程序是如何表示發送方的四個部分的呢?

TCP 滑動窗口方案使用三個指針來跟蹤在四個傳輸類別中的每一個類別中的字節。其中兩個指針是絕對指針(指特定的序列號),一個是相對指針(需要做偏移)。


SND.WND:表示發送窗口的大小(大小是由接收方指定的);

SND.UNA:是一個絕對指針,它指向的是已發送但未收到確認的第一個字節的序列號,也就是 #2 的第一個字節。

SND.NXT:也是一個絕對指針,它指向未發送但可發送范圍的第一個字節的序列號,也就是 #3 的第一個字節。

指向 #4 的第一個字節是個相對指針,它需要 SND.UNA 指針加上 SND.WND 大小的偏移量,就可以指向 #4 的第一個字節了。

那么可用窗口大小的計算就可以是:

可用窗口大 = SND.WND -(SND.NXT - SND.UNA)

接收方的滑動窗口

接下來我們看看接收方的窗口,接收窗口相對簡單一些,根據處理的情況劃分成三個部分:

#1 + #2 是已成功接收并確認的數據(等待應用進程讀取);

#3 是未收到數據但可以接收的數據;

#4 未收到數據并不可以接收的數據;


其中三個接收部分,使用兩個指針進行劃分:

RCV.WND:表示接收窗口的大小,它會通告給發送方。

RCV.NXT:是一個指針,它指向期望從發送方發送來的下一個數據字節的序列號,也就是 #3 的第一個字節。

指向 #4 的第一個字節是個相對指針,它需要 RCV.NXT 指針加上 RCV.WND 大小的偏移量,就可以指向 #4 的第一個字節了。

接收窗口和發送窗口的大小是相等的嗎?

并不是完全相等,接收窗口的大小是約等于發送窗口的大小的。

因為滑動窗口并不是一成不變的。比如,當接收方的應用進程讀取數據的速度非常快的話,這樣的話接收窗口可以很快的就空缺出來。那么新的接收窗口大小,是通過 TCP 報文中的 Windows 字段來告訴發送方。那么這個傳輸過程是存在時延的,所以接收窗口和發送窗口是約等于的關系。

流量控制

發送方不能無腦的發數據給接收方,要考慮接收方處理能力。

如果一直無腦的發數據給對方,但對方處理不過來,那么就會導致觸發重發機制,從而導致網絡流量的無端的浪費。

為了解決這種現象發生,TCP 提供一種機制可以讓「發送方」根據「接收方」的實際接收能力控制發送的數據量,這就是所謂的流量控制。

下面舉個栗子,為了簡單起見,假設以下場景:

  • 客戶端是接收方,服務端是發送方
  • 假設接收窗口和發送窗口相同,都為 200
  • 假設兩個設備在整個傳輸過程中都保持相同的窗口大小,不受外界影響


根據上圖的流量控制,說明下每個過程:

客戶端向服務端發送請求數據報文。這里要說明下,本次例子是把服務端作為發送方,所以沒有畫出服務端的接收窗口。

服務端收到請求報文后,發送確認報文和 80 字節的數據,于是可用窗口 Usable 減少為 120 字節,同時 SND.NXT 指針也向右偏移 80 字節后,指向 321,這意味著下次發送數據的時候,序列號是 321。

客戶端收到 80 字節數據后,于是接收窗口往右移動 80 字節,RCV.NXT 也就指向 321,這意味著客戶端期望的下一個報文的序列號是 321,接著發送確認報文給服務端。

服務端再次發送了 120 字節數據,于是可用窗口耗盡為 0,服務端無法在繼續發送數據。

客戶端收到 120 字節的數據后,于是接收窗口往右移動 120 字節,RCV.NXT 也就指向 441,接著發送確認報文給服務端。

服務端收到對 80 字節數據的確認報文后,SND.UNA 指針往右偏移后指向 321,于是可用窗口 Usable 增大到 80。

服務端收到對 120 字節數據的確認報文后,SND.UNA 指針往右偏移后指向 441,于是可用窗口 Usable 增大到 200。

服務端可以繼續發送了,于是發送了 160 字節的數據后,SND.NXT 指向 601,于是可用窗口 Usable 減少到 40。

客戶端收到 160 字節后,接收窗口往右移動了 160 字節,RCV.NXT 也就是指向了 601,接著發送確認報文給服務端。

服務端收到對 160 字節數據的確認報文后,發送窗口往右移動了 160 字節,于是 SND.UNA 指針偏移了 160 后指向 601,可用窗口 Usable 也就增大至了 200。

操作系統緩沖區與滑動窗口的關系
前面的流量控制例子,我們假定了發送窗口和接收窗口是不變的,但是實際上,發送窗口和接收窗口中所存放的字節數,都是放在操作系統內存緩沖區中的,而操作系統的緩沖區,會被操作系統調整。

當應用進程沒辦法及時讀取緩沖區的內容時,也會對我們的緩沖區造成影響。

那操心系統的緩沖區,是如何影響發送窗口和接收窗口的呢?

我們先來看看第一個例子。

當應用程序沒有及時讀取緩存時,發送窗口和接收窗口的變化。

考慮以下場景:

客戶端作為發送方,服務端作為接收方,發送窗口和接收窗口初始大小為 360;

服務端非常的繁忙,當收到客戶端的數據時,應用層不能及時讀取數據。


根據上圖的流量控制,說明下每個過程:

客戶端發送 140 字節數據后,可用窗口變為 220 (360 - 140)。

服務端收到 140 字節數據,但是服務端非常繁忙,應用進程只讀取了 40 個字節,還有 100 字節占用著緩沖區,于是接收窗口收縮到了 260 (360 - 100),最后發送確認信息時,將窗口大小通過給客戶端。

客戶端收到確認和窗口通告報文后,發送窗口減少為 260。

客戶端發送 180 字節數據,此時可用窗口減少到 80。

服務端收到 180 字節數據,但是應用程序沒有讀取任何數據,這 180 字節直接就留在了緩沖區,于是接收窗口收縮到了 80 (260 - 180),并在發送確認信息時,通過窗口大小給客戶端。

客戶端收到確認和窗口通告報文后,發送窗口減少為 80。

客戶端發送 80 字節數據后,可用窗口耗盡。

服務端收到 80 字節數據,但是應用程序依然沒有讀取任何數據,這 80 字節留在了緩沖區,于是接收窗口收縮到了 0,并在發送確認信息時,通過窗口大小給客戶端。

客戶端收到確認和窗口通告報文后,發送窗口減少為 0。

可見最后窗口都收縮為 0 了,也就是發生了窗口關閉。當發送方可用窗口變為 0 時,發送方實際上會定時發送窗口探測報文,以便知道接收方的窗口是否發生了改變,這個內容后面會說,這里先簡單提一下。

我們先來看看第二個例子。

當服務端系統資源非常緊張的時候,操心系統可能會直接減少了接收緩沖區大小,這時應用程序又無法及時讀取緩存數據,那么這時候就有嚴重的事情發生了,會出現數據包丟失的現象。


說明下每個過程:

客戶端發送 140 字節的數據,于是可用窗口減少到了 220。

服務端因為現在非常的繁忙,操作系統于是就把接收緩存減少了 100 字節,當收到 對 140 數據確認報文后,又因為應用程序沒有讀取任何數據,所以 140 字節留在了緩沖區中,于是接收窗口大小從 360 收縮成了 100,最后發送確認信息時,通告窗口大小給對方。

此時客戶端因為還沒有收到服務端的通告窗口報文,所以不知道此時接收窗口收縮成了 100,客戶端只會看自己的可用窗口還有 220,所以客戶端就發送了 180 字節數據,于是可用窗口減少到 40。

服務端收到了 180 字節數據時,發現數據大小超過了接收窗口的大小,于是就把數據包丟失了。

客戶端收到第 2 步時,服務端發送的確認報文和通告窗口報文,嘗試減少發送窗口到 100,把窗口的右端向左收縮了 80,此時可用窗口的大小就會出現詭異的負值。

所以,如果發生了先減少緩存,再收縮窗口,就會出現丟包的現象。
為了防止這種情況發生,TCP 規定是不允許同時減少緩存又收縮窗口的,而是采用先收縮窗口,過段時間在減少緩存,這樣就可以避免了丟包情況。

窗口關閉

在前面我們都看到了,TCP 通過讓接收方指明希望從發送方接收的數據大小(窗口大小)來進行流量控制。

如果窗口大小為 0 時,就會阻止發送方給接收方傳遞數據,直到窗口變為非 0 為止,這就是窗口關閉。

窗口關閉潛在的危險

接收方向發送方通告窗口大小時,是通過 ACK 報文來通告的。

那么,當發生窗口關閉時,接收方處理完數據后,會向發送方通告一個窗口非 0 的 ACK 報文,如果這個通告窗口的 ACK 報文在網絡中丟失了,那麻煩就大了。


這會導致發送方一直等待接收方的非 0 窗口通知,接收方也一直等待發送方的數據,如不不采取措施,這種相互等待的過程,會造成了死鎖的現象。

TCP 是如何解決窗口關閉時,潛在的死鎖現象呢?

為了解決這個問題,TCP 為每個連接設有一個持續定時器,只要 TCP 連接一方收到對方的零窗口通知,就啟動持續計時器。

如果持續計時器超時,就會發送窗口探測 ( Window probe ) 報文,而對方在確認這個探測報文時,給出自己現在的接收窗口大小。


如果接收窗口仍然為 0,那么收到這個報文的一方就會重新啟動持續計時器;

如果接收窗口不是 0,那么死鎖的局面就可以被打破了。

窗口探查探測的次數一般為 3 此次,每次次大約 30-60 秒(不同的實現可能會不一樣)。如果 3 次過后接收窗口還是 0 的話,有的 TCP 實現就會發 RST 報文來中斷連接。

糊涂窗口綜合癥
如果接收方太忙了,來不及取走接收窗口里的數據,那么就會導致發送方的發送窗口越來越小。

到最后,如果接收方騰出幾個字節并告訴發送方現在有幾個字節的窗口,而發送方會義無反顧地發送這幾個字節,這就是糊涂窗口綜合癥。

要知道,我們的 TCP + IP 頭有 40 個字節,為了傳輸那幾個字節的數據,要達上這么大的開銷,這太不經濟了。

就好像一個可以承載 50 人的大巴車,每次來了一兩個人,就直接發車。除非家里有礦的大巴司機,才敢這樣玩,不然遲早破產。要解決這個問題也不難,大巴司機等乘客數量超過了 25 個,才認定可以發車。

現舉個糊涂窗口綜合癥的栗子,考慮以下場景:

接收方的窗口大小是 360 字節,但接收方由于某些原因陷入困境,假設接收方的應用層讀取的能力如下:

接收方每接收 3 個字節,應用程序就只能從緩沖區中讀取 1 個字節的數據;

在下一個發送方的 TCP 段到達之前,應用程序
還從緩沖區中讀取了 40 個額外的字節;


每個過程的窗口大小的變化,在圖中都描述的很清楚了,可以發現窗口不斷減少了,并且發送的數據都是比較小的了。

所以,糊涂窗口綜合癥的現象是可以發生在發送方和接收方:

接收方可以通告一個小的窗口

而發送方可以發送小數據

于是,要解決糊涂窗口綜合癥,就解決上面兩個問題就可以了

讓接收方不通告小窗口給發送方

讓發送方避免發送小數據

怎么讓接收方不通告小窗口呢?

接收方通常的策略如下:

當「窗口大小」小于 min( MSS,緩存空間/2 ) ,也就是小于 MSS 與 1/2 緩存大小中的最小值時,就會向發送方通告窗口為 0,也就阻止了發送方再發數據過來。

等到接收方處理了一些數據后,窗口大小 >= MSS,或者接收方緩存空間有一半可以使用,就可以把窗口打開讓發送方發送數據過來。

怎么讓發送方避免發送小數據呢?

發送方通常的策略:

使用 Nagle 算法,該算法的思路是延時處理,它滿足以下兩個條件中的一條才可以發送數據:

要等到窗口大小 >= MSS 或是 數據大小 >= MSS

收到之前發送數據的 ack 回包

只要沒滿足上面條件中的一條,發送方一直在囤積數據,直到滿足上面的發送條件。

另外,Nagle 算法默認是打開的,如果對于一些需要小數據包交互的場景的程序,比如,telnet 或 ssh 這樣的交互性比較強的程序,則需要關閉 Nagle 算法。

可以在 Socket 設置 TCP_NODELAY 選項來關閉這個算法(關閉 Nagle 算法沒有全局參數,需要根據每個應用自己的特點來關閉)

setsockopt(sock_fd, IPPROTO_TCP, TCP_NODELAY, (char *)&value, sizeof(int));

擁塞控制


為什么要有擁塞控制呀,不是有流量控制了嗎?

前面的流量控制是避免「發送方」的數據填滿「接收方」的緩存,但是并不知道網絡的中發生了什么。

一般來說,計算機網絡都處在一個共享的環境。因此也有可能會因為其他主機之間的通信使得網絡擁堵。

在網絡出現擁堵時,如果繼續發送大量數據包,可能會導致數據包時延、丟失等,這時 TCP 就會重傳數據,但是一重傳就會導致網絡的負擔更重,于是會導致更大的延遲以及更多的丟包,這個情況就會進入惡性循環被不斷地放大….

所以,TCP 不能忽略網絡上發生的事,它被設計成一個無私的協議,當網絡發送擁塞時,TCP 會自我犧牲,降低發送的數據量。

于是,就有了擁塞控制,控制的目的就是避免「發送方」的數據填滿整個網絡。

為了在「發送方」調節所要發送數據的量,定義了一個叫做「擁塞窗口」的概念。

什么是擁塞窗口?和發送窗口有什么關系呢?

擁塞窗口 cwnd是發送方維護的一個 的狀態變量,它會根據網絡的擁塞程度動態變化的。

我們在前面提到過發送窗口 swnd 和接收窗口 rwnd 是約等于的關系,那么由于入了擁塞窗口的概念后,此時發送窗口的值是swnd = min(cwnd, rwnd),也就是擁塞窗口和接收窗口中的最小值。

擁塞窗口 cwnd 變化的規則:

只要網絡中沒有出現擁塞,cwnd 就會增大;

但網絡中出現了擁塞,cwnd 就減少;

那么怎么知道當前網絡是否出現了擁塞呢?

其實只要「發送方」沒有在規定時間內接收到 ACK 應答報文,也就是發生了超時重傳,就會認為網絡出現了用擁塞。

擁塞控制有哪些控制算法?

擁塞控制主要是四個算法:

慢啟動

擁塞避免

擁塞發生

快速恢復

慢啟動
TCP 在剛建立連接完成后,首先是有個慢啟動的過程,這個慢啟動的意思就是一點一點的提高發送數據包的數量,如果一上來就發大量的數據,這不是給網絡添堵嗎?

慢啟動的算法記住一個規則就行:當發送方每收到一個 ACK,就擁塞窗口 cwnd 的大小就會加 1。

這里假定擁塞窗口 cwnd 和發送窗口 swnd 相等,下面舉個栗子:

連接建立完成后,一開始初始化 cwnd = 1,表示可以傳一個 MSS 大小的數據。

當收到一個 ACK 確認應答后,cwnd 增加 1,于是一次能夠發送 2 個

當收到 2 個的 ACK 確認應答后, cwnd 增加 2,于是就可以比之前多發2 個,所以這一次能夠發送 4 個

當這 4 個的 ACK 確認到來的時候,每個確認 cwnd 增加 1, 4 個確認 cwnd 增加 4,于是就可以比之前多發 4 個,所以這一次能夠發送 8 個。


可以看出慢啟動算法,發包的個數是指數性的增長。

那慢啟動漲到什么時候是個頭呢?

有一個叫慢啟動門限 ssthresh (slow start threshold)狀態變量。

當 cwnd < ssthresh 時,使用慢啟動算法。

當 cwnd >= ssthresh 時,就會使用「擁塞避免算法」。

擁塞避免算法
前面說道,當擁塞窗口 cwnd 「超過」慢啟動門限 ssthresh 就會進入擁塞避免算法。

一般來說 ssthresh 的大小是 65535 字節。

那么進入擁塞避免算法后,它的規則是:每當收到一個 ACK 時,cwnd 增加 1/cwnd。

接上前面的慢啟動的栗子,現假定 ssthresh 為 8:

當 8 個 ACK 應答確認到來時,每個確認增加 1/8,8 個 ACK 確認 cwnd 一共增加 1,于是這一次能夠發送 9 個 MSS 大小的數據,變成了線性增長。


所以,我們可以發現,擁塞避免算法就是將原本慢啟動算法的指數增長變成了線性增長,還是增長階段,但是增長速度緩慢了一些。

就這么一直增長著后,網絡就會慢慢進入了擁塞的狀況了,于是就會出現丟包現象,這時就需要對丟失的數據包進行重傳。

當觸發了重傳機制,也就進入了「擁塞發生算法」。

擁塞發生
當網絡出現擁塞,也就是會發生數據包重傳,重傳機制主要有兩種:

超時重傳

快速重傳

這兩種使用的擁塞發送算法是不同的,接下來分別來說說。

發生超時重傳的擁塞發生算法

當發生了「超時重傳」,則就會使用擁塞發生算法。

這個時候,sshresh 和 cwnd 的值會發生變化:

ssthresh 設為 cwnd/2,

cwnd 重置為 1


接著,就重新開始慢啟動,慢啟動是會突然減少數據流的。這真是一旦「超時重傳」,馬上回到解放前。但是這種方式太激進了,反應也很強烈,會造成網絡卡頓。

就好像本來在秋名山高速漂移著,突然來個緊急剎車,輪胎受得了嗎。。。

發生快速重傳的擁塞發生算法

還有更好的方式,前面我們講過「快速重傳算法」。當接收方發現丟了一個中間包的時候,發送三次前一個包的 ACK,于是發送端就會快速地重傳,不必等待超時再重傳。

TCP 認為這種情況不嚴重,因為大部分沒丟,只丟了一小部分,則 ssthresh 和 cwnd 變化如下:

cwnd = cwnd/2 ,也就是設置為原來的一半;

ssthresh = cwnd;

進入快速恢復算法

快速恢復
快速重傳和快速恢復算法一般同時使用,快速恢復算法是認為,你還能收到 3 個重復 ACK 說明網絡也不那么糟糕,所以沒有必要像 RTO 超時那么強烈。

正如前面所說,進入快速恢復之前,cwnd 和 ssthresh 已被更新了:

cwnd = cwnd/2 ,也就是設置為原來的一半;

ssthresh = cwnd;

然后,進入快速恢復算法如下:

擁塞窗口 cwnd = ssthresh + 3 ( 3 的意思是確認有 3 個數據包被收到了)

重傳丟失的數據包

如果再收到重復的 ACK,那么 cwnd 增加 1

如果收到新數據的 ACK 后,設置 cwnd 為 ssthresh,接著就進入了擁塞避免算法

也就是沒有像「超時重傳」一夜回到解放前,而是還在比較高的值,后續呈線性增長。

參考:https://mp.weixin.qq.com/s?__biz=MzAxODQxMDM0Mw==&mid=2247485167&idx=2&sn=19facbf79be561aee497e36d61d4c3a3&chksm=9bd7f8e7aca071f1d0330bf4aa8850e6ac050da7aad2af5a1b609e6a9c330b5b9c710ca6ddde&scene=21#wechat_redirect

https://mp.weixin.qq.com/s/xe3dEu17mGTqM46LRFxzhg

創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎

總結

以上是生活随笔為你收集整理的tcp前4字节消息长度_网络基础篇之TCP的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

男女全黄一级一级高潮免费看 | 中文字幕在线观看91 | 日韩理论在线播放 | 在线天堂v| 国产欧美久久久精品影院 | www.成人精品 | 日韩高清免费在线 | 日本乱码在线 | 在线韩国电影免费观影完整版 | 久草在线视频网站 | 91一区一区三区 | 中文字幕影视 | 亚洲国产一区在线观看 | 欧美黑人巨大xxxxx | 天天搞天天干天天色 | 日韩在线小视频 | 亚洲欧洲精品视频 | 日韩.com| 综合久久2023 | 手机在线黄色网址 | 欧美日韩国产一区二区三区在线观看 | 久热电影| 亚洲电影久久久 | 成人福利在线观看 | 一区二区中文字幕在线观看 | 国产精品免费观看久久 | 啪一啪在线 | 国产性天天综合网 | 九九视频免费观看视频精品 | 中文字幕观看视频 | a在线观看视频 | 亚洲黄污 | 欧美a级一区二区 | 青春草视频在线播放 | 亚洲国产网站 | 免费在线观看av不卡 | 国产精品a久久久久 | 久久精品99久久久久久 | 美女网站在线看 | 欧美日韩国产三级 | 在线免费国产视频 | 亚洲欧美综合精品久久成人 | 国产又黄又爽又猛视频日本 | 黄网站大全 | 天天天在线综合网 | 亚洲手机av | 最近中文字幕国语免费高清6 | 亚洲精品五月 | 一区二区三区三区在线 | 五月天狠狠操 | 日日夜夜网 | 夜色资源网| 久久资源总站 | 亚洲精品乱码久久久久久写真 | 亚洲综合在线视频 | 久久黄色影院 | 国产精品原创av片国产免费 | 91福利视频免费观看 | 97在线看| 黄网在线免费观看 | 高清av网站 | 一区中文字幕电影 | 久久男人中文字幕资源站 | 亚洲精品白浆高清久久久久久 | 国产色婷婷精品综合在线手机播放 | 五月香婷 | 国产精品高潮呻吟久久久久 | 最近中文字幕免费大全 | 亚洲精品视频免费在线 | 亚洲毛片在线观看. | 久久国产精品久久久 | 久久久久久久国产精品影院 | 久久久久久久久久久成人 | aaa毛片视频 | av黄色影院 | 在线观看一区二区精品 | 91女子私密保健养生少妇 | 五月婷婷在线观看视频 | 超薄丝袜一二三区 | 亚洲视频,欧洲视频 | 免费中午字幕无吗 | 日韩免费小视频 | 久操97| 99久久久免费视频 | 丁香花在线观看免费完整版视频 | 热九九精品 | 综合影视| 美女精品久久久 | 国产免费观看高清完整版 | 狠狠色狠狠色终合网 | 亚洲涩涩网站 | 久草视频播放 | 成人免费一级 | 亚洲欧美婷婷六月色综合 | 中文字幕av专区 | 夜夜干夜夜 | 欧美午夜精品久久久久 | 欧美天堂久久 | 亚洲综合色视频在线观看 | 欧美日韩国产二区 | 一级片视频免费观看 | 亚洲午夜精品一区 | 91网在线看 | 亚洲国产美女久久久久 | 国产精品日韩在线播放 | 国产日韩欧美在线观看 | 国产黄色视 | 欧美性色黄 | 91在线小视频 | 国产精品国产三级国产 | 亚洲乱亚洲乱妇 | 2023av| 91麻豆精品国产91久久久无需广告 | 精品播放 | 97在线看片 | 亚洲精品午夜久久久久久久久久久 | 就色干综合 | 免费在线看成人av | av在线播放快速免费阴 | 麻豆小视频在线观看 | 久久区二区 | 91超碰在线播放 | 久久精品国产美女 | 99国产成+人+综合+亚洲 欧美 | 99精品免费久久久久久日本 | 日韩欧美黄色网址 | 国产精品一区二区 91 | 日韩欧美v| 激情五月激情综合网 | 久久久亚洲网站 | 日韩在线中文字幕 | 国产无吗一区二区三区在线欢 | 亚洲国产资源 | 综合铜03 | 91久久偷偷做嫩草影院 | 国产aa精品 | 日韩视频图片 | 国产91精品在线观看 | 播五月综合 | 国产69精品久久久久99 | 99久久精品免费看国产免费软件 | 国内视频在线观看 | 不卡的av中文字幕 | 夜色成人av | 欧美一区二区三区在线观看 | 国产高清在线视频 | 午夜美女视频 | 国产在线观看免费av | 欧美美女激情18p | 99视频国产在线 | 亚洲日本欧美在线 | a级国产乱理伦片在线播放 久久久久国产精品一区 | 国产小视频你懂的 | 国产91粉嫩白浆在线观看 | 国产一级电影免费观看 | 99久久综合国产精品二区 | 国产精品永久免费 | www最近高清中文国语在线观看 | 最近中文字幕国语免费av | 欧美激情操| 四虎国产精品免费观看视频优播 | 欧美激情视频一区 | 天天操天天干天天爱 | a在线免费 | 精品在线观看一区二区 | 精品美女久久久久 | 日韩一区二区三区在线看 | 亚洲香蕉在线观看 | 国产亚洲精品久久久久久电影 | 激情中文在线 | 99精品一级欧美片免费播放 | 免费精品 | 免费人人干 | 亚洲自拍偷拍色图 | 欧美嫩草影院 | 免费看国产黄色 | 久久99国产一区二区三区 | 国产不卡免费av | 国产精品久久久久久久7电影 | 欧美日韩中文字幕在线视频 | 91九色蝌蚪国产 | 1024在线看片 | 国产高清综合 | 欧美综合久久 | 国产做a爱一级久久 | 久久激情小视频 | av在线电影网站 | 亚洲国产精品电影 | 91免费日韩 | 国产亚洲在线观看 | 久久久久女教师免费一区 | 香蕉视频91 | 欧洲一区精品 | 国产在线第三页 | 麻豆视频一区 | 人人干人人爽 | 国产这里只有精品 | 丁香婷婷综合激情五月色 | 91看片看淫黄大片 | 99久热在线精品视频成人一区 | 九九九热精品免费视频观看网站 | 亚洲狠狠丁香婷婷综合久久久 | h动漫中文字幕 | 国产精品精品 | 国产一级免费电影 | 粉嫩高清一区二区三区 | 手机av在线网站 | 四虎影视8848dvd | 激情开心 | 欧美日一级片 | 欧美性免费 | 97国产在线 | 精品一区精品二区高清 | 成人av高清 | 91精品国产网站 | 亚洲在线观看av | 国产99亚洲 | 国产黄色大全 | 色婷婷亚洲精品 | 欧美射射射 | 精品国产视频在线 | 最近中文字幕高清字幕免费mv | 免费日韩 精品中文字幕视频在线 | 亚洲精品一区二区三区四区高清 | 欧美日韩1区 | 免费福利视频网 | 久久黄色免费观看 | 97香蕉久久超级碰碰高清版 | 精壮的侍卫呻吟h | 久久国产精品久久国产精品 | 人人澡人人干 | 韩国av一区二区 | 91精品国产99久久久久 | 久久免费资源 | 日韩一级片网址 | 国产美女被啪进深处喷白浆视频 | 福利视频一二区 | 精品高清美女精品国产区 | 国产精品中文字幕在线播放 | 亚洲精品在线视频 | 久久毛片高清国产 | 亚洲影院一区 | 久久色在线观看 | 丝袜制服天堂 | 伊色综合久久之综合久久 | 国产中文字幕在线视频 | 日韩a级免费视频 | 日韩综合一区二区三区 | 久久天天躁夜夜躁狠狠躁2022 | 精品国产1区2区3区 国产欧美精品在线观看 | 中文字幕一区二区三区乱码不卡 | 五月婷婷天堂 | 亚洲一区视频免费观看 | 国产精品免费视频久久久 | 国产一级免费在线 | 欧美与欧洲交xxxx免费观看 | 国产高清亚洲 | 国产免费作爱视频 | 91少妇精拍在线播放 | 日韩午夜电影院 | 在线www色 | 欧美福利视频 | 欧美日韩一区二区三区不卡 | 九九视频在线播放 | 日韩精品中文字幕在线 | 中文字幕在线观看视频一区 | 成人午夜精品久久久久久久3d | 一区二区 不卡 | 超碰在线公开免费 | 国产精品国产三级国产专区53 | 九九视频这里只有精品 | 久草视频一区 | 久久久久久久久久亚洲精品 | 久久精品第一页 | 国产精品麻豆三级一区视频 | 精品久久五月天 | 国产精品私人影院 | 国产资源中文字幕 | 91热爆在线观看 | 国产黄色免费看 | 国产一区二区三区在线免费观看 | 四虎在线观看 | 国产精品久久久久久久久久久久午 | 久久久久成人精品亚洲国产 | 99久久综合狠狠综合久久 | 国产资源在线观看 | 美女网站黄在线观看 | 免费在线观看av网站 | se婷婷| 久久人人爽爽人人爽人人片av | 国产精品免费人成网站 | 久久夜夜爽 | 欧美大码xxxx | 国产精品欧美激情在线观看 | 全黄色一级片 | 丁香六月av| 欧美激情片在线观看 | 91漂亮少妇露脸在线播放 | 午夜av不卡| 97久久精品午夜一区二区 | 天天草天天插 | 欧洲精品久久久久毛片完整版 | 免费国产一区二区视频 | 色婷婷色| 免费看的黄网站软件 | 天天操 夜夜操 | 日韩电影黄色 | 蜜臀av性久久久久蜜臀aⅴ流畅 | 久在线观看视频 | 国产精品中文字幕在线播放 | 国产尤物视频在线 | 国产精品18久久久久久不卡孕妇 | av免费网站在线观看 | av高清一区二区三区 | 五月丁婷婷 | 免费男女羞羞的视频网站中文字幕 | 91av蜜桃| 一区二区不卡 | 欧美 国产 视频 | 精品黄色在线 | 色国产在线 | 亚洲国内精品在线 | 欧美日韩中文在线观看 | 久久精品99久久 | 欧美日韩二三区 | 正在播放国产一区 | 日韩av网站在线播放 | 国产精品手机在线 | 日韩有码在线播放 | 天天操天天综合网 | 久久久国产精品成人免费 | 婷婷综合成人 | 成人影视免费看 | 久久精国产| 成 人 黄 色 片 在线播放 | 91av视频观看 | 久久久久在线观看 | 久久优 | 国产精品麻 | 日韩欧美视频在线免费观看 | 狠狠综合久久 | 超碰在线日本 | 免费在线黄 | 成人蜜桃视频 | 亚洲国产色一区 | 国产不卡av在线播放 | 狠狠的操你 | 97超碰精品 | 国产精品久久久久免费 | 肉色欧美久久久久久久免费看 | 色婷婷精品大在线视频 | 国内精品久久久久 | 97爱爱爱| 激情伊人五月天久久综合 | 国产精品成人久久久久 | 亚洲精品高清在线 | 国产三级视频在线 | 日韩视频一区二区在线 | 国产精品理论在线观看 | 在线黄色av电影 | 成人免费在线视频观看 | 91亚州 | 国产精品美女久久久久久久网站 | 超碰97在线资源站 | 婷婷色在线资源 | 婷婷六月天综合 | 日韩av一区二区三区在线观看 | bayu135国产精品视频 | 美女免费网视频 | 最近的中文字幕大全免费版 | 欧美专区国产专区 | 99精品在线直播 | 成人在线观看影院 | 亚洲欧美视频在线观看 | 久久久网| 国产又粗又猛又黄视频 | 天天操狠狠操 | 久久久久黄色 | 在线亚洲小视频 | 四虎免费在线观看视频 | 国产成人333kkk| 色婷婷午夜 | 青草视频免费观看 | 日本激情视频中文字幕 | 久草精品网 | 国产精品美女久久久久久2018 | 亚洲精品乱码久久久久久9色 | 高潮久久久久久久久 | 91精品国自产在线观看欧美 | 精品国产一区二区三区久久久久久 | 日韩欧美黄色网址 | 91视频亚洲 | 99精品偷拍视频一区二区三区 | 日韩在线观看av | 亚洲国产视频在线 | 97日日| 精品二区久久 | 日韩中文字幕免费视频 | 亚洲精品久久久久www | 99久久激情视频 | 日韩精品最新在线观看 | 国内精品亚洲 | 玖玖综合网 | 日韩欧美一级二级 | 天天av综合网 | 精品国产一区二区三区av性色 | 亚洲欧美日韩一二三区 | 西西4444www大胆艺术 | 97人人模人人爽人人喊中文字 | 国产精品白浆视频 | 天天操夜夜操天天射 | 精品久久久久久亚洲综合网站 | 久久视频中文字幕 | 热久在线 | 国产精品毛片久久久久久久久久99999999 | 久久久久久国产精品亚洲78 | 国产综合片 | 国产一级黄色电影 | 波多野结衣在线观看一区二区三区 | 日韩高清免费在线观看 | 性色va| 一区二区三区国产欧美 | 波多野结衣久久精品 | 亚洲精品在线播放视频 | 亚洲一级二级 | 狠狠干免费 | 美女免费视频一区二区 | 一区二区精品国产 | 五月天.com| 亚州国产精品久久久 | 国产亚洲精品v | 成人午夜剧场在线观看 | 国产精品资源 | 免费久久99精品国产婷婷六月 | 91漂亮少妇露脸在线播放 | 欧美黄色软件 | 亚洲一区二区三区四区在线视频 | 日韩免费福利 | 玖玖视频免费在线 | 日日噜噜噜噜夜夜爽亚洲精品 | 一区免费在线 | 日韩av网站在线播放 | 超碰公开在线观看 | 狠狠综合网 | 久久夜色精品亚洲噜噜国4 午夜视频在线观看欧美 | 国产精品视屏 | 97视频免费在线看 | 欧美一级日韩免费不卡 | 国产黄色精品在线 | 日本韩国精品在线 | 一区二区精品视频 | 开心色插| 日韩最新理论电影 | 国产午夜视频在线观看 | 91免费高清观看 | 国产成人精品一区二三区 | www中文在线 | 亚洲精品tv久久久久久久久久 | 亚洲精品国偷自产在线91正片 | 麻豆久久久 | 日日夜夜精品视频天天综合网 | 日韩一区二区在线免费观看 | 人人爽人人射 | av一级片 | 五月天视频网 | 久久久久综合视频 | 在线影视 一区 二区 三区 | 夜夜操天天干 | 日韩大片在线播放 | 五月婷婷影视 | 日本黄色片一区二区 | 欧美日韩免费视频 | 色老板在线 | 久久午夜精品影院一区 | 日韩欧美在线观看一区二区三区 | 亚洲人成免费网站 | 99精品乱码国产在线观看 | 亚洲精品国 | 久久成人人人人精品欧 | 麻豆av一区二区三区在线观看 | 国产视频久久 | 久久国产精品视频 | 免费国产一区二区视频 | 日韩色综合 | 日本成人a| 91精品一区在线观看 | 中文字幕在线观看你懂的 | 国内精品久久天天躁人人爽 | 亚洲精品在线视频观看 | 日韩一区二区在线免费观看 | 国产精品久久久久一区 | 国产精品自产拍在线观看网站 | 亚洲精品在线视频网站 | 国产午夜精品一区二区三区在线观看 | 久久在线免费观看视频 | 91在线观看视频 | 91超级碰碰 | 粉嫩av一区二区三区四区 | 日韩免费在线网站 | 91在线网址 | 日本色小说视频 | 久久久久久久久久久久电影 | 日韩电影在线视频 | 日韩理论视频 | 免费观看性生交 | 成人a级黄色片 | 91免费观看视频网站 | 日韩精品免费在线观看视频 | 日韩欧美有码在线 | 免费视频二区 | 99热精品久久 | 天天综合成人 | 天天色天天上天天操 | 日本黄色免费在线观看 | 国产亚洲一级高清 | 少妇性aaaaaaaaa视频 | a视频在线观看 | 亚洲,播放| 精品久久国产精品 | 精品影院一区二区久久久 | 色狠狠一区二区 | 久久久久国产成人精品亚洲午夜 | 美女黄网久久 | 在线精品视频免费播放 | 99久久99久久 | 97精品超碰一区二区三区 | 果冻av在线| 国产精品福利一区 | 国产精品久久久久久久午夜 | 精品女同一区二区三区在线观看 | 最新国产在线 | 婷婷成人综合 | 国产香蕉视频在线播放 | 99在线国产 | 久久91久久久久麻豆精品 | 天天操天天射天天舔 | 欧美色综合天天久久综合精品 | av成人免费在线观看 | 最新国产一区二区三区 | 国产黄a三级三级三级三级三级 | 日韩三级视频在线观看 | 99999精品| 最新中文字幕在线播放 | 国产一区高清在线观看 | 天天草综合 | 成人欧美在线 | 超碰在线91 | 免费久久网 | 高清一区二区三区 | 99精品视频在线播放观看 | 91超碰免费在线 | 国产精品第二页 | 久久综合激情 | 欧美久久久影院 | 久久99日韩 | av软件在线观看 | 午夜99| 久久中文网| 午夜狠狠操 | 91成人在线观看喷潮 | 亚洲色图 校园春色 | 国产精品久久片 | 久久久综合电影 | 亚洲欧洲视频 | 香蕉久久久久久av成人 | 精品在线观看一区二区 | 日韩av电影免费在线观看 | 99av国产精品欲麻豆 | 日韩黄视频 | 超碰精品在线 | 在线视频福利 | 国产精品二区在线 | 91mv.cool在线观看 | 日韩精品一区二区不卡 | 久久免费av电影 | 国产精品一区二区在线播放 | 欧美激情va永久在线播放 | 伊人久久电影网 | 久久99精品国产91久久来源 | 黄色成人av | 在线观看av免费 | 国产成人一区二区三区电影 | 久久桃花网 | 久久久久久久久免费视频 | 久久 亚洲视频 | 2021av在线| 中国成人一区 | 久久99精品久久只有精品 | 欧美在线视频二区 | 综合色中色 | 日本黄色免费在线观看 | 国产第一福利网 | 91精品视频免费 | av看片在线观看 | 日韩在线视频网址 | 国产精品久久久久久久久婷婷 | 99久久久国产精品免费99 | 日韩在线中文字幕 | 亚洲成人av电影在线 | 丝袜美女视频网站 | 久久免费激情视频 | 色网站视频 | 日韩av不卡在线观看 | 最近免费中文字幕 | a黄色片在线观看 | 中文字幕免费成人 | 在线一二三四区 | av三级av| 超碰日韩在线 | 97夜夜澡人人爽人人免费 | 国产69精品久久久久久久久久 | 国产精品ssss在线亚洲 | 天天久久综合 | 五月婷婷导航 | 久久午夜羞羞影院 | 天天摸天天操天天爽 | 超碰人人射 | 欧美大片在线看免费观看 | 综合久久网 | 91女子私密保健养生少妇 | 久久亚洲精品国产亚洲老地址 | 亚洲免费视频在线观看 | 四虎www. | 国产黄a三级三级三级三级三级 | www狠狠 | 综合网婷婷| 成人三级黄色 | av不卡免费在线观看 | 成年免费在线视频 | 免费精品在线观看 | 日日爱网站 | 成人国产电影在线观看 | 亚洲 在线| 国产高清视频在线播放 | 国产精品美女视频网站 | 色操插 | 免费在线国产视频 | 欧美日本日韩aⅴ在线视频 插插插色综合 | 91av精品 | 国产69精品久久app免费版 | 亚洲精品乱码久久久久久按摩 | 国产精品aⅴ | 成人av在线直播 | 国产美女视频网站 | 亚洲黄色在线免费观看 | 综合久久久 | 国产区久久 | 最新久久久 | 日韩久久网站 | 国产精品久久久久久久久蜜臀 | 五月婷婷六月丁香激情 | 亚洲五月婷 | 免费久久网站 | 夜夜操网站 | 亚洲精品国 | 国产精品久久久久久久久婷婷 | 激情www| 国产在线视频一区二区三区 | 日韩国产欧美在线视频 | 中文字幕一区二区三区四区在线视频 | 亚洲在线| 五月婷婷六月综合 | 亚洲一区欧美激情 | 欧美专区亚洲专区 | 国产精品久久综合 | 国产精品资源在线观看 | 亚洲欧美日韩精品一区二区 | 狠狠色丁香婷婷综合久小说久 | 中文av在线播放 | 日韩精品第1页 | 精品二区久久 | 成人av一区二区三区 | avav片 | 97夜夜澡人人双人人人喊 | 国产精选在线观看 | 欧美日韩一区二区久久 | 国产69久久 | 99视频精品免费视频 | 国产精品99久久免费黑人 | 国产一区二区综合 | 狠狠色丁香婷婷综合久小说久 | 91爱爱电影 | 97超碰人人模人人人爽人人爱 | 日本久久免费电影 | 久久五月精品 | 国产精品永久免费视频 | 久色网| 五月天激情视频在线观看 | 麻豆91在线| 一级片免费视频 | 成人免费中文字幕 | 久久精品久久99 | 黄色avwww| 日本三级人妇 | 精品毛片在线 | 2024国产在线| 欧美日韩免费一区二区三区 | 亚州av网站大全 | 久久夜色精品国产欧美一区麻豆 | 日韩资源视频 | 国产一级片久久 | 五月色综合| 欧美一区二区三区激情视频 | www.夜夜操.com| 色综合久久综合中文综合网 | 激情网在线观看 | 91原创在线观看 | 视频三区| 天天色天天射天天综合网 | 欧美日一级片 | 日韩在线 | 中文视频在线 | 亚洲国产日韩在线 | 日本精品久久久久中文字幕 | 亚州激情视频 | 色.com| 日韩在线精品一区 | 中文字幕精品一区久久久久 | 久久99久久99精品中文字幕 | 2022国产精品视频 | 亚洲三级黄色 | 亚洲精品视频大全 | 成人小视频在线免费观看 | 久久精品国产99 | 国产 在线 高清 精品 | 国产精品完整版 | 国产一区二区在线免费播放 | 亚洲精品久久久蜜臀下载官网 | 精品影院一区二区久久久 | 日韩xxxx视频 | 免费精品视频在线 | 欧美日韩一级久久久久久免费看 | 欧美日韩性视频 | 国产精品一区二区美女视频免费看 | 97色免费视频 | 欧洲一区二区在线观看 | 久久免费福利视频 | 日韩啪啪小视频 | av电影不卡 | 久久超碰在线 | 一区二区三区精品久久久 | 97超碰人人澡| 午夜视频在线网站 | 国产精品成人一区二区三区吃奶 | 欧美日韩国产三级 | 成人黄色电影在线播放 | 91精品国产99久久久久 | 天天综合亚洲 | 久草精品电影 | 色99网| 日韩黄色中文字幕 | 国产中文字幕国产 | 亚洲午夜久久久影院 | 91av成人 | 久久不卡av| www.av在线播放| 精品国产精品一区二区夜夜嗨 | 亚洲精品1区2区3区 超碰成人网 | 国产色在线观看 | 天天弄天天干 | 在线视频在线观看 | 亚洲三级毛片 | 国产精品久久嫩一区二区免费 | 国产精品a成v人在线播放 | 亚洲a色| 粉嫩av一区二区三区四区 | 人人擦| av成人在线播放 | 久久av在线| 成人在线视频你懂的 | 国产黄色高清 | 国产69精品久久99的直播节目 | 在线观看黄网站 | 精品免费观看视频 | av东方在线 | 欧美成年性 | 欧美一区二区精美视频 | 国产99久久久国产精品免费看 | 中文字幕 国产 一区 | 国产成人资源 | av一区在线播放 | 成人在线视频论坛 | 国产黄在线看 | 国产精品久久久久999 | 免费在线观看午夜视频 | 日韩免费福利 | 99热手机在线 | 亚洲日本欧美在线 | 国产精品www| 国产一区在线免费 | 欧美久久久久久 | 香蕉一区| 国产乱码精品一区二区蜜臀 | 中文av在线播放 | 碰超在线 | 久久精品国产亚洲精品 | 99精品电影| 欧美成年黄网站色视频 | 97超碰中文字幕 | 国产一级免费在线观看 | 国产又粗又猛又爽又黄的视频先 | 久久理论电影网 | 狠狠狠狠狠狠狠狠干 | 成全在线视频免费观看 | 成人a免费| 欧美精品久久久久久久久久久 | 久久99视频精品 | 97成人精品区在线播放 | 91精品国产欧美一区二区成人 | 91污污视频在线观看 | 欧美资源 | 五月婷婷在线视频 | av在线网站免费观看 | 成人精品一区二区三区中文字幕 | 国产成人久久精品 | 欧美一级特黄aaaaaa大片在线观看 | 国产艹b视频 | 中文字幕亚洲欧美日韩 | 久久久国产成人 | 久草在线观看视频免费 | 久久艹中文字幕 | 99国产精品久久久久久久久久 | 亚洲久草在线 | 国产免费区 | 97成人精品视频在线观看 | 九九九视频在线 | 2018好看的中文在线观看 | 欧美午夜a | 嫩草av影院 | 888av| www.成人精品 | 日韩精品一区二区在线观看视频 | 麻豆视频网址 | 国产手机在线观看 | 亚洲精品男人的天堂 | 日韩 国产| 在线小视频国产 | 五月天中文字幕 | 狠狠色香婷婷久久亚洲精品 | 国产精品18久久久久久久久久久久 | 久久久久久久综合色一本 | 亚洲a成人v | 国内揄拍国产精品 | 国产亚洲精品久久久久久移动网络 | 久久在线观看视频 | 成年人在线看视频 | 日日成人网 | 日本在线视频网址 | 99精品国产在热久久下载 | 国产精品免费一区二区 | 亚洲成人免费 | 日韩电影一区二区在线观看 | 中文字幕人成乱码在线观看 | 亚洲精品大片www | 久久久资源网 | 国产在线理论片 | 免费看黄在线 | 国产最新精品视频 | 欧美性生活免费 | 国产精品免费视频久久久 | va视频在线观看 | 国产成人在线免费观看 | 国际av在线 | 国产成人久久av977小说 | 久久视频国产精品免费视频在线 | 一区二区影院 | 久久69av | 欧美-第1页-屁屁影院 | 久久久久高清毛片一级 | 色在线国产 | 国产中文字幕在线 | 久久精品日韩 | 久久久免费看片 | 欧美极品少妇xxxxⅹ欧美极品少妇xxxx亚洲精品 | 日韩一区二区三区免费电影 | 日韩色一区二区三区 | 在线国产精品视频 | 久av在线 | 国产一级二级三级在线观看 | 国产视频一区在线播放 | 亚洲最新av| av在线激情 | 美女免费黄视频网站 | 国产一区二区高清 | 91完整版| 久久久一本精品99久久精品66 | 亚洲资源一区 | 久久成人人人人精品欧 | 久久99久久99精品免费看小说 | 亚洲综合色婷婷 | 97品白浆高清久久久久久 | 国产精品亚洲a | 91在线视频免费 | 中文字幕免费在线看 | 亚洲精品美女在线观看播放 | 日韩欧美国产精品 | 日日操网站 | 91精品国产高清自在线观看 | 亚洲国产高清视频 | 热久久国产 | 亚洲国产片色 | 欧美性高跟鞋xxxxhd | 精品一区二区三区久久久 | 美女国内精品自产拍在线播放 | 国产二区视频在线 | 久久99久久99免费视频 | 超碰在线观看97 | 美女视频免费一区二区 | 久久一区国产 | 丁香婷婷激情国产高清秒播 | 国产视频一二区 | 免费a v视频 | 国产老太婆免费交性大片 | 伊人久久一区 | 九九九热精品 | 成年免费在线视频 | 天天操天天干天天操天天干 | 久久免费视频1 | 中文字幕在线观看国产 | 亚洲激精日韩激精欧美精品 | 日韩欧美精品一区 | 日韩亚洲国产中文字幕 | 麻豆视频在线免费观看 | 色婷婷色 | 亚洲日本黄色 | 香蕉在线影院 | 日韩免费二区 | 国产超碰在线 | 国产色视频 | av资源免费观看 | 成人h动漫在线看 | 日韩免费在线观看 | 日韩精品一区二区在线观看视频 | 国产精品一区在线播放 | 亚洲一二区精品 | 国产免费专区 | 狠狠躁日日躁夜夜躁av | 成人91av| 免费视频 你懂的 | 日韩 国产 | 91视频免费看 | 色综合久久久久综合 | 亚洲视频电影在线 | 国产午夜在线观看 | 高清中文字幕 | 人人澡人人模 | 韩日视频在线 | 日本黄区免费视频观看 | 精品一区二区三区久久久 | 国产高清视频色在线www | 色婷婷九月 | www激情久久 | 在线观看免费高清视频大全追剧 | 91观看视频 | 91视频一8mav | 国产色道| 久久久久久久18 | 丁香高清视频在线看看 | 福利久久久 | 一本一道久久a久久精品 | 国产三级精品三级在线观看 | 欧美一级性生活 | 欧美在线一级片 | 91免费高清视频 | 五月激情天 | 亚洲视频 中文字幕 | 国内精品久久久久影院日本资源 | 久久经典国产视频 | 久99久精品| 国产精品久久久久久一区二区三区 | 国产一级特黄毛片在线毛片 | 亚洲午夜精品在线观看 | 丁香六月在线观看 | 精品国产资源 | 欧美一级免费高清 | 亚洲欧美偷拍另类 | 在线成人av | 久久公开视频 | 青春草视频 | 亚洲精品18p | 国产一区二区免费看 | 久久久高清免费视频 | 狠狠色香婷婷久久亚洲精品 | 中文字幕第一 | 深爱五月激情五月 | 中文字幕免费高清av | av在线网站观看 | 在线国产视频观看 | 国产美女在线精品免费观看 | 麻豆国产在线视频 | 一区二区三区四区不卡 | 久久久91精品国产一区二区三区 | 手机av永久免费 | 日韩精品一区二区三区三炮视频 | 夜夜操夜夜干 | 久久精彩视频 | www.亚洲精品视频 | 欧美一二三四在线 |