精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

斯坦福 CS144 計算機網絡播客:傳輸層協議、可靠通信與端到端原則

網絡 網絡管理
用戶數據報協議 (User Datagram Protocol, UDP)?提供的是一種極其簡單的服務。你可以把它想象成一個只管寄信、不問結果的郵差。

互聯網的核心魅力在于其連接能力,但這份連接的底層網絡,本質上是“盡力而為”(best-effort)的——它不保證數據包一定能送達,也不保證它們的順序或完整性。那么,我們每天使用的網頁瀏覽、文件下載等需要高度可靠性的應用,是如何在這片“狂野西部”之上建立起秩序的呢?

答案就在 傳輸層 (Transport Layer) 。

這篇博文將和你一起,深入探討傳輸層的兩大核心協議:UDP 和 TCP,并揭示它們如何一步步從不可靠的服務之上,構建出我們依賴的可靠通信。

傳輸層的兩大支柱:UDP 與 TCP

傳輸層協議在不同的應用程序之間提供端到端的通信服務。在這個層面上,有兩個性格迥異的主角:UDP 和 TCP。

UDP:輕裝上陣的“信使”

用戶數據報協議 (User Datagram Protocol, UDP) 提供的是一種極其簡單的服務。你可以把它想象成一個只管寄信、不問結果的郵差。

它的特點非常鮮明:

  • 無連接 (Connectionless) :發送數據前不需要“握手”建立連接。每個數據報(datagram)都包含了所有必要的信息,獨立地在網絡中傳輸。
  • 不可靠 (Unreliable) :它不保證數據報一定送達,不發送確認,不檢測丟失,也不會要求重發。
  • 無序 (No Ordering) :數據報到達的順序可能與發送順序不同。如果應用需要有序,必須自己在上層處理。
  • 開銷小 :UDP 頭部只有 8 字節,包含源/目的端口、長度和校驗和四個字段,非常高效。

正是因為這些特點,UDP 非常適用于那些對實時性要求高、能容忍少量丟包、或者應用層自己實現了可靠性機制的場景。

典型的應用實例包括:

  • DNS (域名系統) :一次請求和一次響應,快速高效。
  • DHCP (動態主機配置協議) :用于獲取 IP 地址。
  • NTP (網絡時間協議) :用于時間同步。
  • 在線游戲、視頻直播等。

值得一提的是 UDP 的校驗和 (Checksum)。它不僅計算 UDP 頭部和數據,還包含了源/目的 IP 地址和協議 ID 等偽頭部信息。這在理論上違反了分層原則(傳輸層不應關心網絡層信息),但這是一個非常務實的設計,它能幫助檢測數據報是否因為網絡錯誤而被“張冠李戴”,送錯了終點。

TCP:穩重可靠的“工程師”

傳輸控制協議 (Transmission Control Protocol, TCP) 是互聯網的基石,超過 95% 的互聯網應用(如網頁瀏覽、郵件、文件傳輸)都構建在它之上。與 UDP 的“放任不管”不同,TCP 提供的是一種 可靠的、面向連接的、雙向字節流 (bi-directional byte stream) 服務。

它就像一位嚴謹的工程師,通過一系列復雜的機制來確保萬無一失:

  • 可靠性 (Reliability) :確保數據無損壞、無丟失、無重復且按序到達。
  • 有序交付 (Ordered Delivery) :將數據按發送順序交付給應用層。
  • 字節流 (Byte Stream) :對應用程序來說,數據就像一個連續不斷的字節流,TCP 會負責將其拆分成合適大小的段 (segment) 進行傳輸。
  • 面向連接 (Connection-Oriented) :在通信前,必須通過“三次握手”建立連接;結束后,通過“四次揮手”斷開連接。

為了實現這些目標,TCP 精心設計了多種機制:

  • 確認 (Acknowledgement, ACK) :接收方每收到一個數據段,都會向發送方回送一個確認。
  • 序列號 (Sequence Number) :TCP 將每個字節都進行了編號。每個 TCP 段的頭部都攜帶了該段數據第一個字節的序列號,用于檢測丟包和重排亂序的數據。
  • 校驗和 (Checksum) :用于檢測數據在傳輸過程中是否被損壞。
  • 流量控制 (Flow Control) :防止發送方發送數據太快,壓垮接收方的緩沖區。
  • 擁塞控制 (Congestion Control) :從整個網絡的角度出發,調節發送速率,避免造成網絡擁塞。

ICMP:網絡層的“偵察兵”

還有一個協議我們必須提及: 互聯網控制消息協議 (Internet Control Message Protocol, ICMP) 。ICMP 是與 IP 緊密相關的控制協議:ICMP 報文被封裝在 IP 數據報中,屬于網絡層,用于向主機和路由器報告網絡層的錯誤并提供診斷功能(例如 ping 和 traceroute)。

我們常用的 ping 和 traceroute 命令,就是基于 ICMP 實現的。例如,ping 使用 ICMP 的“回顯請求 (Echo Request)”和“回顯應答 (Echo Reply)”消息。traceroute 則巧妙地利用了 ICMP 的“超時 (Time Exceeded)”和“端口不可達 (Port Unreachable)”消息來探測數據包經過的路由路徑。

可靠性的基石:TCP 連接管理

TCP 的可靠性始于其連接的建立與拆除過程。這個過程由一個精確定義的 有限狀態機 (Finite State Machine, FSM) 控制,確保了雙方狀態的同步。

三次握手:建立連接

TCP 通過三次報文交換來建立一個連接,這個過程被稱為 三向握手 (Three-Way Handshake) 。

Client                                     Server
   (state: CLOSED)                             (state: LISTEN)

       -- SYN (seq=x) ---------------->

   (state: SYN_SENT)
                                               (state: SYN_RCVD)
       <-- SYN, ACK (seq=y, ack=x+1) --

   (state: ESTABLISHED)
       -- ACK (seq=x+1, ack=y+1) ----->

                                               (state: ESTABLISHED)
  1. SYN :客戶端(主動開啟方)發送一個 SYN 報文段,其中包含一個隨機生成的 初始序列號 (Initial Sequence Number, ISN) ,我們稱之為 seq=x。此時,客戶端進入 SYN_SENT 狀態。
  2. SYN+ACK :服務器收到 SYN 后,也發送一個 SYN 報文段作為響應,其中包含了服務器自己的 ISN (seq=y),同時通過 ACK 報文段確認收到了客戶端的 SYN,確認號為 ack=x+1。此時,服務器進入 SYN_RCVD 狀態。
  3. ACK :客戶端收到服務器的 SYN+ACK 后,發送一個 ACK 報文段來確認服務器的 SYN,確認號為 ack=y+1。

至此,雙方都確認了對方的接收和發送能力,連接建立成功,可以開始傳輸數據。隨機化 ISN 的一個重要目的是為了防止舊連接中延遲的數據包干擾新建立的連接。

四次揮手:斷開連接

連接的拆除則需要四次報文交換,即 四向揮手 (Four-Way Handshake) 。

Client                                     Server
  (state: ESTABLISHED)                        (state: ESTABLISHED)

       -- FIN (seq=x) ----------------->
                                              (state: CLOSE_WAIT)
   (state: FIN_WAIT_1)
       <--------------- ACK (ack=x+1) --

   (state: FIN_WAIT_2)
                                              (sends remaining data...)

       <------------------ FIN (seq=y) --
                                              (state: LAST_ACK)
   (state: TIME_WAIT)
       -- ACK (ack=y+1) ---------------->
                                              (state: CLOSED)

   (waits 2*MSL)

   (state: CLOSED)
  1. FIN :當一方(比如客戶端)數據發送完畢,會發送一個 FIN 報文段,表示“我這邊沒數據要發了”。
  2. ACK :另一方(服務器)收到 FIN 后,回復一個 ACK,表示“知道了”。此時,從客戶端到服務器方向的連接關閉,但服務器仍然可以向客戶端發送數據。
  3. FIN :當服務器也發送完所有數據后,它會發送自己的 FIN 報文段。
  4. ACK :客戶端收到服務器的 FIN 后,回復最后一個 ACK。

在這里,主動關閉方(客戶端)在發送最后一個 ACK 后,會進入一個特殊的 TIME_WAIT 狀態,并等待兩倍的 最大段生存時間 (Maximum Segment Lifetime, MSL) 。這主要是為了兩個目的:

  1. 確保最后一個 ACK 報文能成功到達對方。如果這個 ACK 丟失,對方會重傳 FIN,客戶端仍能響應。
  2. 防止新連接復用相同的端口號時,受到舊連接中延遲報文的干擾。

TCP 的智慧:流量、窗口與擁塞控制

當 TCP 連接進入 ESTABLISHED 狀態后,真正的數據傳輸才剛剛開始。但這并非一個簡單的“你發我收”的過程。TCP 面臨兩大核心挑戰:

  1. 流量控制 (Flow Control) :如何確保發送方不會因為發送速度過快,而壓垮(overwhelm)接收方的處理能力?這是一個點對點的問題。
  2. 擁塞控制 (Congestion Control) :如何確保單個 TCP 連接不會因為發送速度過快,而壓垮整個網絡的承載能力,導致網絡擁塞甚至崩潰?這是一個全局性的問題。

為了優雅地解決這兩個問題,TCP 設計了其最核心的機制之一—— 滑動窗口 (Sliding Window) ,并在此基礎上衍生出兩套獨立的控制算法。

流量控制:照顧接收方的感受

流量控制的目標非常明確:匹配發送方的發送速率與接收方的接收速率。

想象一下你正在往一個杯子里倒水。如果倒得太快,水就會溢出。TCP 的接收方同樣有一個大小有限的緩沖區(receive buffer)。如果發送方發送的數據超出了這個緩沖區的容納能力,后續的數據包就會被丟棄,造成不必要的網絡開銷和重傳。

TCP 的解決方案是讓接收方明確地告訴發送方:“我還能接收多少數據”。

  • 接收窗口 (Receive Window, rwnd) :接收方會在其發送的每一個 TCP 報文段(無論是純 ACK 報文還是攜帶數據的報文)的頭部 Window 字段中,填入其當前接收緩沖區的剩余空間大小。這個值就是**接收窗口 (rwnd)**。
  • 發送方的響應 :發送方在收到這個 rwnd 值后,就會相應地調整自己的發送行為。它會確保任何時刻,網絡中“在途”(已發送但未收到確認)的數據總量,不能超過接收方通告的 rwnd 值。
Sender's View:

| ... | 已發送并確認 | 已發送但未確認 (在途數據) | 可用但未發送 | 不可用 | ... |
+------------------+-----------------------------+----------------+----------+
                   ^                             ^
                 上次確認                   最后發送
                   |<--  在途數據量 <= rwnd (接收窗口) -->|

零窗口問題與探測

一個特殊情況是,當接收方緩沖區滿了,它會通告一個 rwnd = 0 的窗口。此時發送方必須停止發送數據。但問題是,如果接收方后續處理了數據、騰出了空間,它發出的更新窗口的 ACK 報文在網絡中丟失了怎么辦?發送方將永遠等待下去,形成死鎖。

為了解決這個問題,TCP 設計了 零窗口探測 (Zero-Window Probe) 機制。當發送方收到零窗口通知后,會啟動一個計時器。計時器超時后,它會發送一個非常小的探測報文(通常只包含 1 字節數據),“戳”一下接收方。接收方在收到這個探測報文后,會回復一個包含當前 rwnd 的 ACK,這樣發送方就能獲知窗口是否已經更新,從而打破死鎖。

擁塞控制:照顧整個網絡的感受

流量控制解決了點對點的問題,但如果網絡路徑上的路由器處理能力有限,即使接收方 rwnd 很大,大量的并發數據流依然會導致網絡擁塞(congestion)。擁塞會導致路由器隊列溢出、大量丟包、延遲劇增,最終導致整個網絡吞吐量急劇下降,這種現象被稱為 擁塞崩潰 (Congestion Collapse) 。

擁塞控制的核心思想是:TCP 發送方通過觀察網絡狀態(主要是 丟包 ),來動態調整自己的發送速率。

  • 擁塞窗口 (Congestion Window, cwnd) :為此,TCP 在發送方內部維護了另一個狀態變量—— 擁塞窗口 (cwnd) 。它代表了發送方在收到 ACK 之前,可以向網絡中發送的最大數據量。cwnd 的大小不依賴于接收方,而是發送方根據網絡擁塞程度的 自我評估 。
  • 真正的發送窗口 :最終,一個 TCP 發送方在任意時刻的實際發送窗口,是 流量控制窗口和擁塞控制窗口中的較小者 。

EffectiveWindow = min(rwnd, cwnd) 這個簡單的公式優雅地將兩個控制機制結合在了一起。

  • TCP 擁塞控制的四大核心算法 :cwnd 的動態調整過程,主要由以下四個算法協同完成,它們共同構成了一套復雜的“舞蹈”,以適應不斷變化的網絡狀況。

1. 慢啟動 (Slow Start)

  • 目的 :在連接剛建立時,快速探測網絡的可用帶寬。
  • 行為 :cwnd 初始值很?。ㄍǔ?1 到 10 個 MSS,即最大報文段長度)。每收到一個 ACK,cwnd 就增加 1 個 MSS。這使得 cwnd 在每個 往返時間 (Round-Trip Time, RTT) 內近似翻倍,呈現 指數級增長 。
  • 結束 :當 cwnd 的大小超過一個預設的 慢啟動閾值 (Slow Start Threshold, ssthresh) 時,慢啟動階段結束,進入擁塞避免階段。

2. 擁塞避免 (Congestion Avoidance)

  • 目的 :當 cwnd 增長到一定程度(可能接近網絡容量)后,需要更謹慎地增加發送速率,避免造成擁塞。
  • 行為 :進入此階段后,cwnd 不再指數增長,而是 線性增長 。粗略地說,每個 RTT,cwnd 只增加 1 個 MSS。這種“加性增(Additive Increase)”的方式會溫和地探測更多可用帶寬。

3. 擁塞發生時的反應(快速重傳與快速恢復)

當擁塞發生時,網絡就會出現丟包。TCP 通過兩種方式感知丟包:

  • 超時重傳 (Timeout Retransmission) :這是最壞的情況,表示發送方在很長一段時間內沒有收到任何 ACK。TCP 會認為網絡發生了嚴重擁塞。
  • 3 個重復的 ACK (3 Duplicate ACKs) :當發送方連續收到 3 個或以上針對同一數據包的 ACK 時,它會認為這個數據包之后的一個數據包丟失了。這是一個相對溫和的擁塞信號。

針對這兩種情況,TCP 的反應是不同的:

  • 對于超時 :TCP 會采取激烈的“乘性減(Multiplicative Decrease)”策略。
  1. 將 ssthresh 設置為當前 cwnd 的一半。
  2. 將 cwnd 重置為初始值(例如 1 MSS)。
  3. 重新進入 慢啟動 階段。
  • 對于 3 個重復 ACK :TCP 啟用快速重傳 (Fast Retransmit) 和快速恢復 (Fast Recovery) 算法。
  1. 快速重傳 :不等超時,立即重傳那個被認為丟失的數據段。
  2. 快速恢復 :不將 cwnd 降為 1,因為收到重復 ACK 說明網絡中仍有數據包在正常傳輸。
  • 將 ssthresh 設置為當前 cwnd 的一半。
  • 將 cwnd 也設置為新的 ssthresh 值(而不是 1)。
  • 直接進入 擁塞避免 階段,跳過慢啟動。

總結:流量控制 vs. 擁塞控制

特性

流量控制 (Flow Control)

擁塞控制 (Congestion Control)

目標

保護 接收方 ,防止其緩沖區溢出

保護 網絡 ,防止網絡擁塞崩潰

控制方

由 接收方 驅動

由 發送方 驅動(基于對網絡的推斷)

核心機制

接收窗口 (rwnd),由接收方在 TCP 頭部通告

擁塞窗口 (cwnd),由發送方內部維護

問題范疇

端到端(點對點)問題

端到網絡再到端(系統性)問題

信號來源

接收方明確告知其可用緩沖空間

發送方通過 丟包(超時或重復 ACK)來推斷擁塞

通過這兩套機制的精妙配合,TCP 成功地在 ESTABLISHED 狀態下實現了既能充分利用網絡帶寬、又能避免壓垮接收方和整個網絡的智慧傳輸。

互聯網的設計哲學:端到端原則

為什么網絡協議會設計成今天這個樣子?背后有一個非常重要的指導思想—— 端到端原則 (End-to-End Principle) 。

這個原則有如下兩個版本。

弱端到端原則 (Weak End-to-End Principle)

其核心思想是,某些功能(如文件傳輸的正確性、安全性)只有在通信系統的 端點 (endpoint) ,也就是應用程序中,才能被完整且正確地實現。網絡中間的節點(如路由器)可以提供一些輔助功能作為性能優化(比如在無線鏈路層進行重傳),但應用程序 不能依賴 這些中間輔助來保證最終的正確性。

強端到端原則 (Strong End-to-End Principle)

這個版本更為激進,它認為網絡的職責應該盡可能簡單——就是高效、靈活地傳輸數據報。所有其他復雜功能都應該放在網絡的邊緣(端點)去實現。這樣做的好處是保持了網絡核心的簡潔和靈活性,能夠促進上層應用的創新。

數據的“指紋”:錯誤檢測機制

錯誤檢測 (Error Detection) 是闡述端到端原則最初的經典例子。以太網(鏈路層)使用強大的 CRC 校驗,TCP(傳輸層)使用自己的校驗和。但即便如此,數據在從路由器內存讀出寫入的過程中,仍可能發生錯誤。因此,為了確保萬無一失,像 BitTorrent 這樣的應用程序在接收完所有 TCP 數據后,依然會對每個數據塊進行一次哈希校驗。這完美體現了端到端原則——最終的正確性必須由端點應用來負責。

為了檢測數據在傳輸過程中是否被篡改,協議棧在不同層級使用了多種錯誤檢測算法。

  • 校驗和 (Checksum) :TCP/IP 協議棧廣泛使用的一種簡單算法。它通過對數據進行反碼求和來計算出一個值。它的優點是計算速度快,軟件實現容易,但缺點是錯誤檢測能力較弱。
  • 循環冗余校驗 (Cyclic Redundancy Code, CRC) :一種基于多項式除法的強大錯誤檢測碼。它的計算相對復雜,但硬件實現非常高效。CRC 能夠檢測出絕大多數常見的傳輸錯誤,因此被以太網、Wi-Fi 等鏈路層協議廣泛采用。
  • 消息認證碼 (Message Authentication Code, MAC) :這不僅是用于檢測隨機錯誤,更是為了 安全 。它通過將數據和一個共享的密鑰結合起來計算出一個“指紋”。只有擁有密鑰的通信雙方才能生成或驗證這個 MAC。任何對數據的惡意篡改都會導致 MAC 驗證失敗。我們熟知的 TLS/SSL 就使用了這種機制來保證數據完整性。

TCP 的生命周期:深入理解 TCP 狀態機

在上面的文章中,我們探討了 TCP 如何通過三次握手和四次揮手來建立和終止連接。但這些“握手”和“揮手”并非孤立事件,它們是一系列嚴謹狀態轉換的一部分。控制這一系列轉換的“規則手冊”,就是 TCP 狀態機 (TCP State Machine) 。

每一個 TCP 連接,從誕生到消亡,都嚴格遵循這個狀態機定義的路徑。它不是一個抽象的理論模型,而是實實在在運行在全球數十億設備中的代碼邏輯,是保證不同廠商、不同系統的設備能夠無誤溝通的基石。

理解 TCP 狀態機,不僅能幫助我們深入領會 TCP 的可靠性精髓,還能在網絡故障排查、程序性能優化時,為我們提供強有力的理論武器。例如,當你在服務器上用 netstat 命令看到大量處于 TIME_WAIT 或 CLOSE_WAIT 狀態的連接時,你就能立刻明白這意味著什么。

宏觀藍圖:TCP 狀態轉換圖

首先,讓我們看一下 TCP 狀態機的全貌。這張圖囊括了 TCP 連接生命周期中所有可能的狀態和轉換路徑。初看可能有些復雜,但別擔心,我們會一步步分解它。

圖片

我們將沿著最常見的路徑——連接建立、數據傳輸、連接關閉——來詳細解讀這個生命周期。

第一幕:連接建立(三次握手)

連接的建立分為主動方(通常是客戶端)和被動方(通常是服務器)。

被動方(服務器)的視角

CLOSED -> LISTEN

  • 觸發事件 : 應用程序在服務器上啟動,調用 listen() 系統調用,準備接受新的連接請求。
  • 狀態描述 : 此時服務器還沒有收到任何連接請求,只是“豎起耳朵”在監聽指定的端口。這是連接生命的起點。

LISTEN -> SYN_RCVD (SYN Received)

  • 觸發事件 : 服務器接收到一個來自客戶端的 SYN 報文段。
  • 采取動作 : 服務器回復一個 SYN+ACK 報文段,確認客戶端的 SYN 并發送自己的 SYN。
  • 狀態描述 : 服務器已經“收到同步信號”,并發送了響應,現在等待客戶端的最終確認。

SYN_RCVD -> ESTABLISHED (Established)

  • 觸發事件 : 服務器接收到客戶端針對其 SYN+ACK 的 ACK 報文段(三次握手的最后一步)。
  • 狀態描述 : 連接已成功建立!雙方現在可以自由地雙向傳輸數據。
主動方(客戶端)的視角

CLOSED -> SYN_SENT (SYN Sent)

  • 觸發事件 : 應用程序在客戶端上發起連接請求,例如調用 connect()。
  • 采取動作 : 客戶端發送一個 SYN 報文段給服務器。
  • 狀態描述 : 客戶端已經“發送了同步信號”,現在等待服務器的響應。

SYN_SENT -> ESTABLISHED

  • 觸發事件 : 客戶端接收到服務器的 SYN+ACK 報文段。
  • 采取動作 : 客戶端回復一個 ACK 報文段。
  • 狀態描述 : 在客戶端看來,發送完最后一個 ACK 后,連接就已建立。

第二幕:數據傳輸

ESTABLISHED

這是連接生命中最長、也是最有價值的階段。在這個狀態下,雙方的應用程序通過 send() 和 recv() 等系統調用,自由地交換數據。所有的數據傳輸、流量控制、擁塞控制都在這個穩定的狀態下進行。

示例 — 被動方收到 FIN -> CLOSE_WAIT(服務器端常見情況)

場景:客戶端正常關閉輸出方向(發送 FIN),服務器 recv() 返回 0(EOF),內核將套接字置為 CLOSE_WAIT,此時服務器的應用必須調用 close()(或 shutdown())來發送自己的 FIN,否則會一直處于 CLOSE_WAIT(常見泄漏 bug)。

/* server_close_wait_example.c
   編譯: gcc server_close_wait_example.c -o server
*/
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>

int main() {
    int srv = socket(AF_INET, SOCK_STREAM, 0);
    struct sockaddr_in addr = {0};
    addr.sin_family = AF_INET;
    addr.sin_port = htons(9090);
    addr.sin_addr.s_addr = INADDR_ANY;
    bind(srv, (struct sockaddr*)&addr, sizeof(addr));
    listen(srv, 1);

    int c = accept(srv, NULL, NULL);
    char buf[128];
    ssize_t n = recv(c, buf, sizeof(buf), 0);
    if (n == 0) {
        // <-- recv() 返回 0:對端已發 FIN,套接字進入 CLOSE_WAIT
        printf("peer closed write side (recv==0) -> socket is in CLOSE_WAIT\n");
        // 此處如果程序忘記 close(c),套接字將持續處于 CLOSE_WAIT
    } else if (n > 0) {
        write(STDOUT_FILENO, buf, n);
    }
    // 正確做法:處理完剩余數據后關閉連接,發送自己的 FIN -> LAST_ACK 或直接 close 完成終止
    fflush(stdout);
    sleep(10);
    close(c);
    close(srv);
    return 0;
}

關鍵點

  • recv() 返回 0 就是應用層收到“對方已經關閉發送方向”的信號,OS 狀態變成 CLOSE_WAIT。
  • 如果應用不 close()(或 shutdown(SHUT_WR)),會長期占用 CLOSE_WAIT,可能導致服務器資源耗盡。

在我的 MAC 上,使用 Control + D 發送 FIN ,一共三個終端:

終端1> ./server
終端3> lsof -nP -iTCP:9090
COMMAND   PID     USER   FD   TYPE             DEVICE SIZE/OFF NODE NAME
server  75553 piperliu    3u  IPv4 0x21a588ac71b533f4      0t0  TCP *:9090 (LISTEN)

終端2> nc 127.0.0.1 9090
終端3> lsof -nP -iTCP:9090
COMMAND   PID     USER   FD   TYPE             DEVICE SIZE/OFF NODE NAME
server  75553 piperliu    3u  IPv4 0x21a588ac71b533f4      0t0  TCP *:9090 (LISTEN)
server  75553 piperliu    4u  IPv4 0x8e56a7a57207245f      0t0  TCP 127.0.0.1:9090->127.0.0.1:51689 (ESTABLISHED)
nc      75970 piperliu    3u  IPv4 0x9268cd499a63ea18      0t0  TCP 127.0.0.1:51689->127.0.0.1:9090 (ESTABLISHED)

終端2> ^D  # Control + D
終端1> peer closed write side (recv==0) -> socket is in CLOSE_WAIT
終端3> lsof -nP -iTCP:9090
COMMAND   PID     USER   FD   TYPE             DEVICE SIZE/OFF NODE NAME
server  75553 piperliu    3u  IPv4 0x21a588ac71b533f4      0t0  TCP *:9090 (LISTEN)
server  75553 piperliu    4u  IPv4 0x8e56a7a57207245f      0t0  TCP 127.0.0.1:9090->127.0.0.1:51689 (CLOSE_WAIT)
nc      75970 piperliu    3u  IPv4 0x9268cd499a63ea18      0t0  TCP 127.0.0.1:51689->127.0.0.1:9090 (FIN_WAIT_2)
示例 — 主動方半關閉(client 發 FIN 后仍可讀):FIN_WAIT_1 -> FIN_WAIT_2 -> TIME_WAIT

場景:客戶端把發送方向關閉(shutdown(fd, SHUT_WR))但繼續讀服務器返回的數據;這是半關閉(half-close)的典型用法,適合客戶端發送完請求但仍需讀取結果的協議(HTTP/1.0 以前的部分場景)。

/* client_half_close_example.c
   編譯: gcc client_half_close_example.c -o client
*/
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>

int main() {
    int s = socket(AF_INET, SOCK_STREAM, 0);
    struct sockaddr_in srv = {0};
    srv.sin_family = AF_INET;
    srv.sin_port = htons(9090);
    inet_pton(AF_INET, "127.0.0.1", &srv.sin_addr);

    connect(s, (struct sockaddr*)&srv, sizeof(srv));

    const char *req = "hello, server\n";
    send(s, req, strlen(req), 0);       // 發送數據
    shutdown(s, SHUT_WR);               // <-- 發送 FIN(進入 FIN_WAIT_1)
                                        // 一旦收到對方 ACK,會進入 FIN_WAIT_2
    // 仍然可以 recv() 直到 peer 發 FIN(然后我們回復最后的 ACK;進入 TIME_WAIT)
    char buf[256];
    ssize_t n;
    while ((n = recv(s, buf, sizeof(buf), 0)) > 0) {
        write(STDOUT_FILENO, buf, n);
    }
    // 當對端發 FIN 時,recv 返回 0,內核會把我們放到 TIME_WAIT(在完整握手序列中)
    close(s);
    return 0;
}

關鍵點

  • shutdown(SHUT_WR):應用告知內核“我不會再發數據了”,內核發送 FIN(到 FIN_WAIT_1)。
  • 在 FIN_WAIT_2 階段還能 recv(),直到對方關閉其發送方向并觸發 TIME_WAIT。
  • TIME_WAIT 的存在有兩個目的:保證最后 ACK 可重傳 & 防止舊數據干擾新連接(2 * MSL)。

第三幕:連接關閉(四次揮手)

與連接建立類似,關閉連接也分為主動方和被動方。任何一方都可以是主動關閉方。

主動關閉方(例如,客戶端)的視角

ESTABLISHED -> FIN_WAIT_1

  • 觸發事件 : 客戶端應用程序調用 close(),決定關閉連接。
  • 采取動作 : 客戶端發送一個 FIN 報文段,表示“我的數據已經發完了”。
  • 狀態描述 : 客戶端進入等待狀態,等待服務器對其 FIN 的確認。

FIN_WAIT_1 -> FIN_WAIT_2

  • 觸發事件 : 客戶端收到了服務器對其 FIN 的 ACK。
  • 狀態描述 : 此時,從客戶端到服務器方向的連接已經關閉,這被稱為 半關閉 (half-close) 狀態??蛻舳瞬荒茉侔l送數據,但仍然可以接收來自服務器的數據??蛻舳爽F在等待服務器發送它自己的 FIN。

FIN_WAIT_2 -> TIME_WAIT

  • 觸發事件 : 客戶端終于收到了服務器的 FIN 報文段。
  • 采取動作 : 客戶端回復最后一個 ACK。
  • 狀態描述 : 客戶端進入 TIME_WAIT 狀態。這是整個狀態機中最關鍵和最常被問到的狀態之一。
TIME_WAIT:優雅退場的藝術

TIME_WAIT 狀態,也稱為 2MSL 等待狀態 ,其存在有兩個至關重要的原因:

  1. 保證可靠的關閉 : 為了確保最后一個 ACK 能夠成功到達服務器。如果這個 ACK 在網絡中丟失,服務器將收不到確認,會超時重傳它的 FIN。此時,處于 TIME_WAIT 狀態的客戶端仍然可以接收到這個重傳的 FIN 并重新發送 ACK,從而保證服務器能夠正常關閉。
  2. 防止舊連接的干擾 : 一個連接由一個四元組(源IP,源端口,目的IP,目的端口)唯一確定。在 TIME_WAIT 狀態持續的 2倍最大段生存時間 (2 * MSL) 內,這個四元組不能被用于建立新的連接。這可以防止網絡中可能存在的、來自舊連接的延遲數據包(“迷路”的報文)被新連接錯誤地接收,從而保證了新連接的純凈。
被動關閉方(例如,服務器)的視角

ESTABLISHED -> CLOSE_WAIT

  • 觸發事件 : 服務器接收到客戶端的 FIN 報文段。
  • 采取動作 : 服務器回復一個 ACK,并通知上層應用程序:對方已經關閉了連接。
  • 狀態描述 : 服務器進入 CLOSE_WAIT 狀態。這個狀態的含義是“等待應用程序關閉連接”。如果一個服務器上有大量連接處于 CLOSE_WAIT 狀態,通常意味著應用程序存在 bug——它沒有在接收到連接關閉信號后,及時調用 close() 來關閉自己的寫通道。

CLOSE_WAIT -> LAST_ACK

  • 觸發事件 : 服務器端的應用程序在處理完剩余數據后,也調用 close()。
  • 采取動作 : 服務器發送自己的 FIN 報文段。
  • 狀態描述 : 服務器等待來自客戶端的最后一次 ACK。

LAST_ACK -> CLOSED

  • 觸發事件 : 服務器收到了來自客戶端的最后一個 ACK。
  • 狀態描述 : 連接徹底關閉,資源被釋放。
示例 — 同時關閉 -> CLOSING

場景:雙方幾乎同時調用 close()(或都先 shutdown(SHUT_WR) 然后 send FIN),就可能出現 CLOSING 狀態:雙方都發送了 FIN,一方收到了對方的 FIN,但尚未收到對方對自己 FIN 的 ACK(罕見但可能發生)。

下面是兩端幾乎同時 shutdown(SHUT_WR) 的示意代碼(實測難以完全同步,示例用于說明意圖):

/* pseudo-simultaneous-close.c (示意) */
    // A: send FIN
    shutdown(sockA, SHUT_WR);   // A -> FIN
    // B: almost same time
    shutdown(sockB, SHUT_WR);   // B -> FIN
    // 如果 A 在等待來自 B 的 ACK 時收到了 B 的 FIN -> A 進入 CLOSING

關鍵點

  • CLOSING 是短暫、中介的狀態,只在特定并發關閉的時序下出現。
  • 大多數代碼無需專門處理 CLOSING,只要按正確順序 close()/shutdown() 即可。
示例 — RST(abortive close):如何讓連接立刻變為 CLOSED(“暴力關閉”)并產生 RST

場景:有時我們想要立即釋放資源,不想等待內核緩沖區或四次揮手超時(例如發生嚴重錯誤)??梢酝ㄟ^ SO_LINGER 配合 close() 強制發送 RST(中斷連接)。

/* abortive_close.c */
#include <sys/socket.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>

void abortive_close(int fd) {
    struct linger ling;
    ling.l_onoff = 1;
    ling.l_linger = 0; // 啟用 linger, linger=0 表示 close() 立即發送 RST
    setsockopt(fd, SOL_SOCKET, SO_LINGER, &ling, sizeof(ling));
    close(fd); // 立刻產生 RST,連接對端會立即收到 reset 并進入 CLOSED
}

關鍵點

  • 使用 SO_LINGER 且 l_linger == 0 時 close() 觸發 RST,不會按正常 FIN 順序。
  • RST 會立即釋放雙方資源,但也可能導致對端發生錯誤(例如 ECONNRESET 或 SIGPIPE)。
示例 — TIME_WAIT 與端口重用:SO_REUSEADDR / SO_REUSEPORT 行為提示

當一個 socket 在 TIME_WAIT 中,通常不能立即被同一四元組重用。為了解決服務端快速重啟的問題,常設 SO_REUSEADDR(注意:這不是萬能鑰匙,語義依實現而異)。

/* server_reuseaddr.c 片段 */
int srv = socket(AF_INET, SOCK_STREAM, 0);
int on = 1;
setsockopt(srv, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
bind(srv, (struct sockaddr*)&addr, sizeof(addr));
listen(srv, 128);

注意

  • SO_REUSEADDR 允許 bind 到處于 TIME_WAIT 的端口上(在很多系統上可以),但并不改變 TIME_WAIT 的存在 — 它只是影響 bind 行為。
  • 在高并發短連接服務中,也可以使用端口池或 ephemeral port 的方式減輕 TIME_WAIT 壓力(或使用負載均衡把連接分散到多臺后端)。

特殊情況

  • CLOSING 狀態 : 一個比較罕見的狀態。它發生在雙方幾乎同時發送 FIN 的情況下。例如,A 發送 FIN 后,在等待 B 的 ACK 期間,卻收到了 B 發來的 FIN。此時,A 就會進入 CLOSING 狀態,等待 B 對自己 FIN 的 ACK。
  • RST (Reset) : 除了優雅的 FIN 揮手,TCP 還有一種“暴力”的關閉方式——發送 RST 報文段。這會直接中斷連接,使狀態立即跳轉到 CLOSED。常見于向一個未監聽的端口發起連接,或是一方異常退出時。
CLOSE_WAIT 泄漏示例
# netstat -tn | grep CLOSE_WAIT | wc -l
350

如果你在服務器上看到大量 CLOSE_WAIT,通常說明應用端未及時調用 close()。用 lsof -i :port 或 ss -tanp | grep CLOSE_WAIT 找到對應 PID,檢查是否忘記在處理完 recv() == 0 后關閉描述符(或在異常路徑中漏掉 close)。

TIME_WAIT 普遍存在
# netstat -an | grep TIME_WAIT | wc -l
1200

TIME_WAIT 數量大通常是短連接頻繁建立/關閉的天然結果,不是內核異常??煽紤]:

  • 使用長連接(keep-alive)。
  • 復用連接(連接池)。
  • 如果合理,可調整內核 tcp 參數(例如 Linux 的 tcp_tw_reuse、tcp_fin_timeout),但生產環境要小心。
如果 send 后收到 SIGPIPE
  • 這通常發生于對端已 close(或 RST)并且應用繼續 write()。解決:忽略 SIGPIPE(signal(SIGPIPE, SIG_IGN))或在 send() 中使用 MSG_NOSIGNAL。

小結:把 C 代碼的行為映射回狀態機

  • connect()(客戶端) -> SYN_SENT;收到 SYN+ACK 并 ACK -> ESTABLISHED。
  • listen() -> LISTEN;accept() 后收到 SYN -> SYN_RCVD -> ESTABLISHED。
  • shutdown(fd, SHUT_WR) 或 close()(發送方) -> 內核發送 FIN -> FIN_WAIT_1。
  • recv() == 0(被動方) -> 收到對端 FIN,內核把 socket 標記為 CLOSE_WAIT;必須 close() 才會發送自己的 FIN。
  • SO_LINGER with l_linger=0 + close() -> 發送 RST,立即 CLOSED(暴力釋放)。
  • 同時 FIN -> 可能出現 CLOSING(罕見)。
  • 等待 2 * MSL 后 TIME_WAIT -> CLOSED(保證最后 ACK 可重傳 & 防止舊報文干擾)。
責任編輯:武曉燕 來源: Piper蛋窩
相關推薦

2025-08-29 01:11:00

2025-09-01 04:00:55

2025-08-26 02:50:00

2025-09-01 07:08:43

2025-09-01 01:22:00

2025-08-27 06:29:45

2025-08-29 06:24:37

2010-06-14 18:51:05

計算機網絡協議

2020-04-15 08:00:00

計算機網絡通信設備通信協議

2013-10-28 10:06:26

HTTP協議網絡協議

2010-09-08 20:45:31

計算機網絡協議

2010-06-12 16:56:37

2010-09-08 20:42:09

計算機網絡協議

2010-09-02 16:02:45

計算機網絡協議

2013-05-14 13:02:17

計算機網絡基礎協議

2013-03-08 12:51:03

計算機網絡基礎協議DHCP

2010-06-12 16:51:54

計算機網絡通信協議

2015-05-28 11:09:00

2010-06-14 18:54:57

計算機網絡協議

2010-09-08 21:01:44

計算機網絡協議
點贊
收藏

51CTO技術棧公眾號

久久精品资源| 丁香六月天婷婷| 久久中文字幕av| 欧美一区二区三区四区五区| 日韩在线视频在线| 亚洲人午夜射精精品日韩| 美女视频黄 久久| 欧美人与性动交| xxx在线播放| 日韩不卡在线视频| 色视频一区二区| 一区二区三区三区在线| 人妻妺妺窝人体色www聚色窝 | 这里只有视频精品| 无码人妻少妇色欲av一区二区| а√在线天堂官网| 国产精品夫妻自拍| 精品综合久久| www.色呦呦| 日日夜夜免费精品视频| 色综合色综合久久综合频道88| av男人的天堂av| 嗯用力啊快一点好舒服小柔久久| 在线视频亚洲一区| 波多野结衣之无限发射| 一区二区三区视频在线观看视频| av影院午夜一区| 91久久久久久| 国产精品免费无遮挡无码永久视频| 欧美1区3d| 色婷婷久久一区二区| 日本aaa视频| 97久久超碰| 欧美一区二区三区视频| 中文字幕第36页| 中国色在线日|韩| 亚洲大片免费看| 国风产精品一区二区| 91大神xh98hx在线播放| 久久久久久久久久美女| 国产日韩三区| 亚洲欧美激情国产综合久久久| 久久 天天综合| 国产精品视频久久| 天堂网中文字幕| 亚洲欧美成人| 欧美一区二区三区……| 亚洲男人第一av| 亚洲第一伊人| 久久久久免费视频| 免费一级片视频| 欧美va天堂| 欧美成人午夜激情在线| 国产精品国产三级国产传播| 清纯唯美亚洲综合一区| 国产亚洲欧美视频| 卡一卡二卡三在线观看| 日本大胆欧美| 色婷婷成人综合| 少妇被躁爽到高潮无码文| 在线电影一区二区| 美女福利视频一区| 欧美成人片在线观看| 欧美日韩国产探花| 久久免费国产精品1| 久久精品女人毛片国产| 亚洲美女毛片| 欧美中文在线免费| 天天综合久久综合| 久久国产视频网| 91免费观看| 欧美一区二区黄片| 99精品视频在线观看| 蜜桃导航-精品导航| 成人高清免费在线播放| 欧美激情在线一区二区| 亚洲午夜精品久久久中文影院av| 老司机精品视频在线观看6| 亚洲美女屁股眼交| 久激情内射婷内射蜜桃| 日本电影欧美片| 欧美人狂配大交3d怪物一区| 麻豆精品国产传媒| 欧美日韩导航| 色噜噜国产精品视频一区二区 | 国产精品欧美日韩一区二区| 亚洲熟女乱色一区二区三区久久久| 黄网站免费久久| 俄罗斯精品一区二区三区| 天天操天天爱天天干| 国产亚洲一区二区三区| 免费观看黄色大片| 17videosex性欧美| 欧美三级视频在线播放| 性xxxxxxxxx| 欧美人与牛zoz0性行为| 久久夜色精品国产亚洲aⅴ| 国产在线观看免费视频今夜| 日韩不卡一二三区| 999国内精品视频在线| 欧美日韩国产综合视频| 亚洲色欲色欲www| 国产免费成人在线| 91麻豆精品| 精品一区二区亚洲| 午夜爽爽爽男女免费观看| 亚洲每日在线| 91超碰在线电影| 韩国三级在线观看久| 一区二区三区日韩精品| wwwwww.色| 欧美电影完整版在线观看| zzijzzij亚洲日本成熟少妇| 51国产偷自视频区视频| 激情综合色丁香一区二区| 久久精品一二三区| 日韩精品分区| 欧美猛男男办公室激情| jizz中文字幕| av不卡在线| 91蜜桃网站免费观看| 天堂中文8资源在线8| 狠狠综合久久av一区二区小说| a级大片免费看| 久久在线电影| 国产精品黄页免费高清在线观看| 搡老岳熟女国产熟妇| 亚洲欧美另类小说视频| 日本 片 成人 在线| 九九久久精品| 欧美一级免费看| 日本激情视频网站| 一区二区三区色| 男插女视频网站| 天天精品视频| 国产裸体写真av一区二区| 国产在线色视频| 欧美午夜激情小视频| 中文字幕乱码一区| 亚洲人体大胆视频| 国产精品日韩一区二区免费视频| 日本中文字幕在线视频| 在线观看视频一区二区| 亚洲精品一区二区三区影院忠贞| 香蕉久久国产| 乱色588欧美| 中国字幕a在线看韩国电影| 日韩成人小视频| 西西44rtwww国产精品| 成人福利电影精品一区二区在线观看| 男人的天堂avav| 亚洲精品观看| 国内外成人免费激情在线视频网站| 精品久久久免费视频| 一区二区三区在线免费视频 | 99r国产精品| 免费看日本毛片| 亚洲美女15p| 国产第一区电影| √天堂资源地址在线官网| 欧美三电影在线| 国产高潮流白浆| 成人黄色小视频在线观看| 日韩国产欧美亚洲| 国产精品一在线观看| 国产精品久久网| 麻豆视频在线免费观看| 日韩视频在线你懂得| 国产精彩视频在线观看| 97久久超碰精品国产| 可以在线看的黄色网址| 成人情趣视频| 91久久久一线二线三线品牌| av中文字幕在线看| 亚洲欧洲成视频免费观看| 日韩精品在线一区二区三区| 中文字幕一区二区三中文字幕| 女王人厕视频2ⅴk| 日韩一级不卡| 亚洲第一导航| 无人区乱码一区二区三区| 7m第一福利500精品视频| 阿v免费在线观看| 欧美一区二区免费观在线| 香蕉免费毛片视频| 国产欧美1区2区3区| 91精产国品一二三| 久久精品人人| 天天干天天色天天爽| 精品伊人久久久| 国产欧美日韩精品丝袜高跟鞋| 最近中文字幕免费mv2018在线| 亚洲国产精品久久久久久| 免费一级a毛片| 一区二区三区四区不卡在线| 亚洲区自拍偷拍| 国产精品18久久久久久vr| 狠狠97人人婷婷五月| 欧美mv日韩| 久久精品一二三区| 久久wwww| 国产精品视频一| 69av成人| 欧美老女人在线视频| 加勒比一区二区三区在线| 欧美一级二级三级蜜桃| 国产一级片免费视频| 婷婷亚洲久悠悠色悠在线播放| 国产中文字幕久久| 久久久亚洲午夜电影| 伊人久久久久久久久| 麻豆国产精品一区二区三区| 欧美丰满熟妇bbbbbb百度| 亚洲成人三区| 日韩欧美亚洲日产国| 久久夜色电影| 亚洲自拍另类欧美丝袜| 成人全视频在线观看在线播放高清| 久久人人爽人人爽人人片av高请| 欧美猛烈性xbxbxbxb| 亚洲天天在线日亚洲洲精| 天天爱天天干天天操| 日韩精品自拍偷拍| 国产精品乱码一区二区| 欧美在线观看一二区| 九九九在线观看| 亚洲高清免费一级二级三级| 欧美成人精品欧美一| 亚洲日本乱码在线观看| 成人无码精品1区2区3区免费看| 99精品欧美一区二区三区综合在线| 日韩精品在线播放视频| 韩日精品视频一区| 亚洲欧洲日本精品| 青青草视频一区| 亚洲激情在线观看视频| 三级亚洲高清视频| 日本wwww视频| 免播放器亚洲| 国产91在线免费| 国产日韩欧美三区| 天堂…中文在线最新版在线| 亚洲电影av| 亚洲 自拍 另类小说综合图区| 欧美亚洲不卡| www.国产在线播放| 欧美日韩国产欧| 青青草精品视频在线| 99精品视频免费观看视频| 久艹视频在线免费观看| 99国产精品视频免费观看一公开| 你真棒插曲来救救我在线观看| 影音国产精品| 欧美成人一区二区在线观看| 国产精品亚洲欧美| 激情婷婷综合网| 久久精品91| 天堂在线资源视频| 久草精品在线观看| 国产精品久久久久野外| 成人avav影音| aa片在线观看视频在线播放| 久久免费偷拍视频| 卡一卡二卡三在线观看| 中文字幕字幕中文在线中不卡视频| 久久精品一区二区三区四区五区| 一区二区视频免费在线观看| 亚洲精品77777| 日本精品一级二级| 一区二区三区黄色片| 日韩免费电影网站| 天天操天天操天天操| 国产一区二区日韩| 黄视频在线观看网站| 欧美激情视频免费观看| 92国产精品| 成人xxxx视频| 久草在线综合| 欧洲精品久久| 亚洲国产精品91| 青青青免费在线| 日本在线播放一区二区三区| 美女被艹视频网站| 26uuu亚洲婷婷狠狠天堂| 国产一二三四视频| 一区二区三区在线不卡| 亚洲 欧美 成人| 91精品国产综合久久福利| 欧美一区二区三区激情| 日日狠狠久久偷偷四色综合免费| 一色桃子av在线| 国产极品jizzhd欧美| 欧美久久亚洲| 欧美日韩在线精品| 欧美久色视频| 亚洲黄色小视频在线观看| 国产.欧美.日韩| 女人裸体性做爰全过| 亚洲一二三四久久| 亚洲系列在线观看| 亚洲精品国产精品乱码不99按摩 | 亚洲人成网77777色在线播放| 亚洲精品在线免费| 亚洲深夜激情| 91网址在线观看精品| 久久久天堂av| 国产精品999久久久| 欧美精品乱码久久久久久按摩| 亚洲AV成人无码一二三区在线| 久久精品国产69国产精品亚洲| 国产调教在线| 3d蒂法精品啪啪一区二区免费| 久久最新网址| 免费欧美一级视频| 国产成人亚洲综合a∨猫咪| 波多野结衣一二三四区| 欧美日韩精品在线| 国产成人三级一区二区在线观看一| 国产一区二区三区18| 大桥未久在线视频| 91亚色免费| 一精品久久久| 日韩av卡一卡二| 久久久久久久av麻豆果冻| 久久久精品视频免费| 91精品国产欧美一区二区18| 99riav在线| 日韩美女主播视频| 亚洲免费专区| 日本福利视频在线| 北条麻妃一区二区三区| 清纯粉嫩极品夜夜嗨av| 91精品国产综合久久婷婷香蕉| 国产在线视频网| 国产精品av免费在线观看| 网红女主播少妇精品视频| 欧美一级视频免费看| www.欧美亚洲| 久久久久久久久久免费视频| 欧美精品一区二区三区很污很色的 | 在线高清欧美| 日韩最新中文字幕| 激情小说亚洲一区| 黄色录像免费观看| 宅男噜噜噜66一区二区66| 黄色网页在线播放| 成人亲热视频网站| 亚洲深深色噜噜狠狠爱网站| 伊人国产精品视频| 亚洲柠檬福利资源导航| 精品久久久久成人码免费动漫| 欧美国产日韩一区二区| 黄色欧美网站| 俄罗斯av网站| 国产人伦精品一区二区| 亚洲一级片免费看| 久久精品国产一区| 日韩视频一二区| 性欧美大战久久久久久久| 91网站视频在线观看| av一级在线观看| 日韩网站在线观看| 精品视频一二| 欧美二区在线视频| 久久久一区二区三区捆绑**| 中国老头性行为xxxx| 久久久成人精品视频| 成人激情自拍| 十八禁视频网站在线观看| 国产精品欧美经典| 99久久国产免费| 国产91精品久久久久久久| 经典一区二区| 亚洲天堂伊人网| 亚洲在线视频网站| 久久久久国产精品嫩草影院| 国产精品自拍偷拍| 欧美极品一区二区三区| 日本一区二区三区网站| 欧美三级欧美一级| 日韩影视在线| 午夜精品美女久久久久av福利| 国产乱码精品一区二区三区av| 99视频在线看| 色视频www在线播放国产成人| 91精品国产自产在线丝袜啪| 国产成人久久婷婷精品流白浆| 国产精品二三区| 亚洲欧美丝袜中文综合| 国产精品午夜一区二区欲梦| 影音国产精品| 少妇高潮一区二区三区喷水| 亚洲韩国欧洲国产日产av| 国产美女久久| 日本网站免费在线观看| 成人免费一区二区三区视频| 天天操天天干天天| 亚洲一区二区三区视频播放| 亚洲欧美日韩国产一区| 日韩va亚洲va欧美va清高|