久久精品国产精品国产精品污,男人扒开添女人下部免费视频,一级国产69式性姿势免费视频,夜鲁夜鲁很鲁在线视频 视频,欧美丰满少妇一区二区三区,国产偷国产偷亚洲高清人乐享,中文 在线 日韩 亚洲 欧美,熟妇人妻无乱码中文字幕真矢织江,一区二区三区人妻制服国产

歡迎訪問 生活随笔!

生活随笔

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

编程问答

TCP/IP协议栈之LwIP(六)---网络传输管理之TCP协议

發(fā)布時間:2024/3/7 编程问答 47 豆豆
生活随笔 收集整理的這篇文章主要介紹了 TCP/IP协议栈之LwIP(六)---网络传输管理之TCP协议 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

文章目錄

  • 一、TCP協(xié)議簡介
    • 1.1 正面確認與超時重傳
    • 1.2 連接管理與保活機制
    • 1.3 滑動窗口與緩沖機制
    • 1.4 流量控制與擁塞控制
    • 1.5 提高網(wǎng)絡(luò)利用率的其他機制
  • 二、TCP協(xié)議實現(xiàn)
    • 2.1 TCP報文格式
    • 2.2 TCP數(shù)據(jù)報描述
    • 2.3 TCP狀態(tài)機
    • 2.4 TCP數(shù)據(jù)報操作
      • 2.4.1 TCP報文段輸出處理
      • 2.4.2 TCP報文段輸入處理
      • 2.4.3 TCP定時器
    • 2.5 SYN攻擊
  • 更多文章

一、TCP協(xié)議簡介

在傳輸層協(xié)議中,UDP是一種沒有復雜控制,提供面向無連接通信服務的一種協(xié)議,它將部分控制轉(zhuǎn)移給應用程序去處理,自己卻只提供作為傳輸層協(xié)議的最基本功能。與UDP不同,TCP則是對傳輸、發(fā)送、通信等進行控制的協(xié)議。

TCP(Transmission Control Protocol)與UDP(User Datagram Protocol)的區(qū)別相當大,它充分實現(xiàn)了數(shù)據(jù)傳輸時各種控制功能,可以進行丟包時的重發(fā)控制,還可以對次序亂掉的分包進行順序控制,而這些在UDP中都沒有。此外,TCP作為一種面向有連接的協(xié)議,只有在確認通信對端存在時才會發(fā)送數(shù)據(jù),從而可以控制通信流量的浪費。根據(jù)TCP的這些機制,在IP這種無連接的網(wǎng)絡(luò)上也能夠?qū)崿F(xiàn)高可靠的通信。

為了通過IP數(shù)據(jù)報實現(xiàn)可靠性傳輸,需要考慮很多問題,例如數(shù)據(jù)的破壞、丟包、重復以及分片順序混亂等問題。TCP通過校驗和、序列號、確認應答、重發(fā)控制、連接管理、窗口控制等機制實現(xiàn)可靠性傳輸。

1.1 正面確認與超時重傳

在TCP中,當發(fā)送端的數(shù)據(jù)到達接收主機時,接收端主機會返回一個已收到消息的通知,這個消息叫做確認應答(ACK)。TCP通過肯定的確認應答實現(xiàn)可靠的數(shù)據(jù)傳輸,當發(fā)送端將數(shù)據(jù)發(fā)出之后會等待對端的確認應答,如果有確認應答說明數(shù)據(jù)已經(jīng)成功到達對端,反之則說明數(shù)據(jù)丟失的可能性很大。在一定時間內(nèi)沒有等到確認應答,發(fā)送端就可以認為數(shù)據(jù)已經(jīng)丟失并進行重發(fā),由此即使產(chǎn)生了丟包仍能保證數(shù)據(jù)能夠到達對端,實現(xiàn)可靠傳輸。

未收到確認應答并不意味著數(shù)據(jù)一定丟失,也有可能是數(shù)據(jù)對方已經(jīng)收到,只是返回的確認應答在途中丟失,這種情況也會導致發(fā)送到因沒有收到確認應答而認為數(shù)據(jù)沒有到達目的地,從而進行重新發(fā)送。也有可能因為一些其他原因?qū)е麓_認應答延遲到達,在源主機重發(fā)數(shù)據(jù)以后才到達的情況也屢見不鮮。此時,源發(fā)送主機只要按照機制重發(fā)數(shù)據(jù)即可,但目標主機會反復收到相同的數(shù)據(jù),為了對上層應用提供可靠的傳輸必須放棄重復的數(shù)據(jù)。為此,就必須引入一種機制,它能夠識別是否已經(jīng)接收數(shù)據(jù),又能夠判斷是否需要接收。

上述這些確認應答處理、重傳控制以及重復控制等功能都可以通過序列號實現(xiàn)。序列號是按順序給發(fā)送數(shù)據(jù)的每一個字節(jié)都標上號碼的編號。接收端查詢接收數(shù)據(jù)TCP首部中的序列號和數(shù)據(jù)的長度,將自己下一步應該接收的序號作為確認應答返送回去,這樣通過序列號和確認應答號,TCP可以實現(xiàn)可靠傳輸,整個過程如下圖所示:

前面說到發(fā)送端在一定時間內(nèi)沒有等到確認應答就會進行數(shù)據(jù)重發(fā),在重發(fā)數(shù)據(jù)之前等待確認應答到來的特定時間間隔就叫重發(fā)超時。那么這個重發(fā)超時的具體時間長度又是如何確定的呢?

最理想的是,找到一個最小時間,它能保證確認應答一定能在這個時間內(nèi)返回,然而這個時間長短隨著數(shù)據(jù)包途經(jīng)的網(wǎng)絡(luò)環(huán)境的不同而有所變化,例如跟網(wǎng)絡(luò)的距離、帶寬、擁堵程度等都有關(guān)系。TCP要求不論處在何種網(wǎng)絡(luò)環(huán)境下都要提供高性能通信,并且不論網(wǎng)絡(luò)擁堵情況發(fā)生何種變化,都必須保持這一特性。為此,它在每次發(fā)包時都會計算往返時間及其偏差(往返時間RTT估計)。將這個往返時間和偏差相加,重發(fā)超時時間就是比這個總和要稍大一點的值。往返時間的計算與重發(fā)超時的時間推移過程如下圖所示:


在BSD的Unix以及Windows系統(tǒng)中,超時都以0.5秒為單位進行控制,因此重發(fā)超時都是0.5秒的整數(shù)倍。不過由于最初的數(shù)據(jù)包還不知道往返時間,所以其重發(fā)超時一般設(shè)置為6秒左右。

數(shù)據(jù)被重發(fā)之后若還收不到確認應答,則進行再次發(fā)送,此時等待確認應答的時間將會以2倍、4倍的指數(shù)函數(shù)延長。但數(shù)據(jù)也不會無限、反復的重發(fā),達到一定重發(fā)次數(shù)后,如果仍沒有任何確認應答返回,就會判斷為網(wǎng)絡(luò)或?qū)Χ酥鳈C發(fā)生了異常,強制關(guān)閉連接,并通知應用通信異常強行終止。

1.2 連接管理與保活機制

TCP提供面向有連接的通信傳輸,通信雙方在有效數(shù)據(jù)交互之前,必須建立穩(wěn)定的連接,同時初始化與連接相關(guān)的數(shù)據(jù)交互、控制信息。UDP是一種面向無連接的通信協(xié)議,因此不檢查對端是否可以通信,直接將UDP數(shù)據(jù)包發(fā)送出去。TCP與此相反,它會在數(shù)據(jù)通信之前通過TCP首部發(fā)送一個SYN包作為建立連接的請求等待確認應答。如果對端發(fā)來確認應答,則認為可以進行數(shù)據(jù)通信,如果對端的確認應答未能到達,就不會進行數(shù)據(jù)通信。在TCP中,通信雙方按照客戶端–服務器模型建立連接的過程稱為“三次握手”過程,圖示如下:

TCP提供全雙工的連接服務,連接的任何一方都可以關(guān)閉某個方向上的數(shù)據(jù)傳輸,當一個方向上的連接被終止時,另一個方向還可以繼續(xù)發(fā)送數(shù)據(jù)。當發(fā)送數(shù)據(jù)的一方完成數(shù)據(jù)發(fā)送任務后,它就可以發(fā)送一個FIN標志置1的握手包來終止這個方向上的連接,當另一端收到這個FIN包時,它必須通知應用層另一端已經(jīng)終止了該方向的數(shù)據(jù)傳輸。發(fā)送FIN通常是應用層進行關(guān)閉的結(jié)果,收到一個FIN意味著在這個方向上已經(jīng)沒有數(shù)據(jù)流動,但在另一個方向上仍能發(fā)送數(shù)據(jù),此時的連接處于半關(guān)閉狀態(tài)。要完全關(guān)閉一條連接,需要四次報文交互的過程,稱連接斷開過程為“四次握手”過程,圖示如下:

在建立TCP連接的同時,也可以確定發(fā)送數(shù)據(jù)包的單位,也即最大報文段長度(MSS:Maximum Segment Size),最理想的情況是,MSS正好是IP中不會被分片處理的最大數(shù)據(jù)長度。

TCP在傳送大量數(shù)據(jù)時,是以MSS的大小將數(shù)據(jù)進行分割傳送的,進行重發(fā)時也是以MSS為單位的。MSS是在三次握手的時候,在兩端主機之間被計算得出的,兩端的主機在發(fā)送建立連接的請求時,會在TCP首部中寫入MSS選項,告訴對方自己的接口能夠適應的MSS的大小,然后會在兩者之間選擇一個較小的值投入使用,整個過程圖示如下:

如果一個TCP連接已處于穩(wěn)定狀態(tài),而同時雙方都沒有數(shù)據(jù)需要發(fā)送,則在這個連接之間不會再有任何信息交互。然而在很多情況下,連接雙方都希望知道對方是否仍處于活動狀態(tài),TCP提供了保活定時器來實現(xiàn)這種檢測功能。

TCP必須為服務器應用程序提供保活功能,服務器通常希望知道客戶主機的運行狀況,從而可以合理分配客戶占用的資源。如果某條連接在兩個小時內(nèi)沒有任何動作,則服務器就向客戶端發(fā)送一個保活探查報文,若客戶主機依然正常運行且從服務器仍可達,則服務器應用程序并不能感覺到保活探查的發(fā)生,TCP負責的保活探查工作對應用程序不可見;若客戶主機崩潰或從服務器不可達等情況,服務器應用程序?qū)⑹盏絹碜訲CP層的差錯報文(比如連接超時、連接被對方復位、路由超時等),服務器將終止該連接并釋放資源。

1.3 滑動窗口與緩沖機制

TCP以1個段為單位,每發(fā)一個段進行一次確認應答處理,這種傳輸方式有個缺點,包的往返時間越長通信性能就越低。為解決這個問題,TCP引入了窗口的概念,即使在往返時間較長的情況下,它也能控制網(wǎng)絡(luò)性能的下降。引入了發(fā)送接收窗口后,確認應答不再以每個分段而是以更大的單位進行確認,轉(zhuǎn)發(fā)時間將會被大幅度將會被大幅度的縮短。

窗口大小就是指無需等待確認應答而可以繼續(xù)發(fā)送數(shù)據(jù)的最大值,這個機制實現(xiàn)了使用大量的緩沖區(qū),通過對多個段同時進行確認應答的功能。在整個窗口的確定應答沒有到達之前,如果其中部分數(shù)據(jù)出現(xiàn)丟包,那么發(fā)送端仍然要負責重傳,為此發(fā)送端主機得設(shè)置緩存保留這些待被重傳的數(shù)據(jù),直到收到它們的確認應答。滑動窗口的結(jié)構(gòu)如下圖示:

滑動窗口可以看成定義在數(shù)據(jù)緩沖上的一個窗口,緩沖中存放了從應用程序傳遞過來的待發(fā)送數(shù)據(jù)。在滑動窗口以外的部分包括尚未發(fā)送的數(shù)據(jù)以及已經(jīng)確認對端已收到的數(shù)據(jù)。當數(shù)據(jù)發(fā)出后若如期收到確認應答就可以不用再進行重發(fā),此時數(shù)據(jù)就可以從緩存區(qū)清除。收到確認應答的情況下,將窗口滑動到確認應答中的序列號位置,這樣可以順序的將多個段同時發(fā)送提高通信性能,這種機制被稱為滑動窗口控制

滑動窗口控制可以到達很好的流量控制效果和擁塞控制效果,實際上流量控制與擁塞控制的本質(zhì)在于對發(fā)送窗口的合理調(diào)節(jié)。由于每個分段都會有確認應答,而滑動窗口的已確認序列號表示該序列號之前的所有數(shù)據(jù)都已收到確認應答,即便某些確認應答丟失也無需重發(fā)。如果某個報文段確實丟失了,同一個序列號的確認應答將會被重復不斷的返回(接收端在沒有收到自己所期望序列號的數(shù)據(jù)時,會對之前收到的數(shù)據(jù)進行確認應答),發(fā)送端主機如果連續(xù)3次收到同一個確認應答,就會將其所對應的數(shù)據(jù)進行重發(fā)。這種機制比前面介紹的超時重傳更高效,因此也被稱為快速重傳控制。快速重傳過程如下圖示:

接收方為了接收數(shù)據(jù),也必須在接收緩存上維護一個接收窗口,接收方需要將數(shù)據(jù)填入緩沖區(qū)、對數(shù)據(jù)進行順序組織(因底層的報文可能是無序到達的,需要把無序報文組織為有序數(shù)據(jù)流并刪除重復報文)等操作,并向發(fā)送方通告自己的接收窗口大小,它告訴發(fā)送方:我還能接收多少字節(jié)的數(shù)據(jù)。發(fā)送方應根據(jù)這個窗口通告值適當?shù)卣{(diào)整發(fā)送窗口的大小,以調(diào)整數(shù)據(jù)的發(fā)送速度。

需要指出的是,TCP是全雙工通信,兩個方向上的數(shù)據(jù)傳送是獨立的,任何一方既可以作為發(fā)送端也可以作為接收端,因此任何一方都將為每個TCP連接維護兩個窗口,一個用于數(shù)據(jù)接收,另一個用于數(shù)據(jù)發(fā)送,在一條完整的TCP連接上應該同時存在四個窗口。

1.4 流量控制與擁塞控制

發(fā)送端根據(jù)自己的實際情況發(fā)送數(shù)據(jù),接收端可能因緩存耗盡或忙于處理其他任務而來不及處理到來的數(shù)據(jù)包,如果接收端將本應該接收的數(shù)據(jù)丟棄的話,就又會觸發(fā)重傳機制,從而導致網(wǎng)絡(luò)流量的無端浪費。為了防止這種現(xiàn)象的發(fā)生,TCP提供了一種機制可以讓發(fā)送端根據(jù)接收端的實際接收能力控制發(fā)送的數(shù)據(jù)量,這就是所謂的流量控制機制。

在TCP首部中,專門有一個字段用來通知接收窗口的大小,接收端主機將自己可以接收的緩存區(qū)大小放入這個字段中通知給發(fā)送端,發(fā)送端會發(fā)送不超過這個窗口限度的數(shù)據(jù),這個字段的值越大說明網(wǎng)絡(luò)的吞吐量越高。接收端這個緩沖區(qū)一旦面臨數(shù)據(jù)溢出時,窗口大小的值也會隨之被設(shè)置為一個更小的值通知給發(fā)送端,從而控制數(shù)據(jù)發(fā)送量。發(fā)送端主機根據(jù)接收端主機的指示,對發(fā)送數(shù)據(jù)的量進行控制的過程如下圖示:

當接收端緩沖區(qū)用完后,不得不停止接收數(shù)據(jù)(此時接收窗口大小為0),在收到發(fā)送窗口更新通知后通信才能繼續(xù)進行。如果這個窗口的更新通知在傳送途中丟失,可能會導致無法繼續(xù)通信,為避免此類問題的發(fā)生,發(fā)送端主機會定時(由堅持定時器persist timer管理該定時周期)的發(fā)送一個叫做窗口探測的數(shù)據(jù)段,次數(shù)據(jù)段僅含一個字節(jié)以獲取最新的窗口大小信息。

有了TCP的窗口控制,收發(fā)主機之間即使不再以一個數(shù)據(jù)段為單位發(fā)送確認應答,也能夠連續(xù)發(fā)送大量數(shù)據(jù)包。計算機網(wǎng)絡(luò)都處于一個共享環(huán)境中,可能會因為其他主機之間的通信使得網(wǎng)絡(luò)擁堵,如果在通信剛開始時就突然發(fā)送大量數(shù)據(jù),可能會導致整個網(wǎng)絡(luò)的癱瘓。TCP為了防止該問題的出現(xiàn),在通信一開始時就會通過一個叫慢啟動的算法得出的數(shù)值對發(fā)送數(shù)據(jù)量進行控制。

首先,為了在發(fā)送端調(diào)節(jié)所要發(fā)送數(shù)據(jù)的量,定義了一個叫做擁塞窗口的概念,在慢啟動的時候?qū)⑦@個擁塞窗口大小設(shè)置為1個數(shù)據(jù)段(1 MSS)發(fā)送數(shù)據(jù),之后每收到一次確認應答擁塞窗口的值就加1。在發(fā)送數(shù)據(jù)包時,將擁塞窗口的大小與接收端主機通知的窗口大小做比較,取其中較小的值作為實際發(fā)送窗口的大小。有了上述這些機制,就可以有效減少通信開始時連續(xù)發(fā)包導致的網(wǎng)絡(luò)擁塞情況的發(fā)生。

不過,隨著包的每次往返,擁塞窗口也會以1、2、4、8等指數(shù)函數(shù)增長(每收到一次確認應答擁塞窗口值加1,收到一個窗口大小數(shù)量的確認應答則擁塞窗口大小翻倍),擁堵情況激增甚至導致網(wǎng)絡(luò)擁塞情況的發(fā)生。為了防止這些,TCP又引入了慢啟動閾值的概念,只要擁塞窗口的值超過這個閾值,在每收到一次確認應答時,只允許以擁塞窗口大小的倒數(shù)為單位增加,即收到一個窗口大小數(shù)量的確認應答后擁塞窗口大小增加一個數(shù)據(jù)段,這是擁塞窗口大小是線性增長的,該變化過程如下圖所示:

TCP的通信開始時,并沒有設(shè)置相應的慢啟動閾值,而是在超時重傳時,才會設(shè)置為當時擁塞窗口一半的大小。

由重復確認應答而觸發(fā)的快速重傳與普通的超時重傳機制的處理多少有些不同,因為前者要求至少3次的確認應答數(shù)據(jù)段到達對方主機后才會觸發(fā),相比后者網(wǎng)絡(luò)的擁堵要輕一些。所以由重復確認應答進行快速重傳控制時,慢啟動閾值的大小被設(shè)置為當時窗口大小的一半,然后將發(fā)送窗口的大小設(shè)置為該慢啟動閾值 + 3個數(shù)據(jù)段的大小,相當于直接跨國慢啟動階段進入擁塞避免階段,這種機制也稱為快速恢復機制

1.5 提高網(wǎng)絡(luò)利用率的其他機制

  • Nagle算法

TCP中為了提高網(wǎng)絡(luò)利用率,經(jīng)常使用一個叫做Nagle的算法,該算法是指發(fā)送端即使還有應該發(fā)送的數(shù)據(jù),但如果這部分數(shù)據(jù)很少的話,則進行延遲發(fā)送的一種處理機制。具體來說就是僅在已發(fā)送的數(shù)據(jù)都已收到確認應答或可以發(fā)送最大段長度的數(shù)據(jù)時才能發(fā)送數(shù)據(jù),如果兩個條件都不滿足則暫時等待一段時間后再進行數(shù)據(jù)發(fā)送。

根據(jù)這個算法雖然網(wǎng)絡(luò)利用率可以提高,但可能會發(fā)生某種程度的延遲。在某些對響應實時性要求比較高的應用場景中使用TCP時,往往會關(guān)閉對該算法的啟用。

  • 延遲確認應答

接收數(shù)據(jù)的主機如果每次都立刻回復確認應答的話,可能會返回一個較小的窗口,發(fā)送端主機收到這個小窗口通知后會以它為上限發(fā)送數(shù)據(jù),從而又降低了網(wǎng)絡(luò)利用率。為此引入了一個方法,在收到數(shù)據(jù)后不立即返回確認應答,而是延遲一段時間(直到收到2 MSS數(shù)據(jù)時為止,最大延遲0.5秒)發(fā)送確認應答。

TCP采用滑動窗口機制,通常確認應答少一些也不無妨,TCP文件傳輸時,絕大多數(shù)都是每兩個數(shù)據(jù)段返回一次確認應答。

  • 捎帶應答

根據(jù)應用層協(xié)議,發(fā)送出去的數(shù)據(jù)到達對端,對端處理后會返回一個回執(zhí),在雙方通信過程中,為提高網(wǎng)絡(luò)利用率,TCP的確認應答和回執(zhí)數(shù)據(jù)可以通過一個包發(fā)送,這種方式叫做捎帶應答。

接收數(shù)據(jù)傳給應用處理生成回執(zhí)數(shù)據(jù)需要一段時間,如果要實現(xiàn)捎帶應答,需要確認應答等待回執(zhí)數(shù)據(jù)的生成,如果沒有啟用延遲確認應答就無法實現(xiàn)捎帶應答。延遲確認應答是能夠提高網(wǎng)絡(luò)利用率從而降低計算機處理負荷的一種較優(yōu)的處理機制。

二、TCP協(xié)議實現(xiàn)

2.1 TCP報文格式

TCP協(xié)議有著自己的數(shù)據(jù)報組織格式,這里把TCP的數(shù)據(jù)包稱為報文段(Segment),TCP報文段封裝在IP數(shù)據(jù)報中發(fā)送。TCP報文段由TCP首部和TCP數(shù)據(jù)區(qū)組成,首部區(qū)域包含了連接建立與斷開、數(shù)據(jù)確認、窗口大小通告、數(shù)據(jù)發(fā)送相關(guān)的所有標志與控制信息,TCP報文結(jié)構(gòu)如下圖所示:

TCP首部相比UDP首部要復雜得多,TCP中沒有表示包長度和數(shù)據(jù)長度的字段,可由IP層獲知TCP的包長再由TCP的包長可知數(shù)據(jù)的長度。TCP首部的大小為20~60字節(jié),在沒有任何選項的情況下,首部大小為20字節(jié),與不含選項字段的IP報首部大小相同,TCP數(shù)據(jù)部分可以為空(比如建立或斷開連接時)。

與UDP報文相同,源端口號和目的端口號兩個字段用來標識發(fā)送端和接收端應用進程分別綁定的端口號。32位序號字段標識了從TCP發(fā)送端到TCP接收端的數(shù)據(jù)字節(jié)編號,它的值為當前報文段中第一個數(shù)據(jù)的字節(jié)序號。32位確認序號只有ACK標志置1時才有效,它包含了本機所期望收到的下一個數(shù)據(jù)序號(即上次已成功收到數(shù)據(jù)字節(jié)序號加1),確認常常和反向數(shù)據(jù)一起捎帶發(fā)送。序列號與確認應答號共同為TCP的正面確認、超時重傳、有序重組等可靠通信提供支持。

4位首部長度指出了TCP首部的長度,以4字節(jié)為單位,若沒有任何選項字段則首部長度為5(5*4 = 20字節(jié))。接下來的6bit保留字段暫未使用,為將來保留。再接下來是6個標志比特,它們告訴了接收端應該如何解釋報文的內(nèi)容,比如一些報文段攜帶了確認信息、一些報文段攜帶了緊急數(shù)據(jù)、一些報文段包含建立或關(guān)閉連接的請求等,6個標志位的意義如下表示:

在TCP發(fā)送一個報文時,可在窗口字段中填寫相應值以通知對方自己的可用緩沖區(qū)大小(以字節(jié)為單位),報文接收方需要根據(jù)這個值來調(diào)整發(fā)送窗口的大小。窗口字段是實現(xiàn)流量控制的關(guān)鍵字段,當接收方向發(fā)送方通知一個大小為0的窗口時,將完全阻止發(fā)送方的數(shù)據(jù)發(fā)送。

16位校驗和字段的計算和上一章中UDP校驗和計算過程與原理都相同,在UDP首部中校驗和的計算是可選的,但在TCP中校驗和的計算是必須的、強制的。TCP中校驗和包含了偽首部、TCP首部和TCP數(shù)據(jù)區(qū)三部分,偽首部的概念與UDP中完全一樣,只是偽首部中的協(xié)議字段值為6,與TCP相對應。

16位的緊急指針只有當緊急標志位URG置位時才有效,此時報文中包含緊急數(shù)據(jù),緊急數(shù)據(jù)始終放到報文段數(shù)據(jù)開始的地方,而緊急指針定義出了緊急數(shù)據(jù)在數(shù)據(jù)區(qū)中的結(jié)束處,用這個值加上序號字段值就得到了最后一個緊急數(shù)據(jù)的序號。URG位置1的報文段將告訴接收方:這里面的數(shù)據(jù)是緊急的,你可以優(yōu)先直接讀取,不必把它們放在接收緩沖里面(即該報文段不使用普通的數(shù)據(jù)流形式被處理)。

TCP首部可包含0個或多個選項信息,選項總長度可達40字節(jié),用來把附加信息傳遞給對方。每條TCP選項由三部分組成:1字節(jié)的選項類型 + 1字節(jié)的選項總長度 + 選項數(shù)據(jù),具有代表性的選項如下表所示:

其中類型代碼為2的選項是最大報文段長度(MSS),每個連接通常都在通信的第一個報文段(包含SYN標志的連接握手報文)中指明這個選項,用來向?qū)Ψ街该髯约核芙邮艿淖畲髨笪亩?#xff0c;如果沒有指明則使用默認MSS為536,前面提到的客戶端與服務器協(xié)商確定MSS的功能就是通過該選項實現(xiàn)的。

類型代碼為3的選項是窗口擴大因子選項,可以讓通信雙方聲明更大的窗口,首部中的窗口字段長度16bit,即接收窗口最大值為65535字節(jié),在許多高速場合下,這樣的窗口還是太小,會影響發(fā)送端的發(fā)送速度。使用該選項可以向?qū)Ψ酵ǜ娓蟮拇翱?#xff0c;此時通告窗口大小值(假設(shè)為N)為首部中窗口大小字段值(假設(shè)為W)乘以2的窗口擴大因子值(假設(shè)為A)次冪(即N = W * 2^A)。

2.2 TCP數(shù)據(jù)報描述

TCP數(shù)據(jù)報首部比UDP復雜些,描述TCP的數(shù)據(jù)結(jié)構(gòu)自然更復雜,在LwIP中用于描述TCP首部的數(shù)據(jù)結(jié)構(gòu)如下:

// rt-thread\components\net\lwip-1.4.1\src\include\lwip\tcp_impl.h/* Fields are (of course) in network byte order.* Some fields are converted to host byte order in tcp_input().*/ PACK_STRUCT_BEGIN struct tcp_hdr {PACK_STRUCT_FIELD(u16_t src);PACK_STRUCT_FIELD(u16_t dest);PACK_STRUCT_FIELD(u32_t seqno);PACK_STRUCT_FIELD(u32_t ackno);PACK_STRUCT_FIELD(u16_t _hdrlen_rsvd_flags);PACK_STRUCT_FIELD(u16_t wnd);PACK_STRUCT_FIELD(u16_t chksum);PACK_STRUCT_FIELD(u16_t urgp); } PACK_STRUCT_STRUCT; PACK_STRUCT_END#define TCP_FIN 0x01U #define TCP_SYN 0x02U #define TCP_RST 0x04U #define TCP_PSH 0x08U #define TCP_ACK 0x10U #define TCP_URG 0x20U #define TCP_ECE 0x40U #define TCP_CWR 0x80U#define TCPH_HDRLEN(phdr) (ntohs((phdr)->_hdrlen_rsvd_flags) >> 12) #define TCPH_FLAGS(phdr) (ntohs((phdr)->_hdrlen_rsvd_flags) & TCP_FLAGS)#define TCPH_HDRLEN_SET(phdr, len) (phdr)->_hdrlen_rsvd_flags = htons(((len) << 12) | TCPH_FLAGS(phdr)) #define TCPH_FLAGS_SET(phdr, flags) (phdr)->_hdrlen_rsvd_flags = (((phdr)->_hdrlen_rsvd_flags & PP_HTONS((u16_t)(~(u16_t)(TCP_FLAGS)))) | htons(flags)) #define TCPH_HDRLEN_FLAGS_SET(phdr, len, flags) (phdr)->_hdrlen_rsvd_flags = htons(((len) << 12) | (flags))#define TCPH_SET_FLAG(phdr, flags ) (phdr)->_hdrlen_rsvd_flags = ((phdr)->_hdrlen_rsvd_flags | htons(flags)) #define TCPH_UNSET_FLAG(phdr, flags) (phdr)->_hdrlen_rsvd_flags = htons(ntohs((phdr)->_hdrlen_rsvd_flags) | (TCPH_FLAGS(phdr) & ~(flags)) )#define TCP_TCPLEN(seg) ((seg)->len + ((TCPH_FLAGS((seg)->tcphdr) & (TCP_FIN | TCP_SYN)) != 0))

TCP首部中的各個標志位以宏定義的形式表示,同時定義了操作TCP首部各字段的宏定義。

與UDP的內(nèi)容相同,在TCP實現(xiàn)中也專門使用一個數(shù)據(jù)結(jié)構(gòu)來描述一個連接,把這個數(shù)據(jù)結(jié)構(gòu)稱為TCP控制塊或傳輸控制塊。TCP控制塊中包含了雙方實現(xiàn)基本通信所需要的信息,如發(fā)送窗口、接收窗口、數(shù)據(jù)緩沖區(qū)等,也包含了所有與該連接性能保障相關(guān)的字段,如定時器、擁塞控制、滑動窗口控制等。TCP協(xié)議實現(xiàn)的本質(zhì)就是對TCP控制塊中各個字段的操作:在接收到TCP報文段時,在所有控制塊中查找,以得到和報文目的地相匹配的控制塊,并調(diào)用控制塊上注冊的各個函數(shù)對報文進行處理;TCP內(nèi)核維護了一些周期性的定時事件,在定時處理函數(shù)中會對所有控制塊進行處理,例如把某些控制塊中的超時報文段進行重傳,把某些控制塊中的失序報文段刪除。TCP控制塊是整個TCP協(xié)議的核心,也是整個內(nèi)核中最大的數(shù)據(jù)結(jié)構(gòu),在LwIP中用于描述TCP控制塊的數(shù)據(jù)結(jié)構(gòu)如下:

// rt-thread\components\net\lwip-1.4.1\src\include\lwip\tcp.h/* the TCP protocol control block */ struct tcp_pcb { /** common PCB members */IP_PCB; /** protocol specific PCB members */TCP_PCB_COMMON(struct tcp_pcb);/* ports are in host byte order */u16_t remote_port;u8_t flags; #define TF_ACK_DELAY ((u8_t)0x01U) /* Delayed ACK. */ #define TF_ACK_NOW ((u8_t)0x02U) /* Immediate ACK. */ #define TF_INFR ((u8_t)0x04U) /* In fast recovery. */ #define TF_TIMESTAMP ((u8_t)0x08U) /* Timestamp option enabled */ #define TF_RXCLOSED ((u8_t)0x10U) /* rx closed by tcp_shutdown */ #define TF_FIN ((u8_t)0x20U) /* Connection was closed locally (FIN segment enqueued). */ #define TF_NODELAY ((u8_t)0x40U) /* Disable Nagle algorithm */ #define TF_NAGLEMEMERR ((u8_t)0x80U) /* nagle enabled, memerr, try to output to prevent delayed ACK to happen *//* the rest of the fields are in host byte orderas we have to do some math with them *//* Timers */u8_t polltmr, pollinterval;u8_t last_timer;u32_t tmr;/* receiver variables */u32_t rcv_nxt; /* next seqno expected */u16_t rcv_wnd; /* receiver window available */u16_t rcv_ann_wnd; /* receiver window to announce */u32_t rcv_ann_right_edge; /* announced right edge of window *//* Retransmission timer. */s16_t rtime;u16_t mss; /* maximum segment size *//* RTT (round trip time) estimation variables */u32_t rttest; /* RTT estimate in 500ms ticks */u32_t rtseq; /* sequence number being timed */s16_t sa, sv; /* @todo document this */s16_t rto; /* retransmission time-out */u8_t nrtx; /* number of retransmissions *//* fast retransmit/recovery */u8_t dupacks;u32_t lastack; /* Highest acknowledged seqno. *//* congestion avoidance/control variables */u16_t cwnd;u16_t ssthresh;/* sender variables */u32_t snd_nxt; /* next new seqno to be sent */u32_t snd_wl1, snd_wl2; /* Sequence and acknowledgement numbers of lastwindow update. */u32_t snd_lbb; /* Sequence number of next byte to be buffered. */u16_t snd_wnd; /* sender window */u16_t snd_wnd_max; /* the maximum sender window announced by the remote host */u16_t acked;u16_t snd_buf; /* Available buffer space for sending (in bytes). */ #define TCP_SNDQUEUELEN_OVERFLOW (0xffffU-3)u16_t snd_queuelen; /* Available buffer space for sending (in tcp_segs). *//* These are ordered by sequence number: */struct tcp_seg *unsent; /* Unsent (queued) segments. */struct tcp_seg *unacked; /* Sent but unacknowledged segments. */struct tcp_seg *ooseq; /* Received out of sequence segments. */struct pbuf *refused_data; /* Data previously received but not yet taken by upper layer *//* Function to be called when more send buffer space is available. */tcp_sent_fn sent;/* Function to be called when (in-sequence) data has arrived. */tcp_recv_fn recv;/* Function to be called when a connection has been set up. */tcp_connected_fn connected;/* Function which is called periodically. */tcp_poll_fn poll;/* Function to be called whenever a fatal error occurs. */tcp_err_fn errf;/* idle time before KEEPALIVE is sent */u32_t keep_idle;/* Persist timer counter */u8_t persist_cnt;/* Persist timer back-off */u8_t persist_backoff;/* KEEPALIVE counter */u8_t keep_cnt_sent; };struct tcp_pcb_listen { /* Common members of all PCB types */IP_PCB; /* Protocol specific PCB members */TCP_PCB_COMMON(struct tcp_pcb_listen); };/*** members common to struct tcp_pcb and struct tcp_listen_pcb*/ #define TCP_PCB_COMMON(type) \type *next; /* for the linked list */ \void *callback_arg; \/* the accept callback for listen- and normal pcbs, if LWIP_CALLBACK_API */ \DEF_ACCEPT_CALLBACK \enum tcp_state state; /* TCP state */ \u8_t prio; \/* ports are in host byte order */ \u16_t local_port#define DEF_ACCEPT_CALLBACK tcp_accept_fn accept;enum tcp_state {CLOSED = 0,LISTEN = 1,SYN_SENT = 2,SYN_RCVD = 3,ESTABLISHED = 4,FIN_WAIT_1 = 5,FIN_WAIT_2 = 6,CLOSE_WAIT = 7,CLOSING = 8,LAST_ACK = 9,TIME_WAIT = 10 };/* This structure represents a TCP segment on the unsent, unacked and ooseq queues */ struct tcp_seg {struct tcp_seg *next; /* used when putting segements on a queue */struct pbuf *p; /* buffer containing data + TCP header */u16_t len; /* the TCP length of this segment */u8_t flags; #define TF_SEG_OPTS_MSS (u8_t)0x01U /* Include MSS option. */ #define TF_SEG_OPTS_TS (u8_t)0x02U /* Include timestamp option. */ #define TF_SEG_DATA_CHECKSUMMED (u8_t)0x04U /* ALL data (not the header) ischecksummed into 'chksum' */struct tcp_hdr *tcphdr; /* the TCP header */ };/** Function prototype for tcp accept callback functions. Called when a new* connection can be accepted on a listening pcb.* @param arg Additional argument to pass to the callback function (@see tcp_arg())* @param newpcb The new connection pcb* @param err An error code if there has been an error accepting.* Only return ERR_ABRT if you have called tcp_abort from within the* callback function!*/ typedef err_t (*tcp_accept_fn)(void *arg, struct tcp_pcb *newpcb, err_t err);/** Function prototype for tcp receive callback functions. Called when data has* been received.* @param arg Additional argument to pass to the callback function (@see tcp_arg())* @param tpcb The connection pcb which received data* @param p The received data (or NULL when the connection has been closed!)* @param err An error code if there has been an error receiving* Only return ERR_ABRT if you have called tcp_abort from within the* callback function!*/ typedef err_t (*tcp_recv_fn)(void *arg, struct tcp_pcb *tpcb,struct pbuf *p, err_t err);/** Function prototype for tcp sent callback functions. Called when sent data has* been acknowledged by the remote side. Use it to free corresponding resources.* This also means that the pcb has now space available to send new data.* @param arg Additional argument to pass to the callback function (@see tcp_arg())* @param tpcb The connection pcb for which data has been acknowledged* @param len The amount of bytes acknowledged* @return ERR_OK: try to send some data by calling tcp_output* Only return ERR_ABRT if you have called tcp_abort from within the* callback function!*/ typedef err_t (*tcp_sent_fn)(void *arg, struct tcp_pcb *tpcb,u16_t len);/** Function prototype for tcp poll callback functions. Called periodically as* specified by @see tcp_poll.* @param arg Additional argument to pass to the callback function (@see tcp_arg())* @param tpcb tcp pcb* @return ERR_OK: try to send some data by calling tcp_output* Only return ERR_ABRT if you have called tcp_abort from within the* callback function!*/ typedef err_t (*tcp_poll_fn)(void *arg, struct tcp_pcb *tpcb);/** Function prototype for tcp error callback functions. Called when the pcb* receives a RST or is unexpectedly closed for any other reason.* @note The corresponding pcb is already freed when this callback is called!* @param arg Additional argument to pass to the callback function (@see tcp_arg())* @param err Error code to indicate why the pcb has been closed* ERR_ABRT: aborted through tcp_abort or by a TCP timer* ERR_RST: the connection was reset by the remote host*/ typedef void (*tcp_err_fn)(void *arg, err_t err);/** Function prototype for tcp connected callback functions. Called when a pcb* is connected to the remote side after initiating a connection attempt by* calling tcp_connect().* @param arg Additional argument to pass to the callback function (@see tcp_arg())* @param tpcb The connection pcb which is connected* @param err An unused error code, always ERR_OK currently ;-) TODO!* Only return ERR_ABRT if you have called tcp_abort from within the* callback function!* @note When a connection attempt fails, the error callback is currently called!*/ typedef err_t (*tcp_connected_fn)(void *arg, struct tcp_pcb *tpcb, err_t err);/* The TCP PCB lists. */ /** List of all TCP PCBs bound but not yet (connected || listening) */ struct tcp_pcb *tcp_bound_pcbs; /** List of all TCP PCBs in LISTEN state */ union tcp_listen_pcbs_t tcp_listen_pcbs; /** List of all TCP PCBs that are in a state in which* they accept or send data. */ struct tcp_pcb *tcp_active_pcbs; /** List of all TCP PCBs in TIME-WAIT state */ struct tcp_pcb *tcp_tw_pcbs;

上面的TCP控制塊tcp_pcb看起來很大,可以把成員變量分組,每種TCP相關(guān)機制的實現(xiàn)只涉及到其中的某幾個字段,這幾個字段可以按一組去理解和操作。除了定義tcp_pcb,還定義了tcp_pcb_listen,后者主要是用來描述處于LISTEN狀態(tài)的連接,處于LISTEN狀態(tài)的連接只記錄本地端口信息,不記錄任何遠程端口信息,一般只用于在服務器端打開某個端口為客戶端服務。處于LISTEN狀態(tài)的控制塊不會對應于任何一條有效連接,它會進行數(shù)據(jù)發(fā)送、連接握手之類的工作,因此描述LISTEN狀態(tài)的控制塊結(jié)構(gòu)體比tcp_pcb相比更小,使用它可以節(jié)省內(nèi)存空間。

對于描述一個連接的通用字段(比如遠程端口、本地端口、遠程IP地址、本地IP地址、控制塊優(yōu)先級等)就不再贅述了。重點說下flags字段,它描述了當前控制塊的特性,例如是否允許立即發(fā)送ACK、是否使能Nagle算法等,這些標志位是提高TCP傳輸性能的關(guān)鍵。

TCP控制塊中維護了三個緩沖隊列,unsent、unacked、ooseq三個字段分別為隊列的首指針,unsent用于連接還未被發(fā)送出去的報文段,unacked用于連接已經(jīng)發(fā)送出去但還未被確認的報文段,ooseq用于連接接收到的無序報文段,這三個緩沖隊列簡單的實現(xiàn)了對連接的所有報文段的管理。每個報文段用結(jié)構(gòu)體tcp_seg來描述,并以鏈表形式組織成隊列,tcp_seg報文段不僅包含指向裝載報文段的指針pbuf,還包含指向報文段中的TCP首部的指針tcp_hdr,報文段緩沖隊列的組織關(guān)系如下圖所示:

為了組織和描述系統(tǒng)內(nèi)的所有TCP控制塊,內(nèi)核定義了四條鏈表來連接處于不同狀態(tài)下的控制塊,TCP操作過程通常都包括對鏈表上控制塊的查找。定義四條鏈表的代碼在上面已給出:tcp_bound_pcbs鏈表用來連接新創(chuàng)建的且綁定了本地端口的控制塊,可以認為此時的控制塊處于CLOSED狀態(tài);tcp_listen_pcbs鏈表用來連接處于LISTEN狀態(tài)的控制塊,該狀態(tài)下用結(jié)構(gòu)體tcp_pcb_listen來描述一個本地連接;tcp_tw_pcbs鏈表用來連接處于TIME_WAIT狀態(tài)的控制塊;tcp_active_pcbs用于連接處于TCP轉(zhuǎn)換圖中其它所有狀態(tài)的控制塊,上圖展示的就是該鏈表上的控制塊。

2.3 TCP狀態(tài)機

TCP狀態(tài)字段state表示一個連接在整個通信過程中的狀態(tài)變遷。那么TCP連接的狀態(tài)是如何變遷的呢?

前面介紹TCP連接管理時談到TCP建立連接需要“三次握手”過程:首先客戶端發(fā)送SYN置1的連接請求報文后,從CLOSED狀態(tài)遷移到SYN_SENT狀態(tài);服務器收到客戶端的連接請求報文后返回SYN與ACK都置1的應答報文,并從LISTEN狀態(tài)遷移到SYN_RCVD狀態(tài);客戶端收到服務器的SYN應答報文后會再次返回ACK置1的應答報文,當服務器收到該應答報文后雙方的連接就建立起來了,此時雙方都遷移到ESTABLISHED狀態(tài)。

TCP斷開連接需要“四次握手”過程:首先客戶端向服務器發(fā)送FIN置1的報文后,從ESTABLISHED狀態(tài)遷移到FIN_WAIT_1狀態(tài);服務器收到FIN報文后返回ACK置1的應答報文,并從ESTABLISHED狀態(tài)遷移到CLOSE_WAIT狀態(tài),客戶端收到來自服務器的ACK報文后從FIN_WAIT_1狀態(tài)遷移到FIN_WAIT_2狀態(tài);服務器向上層通告該斷開操作并向客戶端發(fā)送一個FIN置1的報文段,從CLOSE_WAIT狀態(tài)遷移到LAST_ACK狀態(tài);客戶端收到來自服務器的FIN報文后返回ACK置1的應答報文,并從FIN_WAIT_2狀態(tài)遷移到TIME_WAIT狀態(tài),服務器收到來自客戶端的ACK報文后從LAST_ACK狀態(tài)遷移到CLOSED狀態(tài)。

在理解了TCP連接建立與斷開流程后,再來看TCP狀態(tài)遷移圖就相對容易了,TCP為每個連接定義了11種狀態(tài)(上面已給出實現(xiàn)代碼),下面給出狀態(tài)轉(zhuǎn)換圖如下:

雖然上面的狀態(tài)轉(zhuǎn)換圖看起來很復雜,但并不是每個連接都會出現(xiàn)圖中的所有轉(zhuǎn)換路徑,圖中有兩條最經(jīng)典的狀態(tài)轉(zhuǎn)換路徑,而TCP絕大部分的狀態(tài)轉(zhuǎn)換都發(fā)生在這兩條路徑上:第一條路徑描述了客戶端申請建立連接與斷開連接的整個過程,如圖中虛線所示;第二條路徑描述了服務器接受來自客戶端的建立連接請求與斷開連接請求的整個過程,如圖中粗實線所示。配合前面介紹的建立連接的“三次握手”過程與斷開連接的“四次握手”過程,應該更容易理解TCP連接的狀態(tài)遷移過程。

實現(xiàn)TCP狀態(tài)遷移的狀態(tài)機函數(shù)實現(xiàn)代碼如下:

// rt-thread\components\net\lwip-1.4.1\src\core\tcp_in.c /*** Implements the TCP state machine. Called by tcp_input. In some* states tcp_receive() is called to receive data. The tcp_seg* argument will be freed by the caller (tcp_input()) unless the* recv_data pointer in the pcb is set.* @param pcb the tcp_pcb for which a segment arrived* @note the segment which arrived is saved in global variables, therefore only the pcb* involved is passed as a parameter to this function*/ static err_t tcp_process(struct tcp_pcb *pcb) {struct tcp_seg *rseg;u8_t acceptable = 0;err_t err;err = ERR_OK;/* Process incoming RST segments. */if (flags & TCP_RST) {/* First, determine if the reset is acceptable. */if (pcb->state == SYN_SENT) {if (ackno == pcb->snd_nxt) {acceptable = 1;}} else {if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, pcb->rcv_nxt+pcb->rcv_wnd)) {acceptable = 1;}}if (acceptable) {recv_flags |= TF_RESET;pcb->flags &= ~TF_ACK_DELAY;return ERR_RST;} else {return ERR_OK;}}if ((flags & TCP_SYN) && (pcb->state != SYN_SENT && pcb->state != SYN_RCVD)) { /* Cope with new connection attempt after remote end crashed */tcp_ack_now(pcb);return ERR_OK;}if ((pcb->flags & TF_RXCLOSED) == 0) {/* Update the PCB (in)activity timer unless rx is closed (see tcp_shutdown) */pcb->tmr = tcp_ticks;}pcb->keep_cnt_sent = 0;tcp_parseopt(pcb);/* Do different things depending on the TCP state. */switch (pcb->state) {case SYN_SENT:/* received SYN ACK with expected sequence number? */if ((flags & TCP_ACK) && (flags & TCP_SYN)&& ackno == ntohl(pcb->unacked->tcphdr->seqno) + 1) {pcb->snd_buf++;pcb->rcv_nxt = seqno + 1;pcb->rcv_ann_right_edge = pcb->rcv_nxt;pcb->lastack = ackno;pcb->snd_wnd = tcphdr->wnd;pcb->snd_wnd_max = tcphdr->wnd;pcb->snd_wl1 = seqno - 1; /* initialise to seqno - 1 to force window update */pcb->state = ESTABLISHED;#if TCP_CALCULATE_EFF_SEND_MSSpcb->mss = tcp_eff_send_mss(pcb->mss, &(pcb->remote_ip)); #endif /* TCP_CALCULATE_EFF_SEND_MSS *//* Set ssthresh again after changing pcb->mss (already set in tcp_connect* but for the default value of pcb->mss) */pcb->ssthresh = pcb->mss * 10;pcb->cwnd = ((pcb->cwnd == 1) ? (pcb->mss * 2) : pcb->mss);--pcb->snd_queuelen;rseg = pcb->unacked;pcb->unacked = rseg->next;tcp_seg_free(rseg);/* If there's nothing left to acknowledge, stop the retransmittimer, otherwise reset it to start again */if(pcb->unacked == NULL)pcb->rtime = -1;else {pcb->rtime = 0;pcb->nrtx = 0;}/* Call the user specified function to call when sucessfully* connected. */TCP_EVENT_CONNECTED(pcb, ERR_OK, err);if (err == ERR_ABRT) {return ERR_ABRT;}tcp_ack_now(pcb);}/* received ACK? possibly a half-open connection */else if (flags & TCP_ACK) {/* send a RST to bring the other side in a non-synchronized state. */tcp_rst(ackno, seqno + tcplen, ip_current_dest_addr(), ip_current_src_addr(),tcphdr->dest, tcphdr->src);}break;case SYN_RCVD:if (flags & TCP_ACK) {/* expected ACK number? */if (TCP_SEQ_BETWEEN(ackno, pcb->lastack+1, pcb->snd_nxt)) {u16_t old_cwnd;pcb->state = ESTABLISHED;/* Call the accept function. */TCP_EVENT_ACCEPT(pcb, ERR_OK, err);if (err != ERR_OK) {/* If the accept function returns with an error, we abort* the connection. *//* Already aborted? */if (err != ERR_ABRT) {tcp_abort(pcb);}return ERR_ABRT;}old_cwnd = pcb->cwnd;/* If there was any data contained within this ACK,* we'd better pass it on to the application as well. */tcp_receive(pcb);/* Prevent ACK for SYN to generate a sent event */if (pcb->acked != 0) {pcb->acked--;}pcb->cwnd = ((old_cwnd == 1) ? (pcb->mss * 2) : pcb->mss);if (recv_flags & TF_GOT_FIN) {tcp_ack_now(pcb);pcb->state = CLOSE_WAIT;}} else {/* incorrect ACK number, send RST */tcp_rst(ackno, seqno + tcplen, ip_current_dest_addr(), ip_current_src_addr(),tcphdr->dest, tcphdr->src);}} else if ((flags & TCP_SYN) && (seqno == pcb->rcv_nxt - 1)) {/* Looks like another copy of the SYN - retransmit our SYN-ACK */tcp_rexmit(pcb);}break;case CLOSE_WAIT:/* FALLTHROUGH */case ESTABLISHED:tcp_receive(pcb);if (recv_flags & TF_GOT_FIN) { /* passive close */tcp_ack_now(pcb);pcb->state = CLOSE_WAIT;}break;case FIN_WAIT_1:tcp_receive(pcb);if (recv_flags & TF_GOT_FIN) {if ((flags & TCP_ACK) && (ackno == pcb->snd_nxt)) {tcp_ack_now(pcb);tcp_pcb_purge(pcb);TCP_RMV_ACTIVE(pcb);pcb->state = TIME_WAIT;TCP_REG(&tcp_tw_pcbs, pcb);} else {tcp_ack_now(pcb);pcb->state = CLOSING;}} else if ((flags & TCP_ACK) && (ackno == pcb->snd_nxt)) {pcb->state = FIN_WAIT_2;}break;case FIN_WAIT_2:tcp_receive(pcb);if (recv_flags & TF_GOT_FIN) {tcp_ack_now(pcb);tcp_pcb_purge(pcb);TCP_RMV_ACTIVE(pcb);pcb->state = TIME_WAIT;TCP_REG(&tcp_tw_pcbs, pcb);}break;case CLOSING:tcp_receive(pcb);if (flags & TCP_ACK && ackno == pcb->snd_nxt) {tcp_pcb_purge(pcb);TCP_RMV_ACTIVE(pcb);pcb->state = TIME_WAIT;TCP_REG(&tcp_tw_pcbs, pcb);}break;case LAST_ACK:tcp_receive(pcb);if (flags & TCP_ACK && ackno == pcb->snd_nxt) {/* bugfix #21699: don't set pcb->state to CLOSED here or we risk leaking segments */recv_flags |= TF_CLOSED;}break;default:break;}return ERR_OK; }

上面就是TCP狀態(tài)機的轉(zhuǎn)換代碼,對照狀態(tài)轉(zhuǎn)換圖更容易理解代碼邏輯。

2.4 TCP數(shù)據(jù)報操作

TCP的輸入/輸出處理函數(shù)較多,它們之間的調(diào)用關(guān)系也比較復雜,下面用一個總函數(shù)調(diào)用流程來展示所有這些函數(shù)之間的調(diào)用關(guān)系:

2.4.1 TCP報文段輸出處理

前面介紹了TCP Raw API編程,用戶應用程序可以通過TCP編程函數(shù)tcp_connect、tcp_write等構(gòu)造一個報文段,這個報文可以用于連接建立和斷開的握手報文,也可以是雙方的數(shù)據(jù)交互報文,握手報文段的構(gòu)造由函數(shù)tcp_enqueue_flags構(gòu)造完成并放入到控制塊的發(fā)送隊列中;而數(shù)據(jù)報文段的構(gòu)造是函數(shù)tcp_write直接完成的,它將TCP數(shù)據(jù)和首部部分字段填入報文中,并使用tcp_seg結(jié)構(gòu)體將報文段組織在發(fā)送緩沖隊列上(一個tcp_seg描述一個可獨立發(fā)送的報文段);當函數(shù)tcp_output被調(diào)用時,它會在控制塊的發(fā)送緩沖隊列上依次取下報文段發(fā)送,這個函數(shù)的唯一工作就是判斷報文段是否在允許的發(fā)送窗口內(nèi),然后調(diào)用函數(shù)tcp_output_segment發(fā)送報文段,當發(fā)送完成后,tcp_output會把相應報文段放在控制塊的未確認隊列unacked上;在tcp_output_segment發(fā)送報文段時,它會填寫首部中的剩余字段,包括確認序號、通告窗口、選項等,最重要的是,它需要與IP層的ip_route函數(shù)交互,獲得偽首部中的源IP地址字段,計算并填寫TCP首部中的校驗和。最后,IP層的發(fā)送函數(shù)ip_output會被調(diào)用,用來組裝并發(fā)送IP數(shù)據(jù)報。

下面給出構(gòu)造數(shù)據(jù)報文段的tcp_write函數(shù)的流程圖,實現(xiàn)代碼較復雜,讀者可以根據(jù)流程圖對照源碼理解其邏輯,構(gòu)造握手報文段的tcp_enqueue_flags函數(shù)比tcp_write簡單許多,讀者可以參考下面的流程圖直接閱讀源碼:

發(fā)送報文段的函數(shù)是tcp_output,其唯一參數(shù)是某個連接的TCP控制塊指針pcb,函數(shù)把這個控制塊unsent隊列上的報文段發(fā)送出去或只發(fā)送一個ACK報文段(unsent隊列無數(shù)據(jù)發(fā)送或發(fā)送窗口此時不允許發(fā)送數(shù)據(jù))。報文段實際由tcp_output_segment發(fā)送出去后,tcp_output需將發(fā)送出去的報文段放入控制塊unacked緩沖隊列中(需保證隊列中的所有報文段序號有序排列),以便后續(xù)的重發(fā)操作。當unsent隊列上的第一個報文段處理完畢,tcp_output會按照上述方法依次處理unsent隊列上的剩余報文段,直到數(shù)據(jù)被全部發(fā)送出去或發(fā)送窗口被填滿。tcp_write函數(shù)的重要部分和tcp_output的實現(xiàn)代碼如下:

// rt-thread\components\net\lwip-1.4.1\src\core\tcp_out.c /*** Write data for sending (but does not send it immediately).** It waits in the expectation of more data being sent soon (as* it can send them more efficiently by combining them together).* To prompt the system to send data now, call tcp_output() after* calling tcp_write().** @param pcb Protocol control block for the TCP connection to enqueue data for.* @param arg Pointer to the data to be enqueued for sending.* @param len Data length in bytes* @param apiflags combination of following flags :* - TCP_WRITE_FLAG_COPY (0x01) data will be copied into memory belonging to the stack* - TCP_WRITE_FLAG_MORE (0x02) for TCP connection, PSH flag will be set on last segment sent,* @return ERR_OK if enqueued, another err_t on error*/ err_t tcp_write(struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t apiflags) {....../** Finally update the pcb state.*/pcb->snd_lbb += len;pcb->snd_buf -= len;pcb->snd_queuelen = queuelen;/* Set the PSH flag in the last segment that we enqueued. */if (seg != NULL && seg->tcphdr != NULL && ((apiflags & TCP_WRITE_FLAG_MORE)==0)) {TCPH_SET_FLAG(seg->tcphdr, TCP_PSH);}...... }/*** Find out what we can send and send it** @param pcb Protocol control block for the TCP connection to send data* @return ERR_OK if data has been sent or nothing to send* another err_t on error*/ err_t tcp_output(struct tcp_pcb *pcb) {struct tcp_seg *seg, *useg;u32_t wnd, snd_nxt;/* First, check if we are invoked by the TCP input processingcode. If so, we do not output anything. Instead, we rely on theinput processing code to call us when input processing is donewith. */if (tcp_input_pcb == pcb) {return ERR_OK;}wnd = LWIP_MIN(pcb->snd_wnd, pcb->cwnd);seg = pcb->unsent;/* If the TF_ACK_NOW flag is set and no data will be sent (either* because the ->unsent queue is empty or because the window does* not allow it), construct an empty ACK segment and send it.* If data is to be sent, we will just piggyback the ACK (see below).*/if (pcb->flags & TF_ACK_NOW &&(seg == NULL ||ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len > wnd)) {return tcp_send_empty_ack(pcb);}/* useg should point to last segment on unacked queue */useg = pcb->unacked;if (useg != NULL) {for (; useg->next != NULL; useg = useg->next);}/* data available and window allows it to be sent? */while (seg != NULL &&ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len <= wnd) {/* Stop sending if the nagle algorithm would prevent it* Don't stop:* - if tcp_write had a memory error before (prevent delayed ACK timeout) or* - if FIN was already enqueued for this PCB (SYN is always alone in a segment -* either seg->next != NULL or pcb->unacked == NULL;* RST is no sent using tcp_write/tcp_output.*/if((tcp_do_output_nagle(pcb) == 0) &&((pcb->flags & (TF_NAGLEMEMERR | TF_FIN)) == 0)){break;}pcb->unsent = seg->next;if (pcb->state != SYN_SENT) {TCPH_SET_FLAG(seg->tcphdr, TCP_ACK);pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW);}tcp_output_segment(seg, pcb);snd_nxt = ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg);if (TCP_SEQ_LT(pcb->snd_nxt, snd_nxt)) {pcb->snd_nxt = snd_nxt;}/* put segment on unacknowledged list if length > 0 */if (TCP_TCPLEN(seg) > 0) {seg->next = NULL;/* unacked list is empty? */if (pcb->unacked == NULL) {pcb->unacked = seg;useg = seg;/* unacked list is not empty? */} else {/* In the case of fast retransmit, the packet should not go to the tail* of the unacked queue, but rather somewhere before it. We need to check for* this case. -STJ Jul 27, 2004 */if (TCP_SEQ_LT(ntohl(seg->tcphdr->seqno), ntohl(useg->tcphdr->seqno))) {/* add segment to before tail of unacked list, keeping the list sorted */struct tcp_seg **cur_seg = &(pcb->unacked);while (*cur_seg &&TCP_SEQ_LT(ntohl((*cur_seg)->tcphdr->seqno), ntohl(seg->tcphdr->seqno))) {cur_seg = &((*cur_seg)->next );}seg->next = (*cur_seg);(*cur_seg) = seg;} else {/* add segment to tail of unacked list */useg->next = seg;useg = useg->next;}}/* do not queue empty segments on the unacked list */} else {tcp_seg_free(seg);}seg = pcb->unsent;}pcb->flags &= ~TF_NAGLEMEMERR;return ERR_OK; }

從整個發(fā)送過程來看,tcp_output只是檢查某個報文是否滿足被發(fā)送的條件,然后調(diào)用函數(shù)tcp_output_segment將報文段發(fā)送出去,后者需要填寫TCP報文首部中剩下的幾個必要字段,然后調(diào)用IP層輸出函數(shù)ip_output發(fā)送報文,tcp_output_segment函數(shù)的功能有點類似于UDP協(xié)議中的udp_sendto函數(shù),讀者可以對照源碼理解。

2.4.2 TCP報文段輸入處理

從上面的TCP函數(shù)調(diào)用流程圖可以看出,與TCP輸入相關(guān)的函數(shù)有5個,TCP報文被IP層遞交給tcp_input函數(shù),這個函數(shù)可以說是TCP層的總輸入函數(shù),它會為報文段尋找一個匹配的TCP控制塊,根據(jù)控制塊狀態(tài)的不同,調(diào)用tcp_timewait_input、tcp_listen_input或tcp_process處理報文段;這里的重點是函數(shù)tcp_process,它實現(xiàn)了前面介紹過的TCP狀態(tài)機(實現(xiàn)源碼也在前面給出),函數(shù)根據(jù)報文信息完成連接狀態(tài)的變遷,同時若報文中有數(shù)據(jù),則函數(shù)tcp_receive會被調(diào)用;整個過程中的難點在于函數(shù)tcp_receive,它完成了TCP中的數(shù)據(jù)接收、數(shù)據(jù)重組等工作,同時TCP中各種性能算法的實現(xiàn)也是在該函數(shù)中完成。

在IP層收到數(shù)據(jù)報后,ip_input函數(shù)會判斷IP首部中的協(xié)議字段,把屬于TCP的報文通過tcp_input函數(shù)傳遞到TCP層。tcp_input完成報文向各個控制塊的分發(fā),并等待控制塊對相應報文的處理結(jié)果,它會根據(jù)處理結(jié)果向用戶遞交數(shù)據(jù)或向連接另一端輸出響應報文。對于每一個待處理報文,tcp_input都將它們的信息記錄在一些全局變量中,其它各函數(shù)可以直接操作這些全局變量來得到想要的信息,這些全局變量的定義如下:

// rt-thread\components\net\lwip-1.4.1\src\core\tcp_in.c/* These variables are global to all functions involved in the inputprocessing of TCP segments. They are set by the tcp_input()function. */ static struct tcp_seg inseg; static struct tcp_hdr *tcphdr; static struct ip_hdr *iphdr; static u32_t seqno, ackno; static u8_t flags; static u16_t tcplen;static u8_t recv_flags; static struct pbuf *recv_data;struct tcp_pcb *tcp_input_pcb;

tcp_input函數(shù)開始會對IP層遞交進來的報文段進行一些基本操作,如丟棄廣播或多播數(shù)據(jù)報、數(shù)據(jù)校驗和驗證,同時提取TCP報文首部各個字段填寫到上述全局變量中。接下來根據(jù)TCP報文段中表示連接的四個字段的值來查找四條鏈表,在哪條鏈表上找到對應的控制塊則交由相應的函數(shù)繼續(xù)處理。下面給出tcp_input函數(shù)的流程圖如下:

tcp_process函數(shù)實現(xiàn)代碼前面已給出,下面給出tcp_input部分比較重要的代碼(函數(shù)太長,不再全部展示,讀者可以結(jié)合流程圖理解源碼)、tcp_timewait_input與tcp_listen_input實現(xiàn)代碼如下:

// rt-thread\components\net\lwip-1.4.1\src\core\tcp_in.c /*** The initial input processing of TCP. It verifies the TCP header, demultiplexes* the segment between the PCBs and passes it on to tcp_process(), which implements* the TCP finite state machine. This function is called by the IP layer (in* ip_input()).* @param p received TCP segment to process (p->payload pointing to the IP header)* @param inp network interface on which this segment was received*/ void tcp_input(struct pbuf *p, struct netif *inp) {......tcp_input_pcb = pcb;err = tcp_process(pcb);/* A return value of ERR_ABRT means that tcp_abort() was calledand that the pcb has been freed. If so, we don't do anything. */if (err != ERR_ABRT) {if (recv_flags & TF_RESET) {/* TF_RESET means that the connection was reset by the otherend. We then call the error callback to inform theapplication that the connection is dead before wedeallocate the PCB. */TCP_EVENT_ERR(pcb->errf, pcb->callback_arg, ERR_RST);tcp_pcb_remove(&tcp_active_pcbs, pcb);memp_free(MEMP_TCP_PCB, pcb);} else if (recv_flags & TF_CLOSED) {/* The connection has been closed and we will deallocate thePCB. */if (!(pcb->flags & TF_RXCLOSED)) {/* Connection closed although the application has only shut down thetx side: call the PCB's err callback and indicate the closure toensure the application doesn't continue using the PCB. */TCP_EVENT_ERR(pcb->errf, pcb->callback_arg, ERR_CLSD);}tcp_pcb_remove(&tcp_active_pcbs, pcb);memp_free(MEMP_TCP_PCB, pcb);} else {err = ERR_OK;/* If the application has registered a "sent" function to becalled when new send buffer space is available, we call itnow. */if (pcb->acked > 0) {TCP_EVENT_SENT(pcb, pcb->acked, err);if (err == ERR_ABRT) {goto aborted;}}if (recv_data != NULL) {if (pcb->flags & TF_RXCLOSED) {/* received data although already closed -> abort (send RST) tonotify the remote host that not all data has been processed */pbuf_free(recv_data);tcp_abort(pcb);goto aborted;}/* Notify application that data has been received. */TCP_EVENT_RECV(pcb, recv_data, ERR_OK, err);if (err == ERR_ABRT) {goto aborted;}/* If the upper layer can't receive this data, store it */if (err != ERR_OK) {pcb->refused_data = recv_data;}}/* If a FIN segment was received, we call the callbackfunction with a NULL buffer to indicate EOF. */if (recv_flags & TF_GOT_FIN) {if (pcb->refused_data != NULL) {/* Delay this if we have refused data. */pcb->refused_data->flags |= PBUF_FLAG_TCP_FIN;} else {/* correct rcv_wnd as the application won't call tcp_recved()for the FIN's seqno */if (pcb->rcv_wnd != TCP_WND) {pcb->rcv_wnd++;}TCP_EVENT_CLOSED(pcb, err);if (err == ERR_ABRT) {goto aborted;}}}tcp_input_pcb = NULL;/* Try to send something out. */tcp_output(pcb);}}...... }/*** Called by tcp_input() when a segment arrives for a listening* connection (from tcp_input()).* @param pcb the tcp_pcb_listen for which a segment arrived* @return ERR_OK if the segment was processed* another err_t on error* @note the return value is not (yet?) used in tcp_input()* @note the segment which arrived is saved in global variables, therefore only the pcb* involved is passed as a parameter to this function*/ static err_t tcp_listen_input(struct tcp_pcb_listen *pcb) {struct tcp_pcb *npcb;err_t rc;if (flags & TCP_RST) {/* An incoming RST should be ignored. Return. */return ERR_OK;}/* In the LISTEN state, we check for incoming SYN segments,creates a new PCB, and responds with a SYN|ACK. */if (flags & TCP_ACK) {/* For incoming segments with the ACK flag set, respond with a RST. */tcp_rst(ackno, seqno + tcplen, ip_current_dest_addr(),ip_current_src_addr(), tcphdr->dest, tcphdr->src);} else if (flags & TCP_SYN) {npcb = tcp_alloc(pcb->prio);/* If a new PCB could not be created (probably due to lack of memory),we don't do anything, but rely on the sender will retransmit theSYN at a time when we have more memory available. */if (npcb == NULL) {return ERR_MEM;}/* Set up the new PCB. */ip_addr_copy(npcb->local_ip, current_iphdr_dest);npcb->local_port = pcb->local_port;ip_addr_copy(npcb->remote_ip, current_iphdr_src);npcb->remote_port = tcphdr->src;npcb->state = SYN_RCVD;npcb->rcv_nxt = seqno + 1;npcb->rcv_ann_right_edge = npcb->rcv_nxt;npcb->snd_wnd = tcphdr->wnd;npcb->snd_wnd_max = tcphdr->wnd;npcb->ssthresh = npcb->snd_wnd;npcb->snd_wl1 = seqno - 1;/* initialise to seqno-1 to force window update */npcb->callback_arg = pcb->callback_arg;npcb->accept = pcb->accept;/* inherit socket options */npcb->so_options = pcb->so_options & SOF_INHERITED;/* Register the new PCB so that we can begin receiving segmentsfor it. */TCP_REG_ACTIVE(npcb);/* Parse any options in the SYN. */tcp_parseopt(npcb);npcb->mss = tcp_eff_send_mss(npcb->mss, &(npcb->remote_ip));/* Send a SYN|ACK together with the MSS option. */rc = tcp_enqueue_flags(npcb, TCP_SYN | TCP_ACK);if (rc != ERR_OK) {tcp_abandon(npcb, 0);return rc;}return tcp_output(npcb);}return ERR_OK; }/*** Called by tcp_input() when a segment arrives for a connection in* TIME_WAIT.* @param pcb the tcp_pcb for which a segment arrived* @note the segment which arrived is saved in global variables, therefore only the pcb* involved is passed as a parameter to this function*/ static err_t tcp_timewait_input(struct tcp_pcb *pcb) {/* RFC 1337: in TIME_WAIT, ignore RST and ACK FINs + any 'acceptable' segments *//* RFC 793 3.9 Event Processing - Segment Arrives:* - first check sequence number - we skip that one in TIME_WAIT (always* acceptable since we only send ACKs)* - second check the RST bit (... return) */if (flags & TCP_RST) {return ERR_OK;}/* - fourth, check the SYN bit, */if (flags & TCP_SYN) {/* If an incoming segment is not acceptable, an acknowledgmentshould be sent in reply */if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, pcb->rcv_nxt+pcb->rcv_wnd)) {/* If the SYN is in the window it is an error, send a reset */tcp_rst(ackno, seqno + tcplen, ip_current_dest_addr(), ip_current_src_addr(),tcphdr->dest, tcphdr->src);return ERR_OK;}} else if (flags & TCP_FIN) {/* - eighth, check the FIN bit: Remain in the TIME-WAIT state.Restart the 2 MSL time-wait timeout.*/pcb->tmr = tcp_ticks;}if ((tcplen > 0)) {/* Acknowledge data, FIN or out-of-window SYN */pcb->flags |= TF_ACK_NOW;return tcp_output(pcb);}return ERR_OK; }

在TCP內(nèi)核中,輸入報文段中的數(shù)據(jù)接收和處理都是由函數(shù)tcp_receive來完成的,這個函數(shù)可以說是整個協(xié)議棧內(nèi)核中代碼最長、最難懂的部分了。在前面TCP狀態(tài)機實現(xiàn)函數(shù)tcp_process中可以看到,函數(shù)tcp_receive在多個地方被調(diào)用來處理報文段中的數(shù)據(jù)。總結(jié)下該函數(shù)需要完成的工作:首先檢查報文中攜帶的確認序號是否確認了未確認序列unacked中的數(shù)據(jù),如果是則釋放掉被確認的數(shù)據(jù)空間,并設(shè)置acked字段值以便tcp_input回調(diào)用戶函數(shù);同時,如果報文段中有數(shù)據(jù)且數(shù)據(jù)有序,這些數(shù)據(jù)會被記錄在recv_data中,以便用戶程序處理;如果控制塊的ooseq隊列上的報文段因為新報文段的到來而變得有序,則這些報文段的數(shù)據(jù)也會被一起連接在recv_data中,在函數(shù)退出后由tcp_input遞交給應用程序處理;如果新報文段不是有序的,則報文段將被插入到隊列ooseq上,該報文段的引用指針將被加1,防止在其他地方被刪除。最后,還有很多其他工作也需要在該函數(shù)中完成,例如當前確認序號包含了對正在進行RTT估計的報文段的確認,則RTT需要被計算;如果收到重復的ACK,這可能會在函數(shù)中啟動快速重傳算法等。下面展示了整個tcp_receive函數(shù)的處理流程,讀者可以參照這個流程圖去閱讀該函數(shù)的源代碼:

前面介紹了TCP協(xié)議如何提供可靠的傳輸服務,比如超時重傳與RTT估計、保活機制、快速重傳與快速恢復、慢啟動與擁塞避免、零窗口探查、Nagle算法與延遲捎帶確認應答等,這些功能的實現(xiàn)代碼也都分布在上面介紹的函數(shù)中,限于篇幅且某功能實現(xiàn)代碼并不局限于某一個函數(shù)內(nèi),這里就不再一一列出了,讀者可以閱讀源碼理解相應功能的實現(xiàn)邏輯。下面以零窗口探查、快速重傳與快速恢復、慢啟動與擁塞避免、RTT(Round-Rrip Time)估算與RTO(Retransmission Timeout)更新等功能在tcp_receive函數(shù)中的部分實現(xiàn)為例,展示其實現(xiàn)代碼如下:

// rt-thread\components\net\lwip-1.4.1\src\core\tcp_in.c /*** Called by tcp_process. Checks if the given segment is an ACK for outstanding* data, and if so frees the memory of the buffered data. Next, is places the* segment on any of the receive queues (pcb->recved or pcb->ooseq). If the segment* is buffered, the pbuf is referenced by pbuf_ref so that it will not be freed until* it has been removed from the buffer.** If the incoming segment constitutes an ACK for a segment that was used for RTT* estimation, the RTT is estimated here as well.** Called from tcp_process().*/ static void tcp_receive(struct tcp_pcb *pcb) {struct tcp_seg *next;struct tcp_seg *prev, *cseg;struct pbuf *p;s32_t off;s16_t m;u32_t right_wnd_edge;u16_t new_tot_len;int found_dupack = 0;if (flags & TCP_ACK) {right_wnd_edge = pcb->snd_wnd + pcb->snd_wl2;/* Update window. */if (TCP_SEQ_LT(pcb->snd_wl1, seqno) ||(pcb->snd_wl1 == seqno && TCP_SEQ_LT(pcb->snd_wl2, ackno)) ||(pcb->snd_wl2 == ackno && tcphdr->wnd > pcb->snd_wnd)) {pcb->snd_wnd = tcphdr->wnd;/* keep track of the biggest window announced by the remote host to calculatethe maximum segment size */if (pcb->snd_wnd_max < tcphdr->wnd) {pcb->snd_wnd_max = tcphdr->wnd;}pcb->snd_wl1 = seqno;pcb->snd_wl2 = ackno;if (pcb->snd_wnd == 0) {if (pcb->persist_backoff == 0) {/* start persist timer */pcb->persist_cnt = 0;pcb->persist_backoff = 1;}} else if (pcb->persist_backoff > 0) {/* stop persist timer */pcb->persist_backoff = 0;}}/* (From Stevens TCP/IP Illustrated Vol II, p970.) Its only a* duplicate ack if:* 1) It doesn't ACK new data * 2) length of received packet is zero (i.e. no payload) * 3) the advertised window hasn't changed * 4) There is outstanding unacknowledged data (retransmission timer running)* 5) The ACK is == biggest ACK sequence number so far seen (snd_una)* * If it passes all five, should process as a dupack: * a) dupacks < 3: do nothing * b) dupacks == 3: fast retransmit * c) dupacks > 3: increase cwnd * * If it only passes 1-3, should reset dupack counter (and add to* stats, which we don't do in lwIP)* If it only passes 1, should reset dupack counter*//* Clause 1 */if (TCP_SEQ_LEQ(ackno, pcb->lastack)) {pcb->acked = 0;/* Clause 2 */if (tcplen == 0) {/* Clause 3 */if (pcb->snd_wl2 + pcb->snd_wnd == right_wnd_edge){/* Clause 4 */if (pcb->rtime >= 0) {/* Clause 5 */if (pcb->lastack == ackno) {found_dupack = 1;if ((u8_t)(pcb->dupacks + 1) > pcb->dupacks) {++pcb->dupacks;}if (pcb->dupacks > 3) {/* Inflate the congestion window, but not if it means thatthe value overflows. */if ((u16_t)(pcb->cwnd + pcb->mss) > pcb->cwnd) {pcb->cwnd += pcb->mss;}} else if (pcb->dupacks == 3) {/* Do fast retransmit */tcp_rexmit_fast(pcb);}}}}}/* If Clause (1) or more is true, but not a duplicate ack, reset* count of consecutive duplicate acks */if (!found_dupack) {pcb->dupacks = 0;}} else if (TCP_SEQ_BETWEEN(ackno, pcb->lastack+1, pcb->snd_nxt)){/* We come here when the ACK acknowledges new data. *//* Reset the "IN Fast Retransmit" flag, since we are no longerin fast retransmit. Also reset the congestion window to theslow start threshold. */if (pcb->flags & TF_INFR) {pcb->flags &= ~TF_INFR;pcb->cwnd = pcb->ssthresh;}/* Reset the number of retransmissions. */pcb->nrtx = 0;/* Reset the retransmission time-out. */pcb->rto = (pcb->sa >> 3) + pcb->sv;/* Update the send buffer space. Diff between the two can never exceed 64K? */pcb->acked = (u16_t)(ackno - pcb->lastack);pcb->snd_buf += pcb->acked;/* Reset the fast retransmit variables. */pcb->dupacks = 0;pcb->lastack = ackno;/* Update the congestion control variables (cwnd andssthresh). */if (pcb->state >= ESTABLISHED) {if (pcb->cwnd < pcb->ssthresh) {if ((u16_t)(pcb->cwnd + pcb->mss) > pcb->cwnd) {pcb->cwnd += pcb->mss;}} else {u16_t new_cwnd = (pcb->cwnd + pcb->mss * pcb->mss / pcb->cwnd);if (new_cwnd > pcb->cwnd) {pcb->cwnd = new_cwnd;}}}....../* RTT estimation calculations. This is done by checking if theincoming segment acknowledges the segment we use to take around-trip time measurement. */if (pcb->rttest && TCP_SEQ_LT(pcb->rtseq, ackno)) {/* diff between this shouldn't exceed 32K since this are tcp timer ticksand a round-trip shouldn't be that long... */m = (s16_t)(tcp_ticks - pcb->rttest);/* This is taken directly from VJs original code in his paper */m = m - (pcb->sa >> 3);pcb->sa += m;if (m < 0) {m = -m;}m = m - (pcb->sv >> 2);pcb->sv += m;pcb->rto = (pcb->sa >> 3) + pcb->sv;pcb->rttest = 0;}...... }

2.4.3 TCP定時器

在TCP函數(shù)調(diào)用總流程中,TCP報文段輸出函數(shù)tcp_output是被定時器tcp_tmr周期性調(diào)用的。此外,與TCP功能相關(guān)的定時器還有很多,比如回調(diào)函數(shù)poll需要定時器的支持,重傳、保活等也都離不開定時器支持。總結(jié)來說,TCP為每條連接總共建立了七個定時器,分別如下:

  • 建立連接(connection establishment)定時器:在服務器響應一個SYN握手報文并試圖建立一條新連接時啟動,此時服務器已發(fā)出自己的SYN+ACK并處于SYN_RCVD等待對方ACK的返回,如果在75秒內(nèi)沒有收到響應,連接建立將中止,這也是服務器處理SYN攻擊的有效手段;
  • 重傳(retransmission)定時器:在TCP發(fā)送某個報文時設(shè)定,如果該定時器超時而對端的確認還未到達,TCP將重傳該報文段。重傳間隔是根據(jù)RTT估計值動態(tài)計算的,且取決于報文段已被重傳的次數(shù);
  • 數(shù)據(jù)組裝(assemble)定時器:在接收緩沖隊列ooseq不為空時有效,如果連接上很長時間內(nèi)都沒有數(shù)據(jù)交互,但是失序報文段緩沖隊列ooseq上還有失序的報文,則相應的報文需要在隊列中刪除;
  • 堅持(persist)定時器:在對方通告接收窗口為0,阻止TCP繼續(xù)發(fā)送數(shù)據(jù)時設(shè)定。定時器超時后,將向?qū)Ψ桨l(fā)送1字節(jié)的數(shù)據(jù),判斷對方接收窗口是否已打開;
  • 保活(keep alive)定時器:在TCP控制塊的so_options字段設(shè)置了SOF_KEEPALIVE選項時生效。如果連接的連續(xù)空閑時間超過2小時,則保活定時器超時,此時應向?qū)Ψ桨l(fā)送保活探查報文,強迫對方響應。如果收到期待的響應,TCP可確定對方主機工作正常,重置保活定時器;如果未收到期待的響應,則TCP關(guān)閉連接釋放資源并通知應用程序?qū)Ψ揭褦嚅_;
  • FIN_WAIT_2定時器:當某個連接從FIN_WAIT_1狀態(tài)變遷到FIN_WAIT_2狀態(tài)并且不能再接收任何新數(shù)據(jù)時,FIN_WAIT_2定時器啟動,定時器超時后連接被關(guān)閉。
  • TIME_WAIT定時器:一般也稱為2MSL(Maximum Segment Lifetime)定時器,當連接轉(zhuǎn)移到TIME_WAIT狀態(tài)即連接主動關(guān)閉時,該定時器啟動,超時后TCP控制塊被刪除,端口號可重新使用。同樣,服務器端在斷開連接過程中會處于LAST_ACK狀態(tài)等待對方ACK的返回,如果在該狀態(tài)下的2MSL時間內(nèi)未收到對方的響應,連接也會被立即關(guān)閉。

所有的7個定時器中,重傳定時器使用rtime字段計數(shù),堅持定時器使用persist_cnt字段計數(shù),其它所有5個定時器都使用tmr字段,通過與各自的一個全局變量做比較判斷是否超時,超時后執(zhí)行相應的處理。這幾個定時器是在連接處于幾種不同的狀態(tài)時使用的,因此它們可以完全獨立的使用tmr字段而不會相互影響,下面是它們的超時上限宏定義:

// rt-thread\components\net\lwip-1.4.1\src\include\lwip\tcp_impl.h#define TCP_TMR_INTERVAL 250 /* The TCP timer interval in milliseconds. */ #define TCP_FAST_INTERVAL TCP_TMR_INTERVAL /* the fine grained timeout in milliseconds */ #define TCP_SLOW_INTERVAL (2*TCP_TMR_INTERVAL) /* the coarse grained timeout in milliseconds */#define TCP_FIN_WAIT_TIMEOUT 20000 /* milliseconds */ #define TCP_SYN_RCVD_TIMEOUT 20000 /* milliseconds */#define TCP_OOSEQ_TIMEOUT 6U /* x RTO */ #define TCP_MSL 60000UL /* The maximum segment lifetime in milliseconds *//* Keepalive values, compliant with RFC 1122. Don't change this unless you know what you're doing */ #define TCP_KEEPIDLE_DEFAULT 7200000UL /* Default KEEPALIVE timer in milliseconds */ #define TCP_KEEPINTVL_DEFAULT 75000UL /* Default Time between KEEPALIVE probes in milliseconds */ #define TCP_KEEPCNT_DEFAULT 9U /* Default Counter for KEEPALIVE probes */ #define TCP_MAXIDLE TCP_KEEPCNT_DEFAULT * TCP_KEEPINTVL_DEFAULT /* Maximum KEEPALIVE probe time */

上面介紹的7種定時器包括TCP絕大部分可靠性的保障都是在tcp_slowtmr慢速定時器處理函數(shù)中完成的,該函數(shù)的實現(xiàn)代碼如下:

// rt-thread\components\net\lwip-1.4.1\src\core\tcp.c/* Incremented every coarse grained timer shot (typically every 500 ms). */ u32_t tcp_ticks; const u8_t tcp_backoff[13] = { 1, 2, 3, 4, 5, 6, 7, 7, 7, 7, 7, 7, 7};/* Times per slowtmr hits */ const u8_t tcp_persist_backoff[7] = { 3, 6, 12, 24, 48, 96, 120 };/* The TCP PCB lists. */ /** List of all TCP PCBs bound but not yet (connected || listening) */ struct tcp_pcb *tcp_bound_pcbs; /** List of all TCP PCBs in LISTEN state */ union tcp_listen_pcbs_t tcp_listen_pcbs; /** List of all TCP PCBs that are in a state in which* they accept or send data. */ struct tcp_pcb *tcp_active_pcbs; /** List of all TCP PCBs in TIME-WAIT state */ struct tcp_pcb *tcp_tw_pcbs;/*** Called every 500 ms and implements the retransmission timer and the timer that* removes PCBs that have been in TIME-WAIT for enough time. It also increments* various timers such as the inactivity timer in each PCB.** Automatically called from tcp_tmr().*/ void tcp_slowtmr(void) {struct tcp_pcb *pcb, *prev;u16_t eff_wnd;u8_t pcb_remove; /* flag if a PCB should be removed */u8_t pcb_reset; /* flag if a RST should be sent when removing */err_t err;err = ERR_OK;++tcp_ticks;++tcp_timer_ctr;tcp_slowtmr_start:/* Steps through all of the active PCBs. */prev = NULL;pcb = tcp_active_pcbs;while (pcb != NULL) {if (pcb->last_timer == tcp_timer_ctr) {/* skip this pcb, we have already processed it */pcb = pcb->next;continue;}pcb->last_timer = tcp_timer_ctr;pcb_remove = 0;pcb_reset = 0;if (pcb->state == SYN_SENT && pcb->nrtx == TCP_SYNMAXRTX) {++pcb_remove;}else if (pcb->nrtx == TCP_MAXRTX) {++pcb_remove;} else {if (pcb->persist_backoff > 0) {/* If snd_wnd is zero, use persist timer to send 1 byte probes* instead of using the standard retransmission mechanism. */pcb->persist_cnt++;if (pcb->persist_cnt >= tcp_persist_backoff[pcb->persist_backoff-1]) {pcb->persist_cnt = 0;if (pcb->persist_backoff < sizeof(tcp_persist_backoff)) {pcb->persist_backoff++;}tcp_zero_window_probe(pcb);}} else {/* Increase the retransmission timer if it is running */if(pcb->rtime >= 0) {++pcb->rtime;}if (pcb->unacked != NULL && pcb->rtime >= pcb->rto) {/* Double retransmission time-out unless we are trying to* connect to somebody (i.e., we are in SYN_SENT). */if (pcb->state != SYN_SENT) {pcb->rto = ((pcb->sa >> 3) + pcb->sv) << tcp_backoff[pcb->nrtx];}/* Reset the retransmission timer. */pcb->rtime = 0;/* Reduce congestion window and ssthresh. */eff_wnd = LWIP_MIN(pcb->cwnd, pcb->snd_wnd);pcb->ssthresh = eff_wnd >> 1;if (pcb->ssthresh < (pcb->mss << 1)) {pcb->ssthresh = (pcb->mss << 1);}pcb->cwnd = pcb->mss;/* The following needs to be called AFTER cwnd is set to onemss - STJ */tcp_rexmit_rto(pcb);}}}/* Check if this PCB has stayed too long in FIN-WAIT-2 */if (pcb->state == FIN_WAIT_2) {/* If this PCB is in FIN_WAIT_2 because of SHUT_WR don't let it time out. */if (pcb->flags & TF_RXCLOSED) {/* PCB was fully closed (either through close() or SHUT_RDWR):normal FIN-WAIT timeout handling. */if ((u32_t)(tcp_ticks - pcb->tmr) >TCP_FIN_WAIT_TIMEOUT / TCP_SLOW_INTERVAL) {++pcb_remove;}}}/* Check if KEEPALIVE should be sent */if(ip_get_option(pcb, SOF_KEEPALIVE) &&((pcb->state == ESTABLISHED) ||(pcb->state == CLOSE_WAIT))) {if((u32_t)(tcp_ticks - pcb->tmr) >(pcb->keep_idle + TCP_KEEP_DUR(pcb)) / TCP_SLOW_INTERVAL){ ++pcb_remove;++pcb_reset;}else if((u32_t)(tcp_ticks - pcb->tmr) > (pcb->keep_idle + pcb->keep_cnt_sent * TCP_KEEP_INTVL(pcb))/ TCP_SLOW_INTERVAL){tcp_keepalive(pcb);pcb->keep_cnt_sent++;}}/* If this PCB has queued out of sequence data, but has beeninactive for too long, will drop the data (it will eventuallybe retransmitted). */if (pcb->ooseq != NULL &&(u32_t)tcp_ticks - pcb->tmr >= pcb->rto * TCP_OOSEQ_TIMEOUT) {tcp_segs_free(pcb->ooseq);pcb->ooseq = NULL;}/* Check if this PCB has stayed too long in SYN-RCVD */if (pcb->state == SYN_RCVD) {if ((u32_t)(tcp_ticks - pcb->tmr) >TCP_SYN_RCVD_TIMEOUT / TCP_SLOW_INTERVAL) {++pcb_remove;}}/* Check if this PCB has stayed too long in LAST-ACK */if (pcb->state == LAST_ACK) {if ((u32_t)(tcp_ticks - pcb->tmr) > 2 * TCP_MSL / TCP_SLOW_INTERVAL) {++pcb_remove;}}/* If the PCB should be removed, do it. */if (pcb_remove) {struct tcp_pcb *pcb2;tcp_err_fn err_fn;void *err_arg;tcp_pcb_purge(pcb);/* Remove PCB from tcp_active_pcbs list. */if (prev != NULL) {prev->next = pcb->next;} else {/* This PCB was the first. */tcp_active_pcbs = pcb->next;}if (pcb_reset) {tcp_rst(pcb->snd_nxt, pcb->rcv_nxt, &pcb->local_ip, &pcb->remote_ip,pcb->local_port, pcb->remote_port);}err_fn = pcb->errf;err_arg = pcb->callback_arg;pcb2 = pcb;pcb = pcb->next;memp_free(MEMP_TCP_PCB, pcb2);tcp_active_pcbs_changed = 0;TCP_EVENT_ERR(err_fn, err_arg, ERR_ABRT);if (tcp_active_pcbs_changed) {goto tcp_slowtmr_start;}} else {/* get the 'next' element now and work with 'prev' below (in case of abort) */prev = pcb;pcb = pcb->next;/* We check if we should poll the connection. */++prev->polltmr;if (prev->polltmr >= prev->pollinterval) {prev->polltmr = 0;tcp_active_pcbs_changed = 0;TCP_EVENT_POLL(prev, err);if (tcp_active_pcbs_changed) {goto tcp_slowtmr_start;}/* if err == ERR_ABRT, 'prev' is already deallocated */if (err == ERR_OK) {tcp_output(prev);}}}}/* Steps through all of the TIME-WAIT PCBs. */prev = NULL;pcb = tcp_tw_pcbs;while (pcb != NULL) {pcb_remove = 0;/* Check if this PCB has stayed long enough in TIME-WAIT */if ((u32_t)(tcp_ticks - pcb->tmr) > 2 * TCP_MSL / TCP_SLOW_INTERVAL) {++pcb_remove;}/* If the PCB should be removed, do it. */if (pcb_remove) {struct tcp_pcb *pcb2;tcp_pcb_purge(pcb);/* Remove PCB from tcp_tw_pcbs list. */if (prev != NULL) {prev->next = pcb->next;} else {/* This PCB was the first. */tcp_tw_pcbs = pcb->next;}pcb2 = pcb;pcb = pcb->next;memp_free(MEMP_TCP_PCB, pcb2);} else {prev = pcb;pcb = pcb->next;}} }

很容易看出,各個定時器的實現(xiàn)都是通過使用全局變量tcp_ticks與tmr字段的差值來實現(xiàn)的,當TCP進入某個狀態(tài)時,就會將控制塊tmr字段設(shè)置為以前的全局時鐘tcp_ticks的值,所以上面的差值可以有效表示出TCP處于某個狀態(tài)的時間。各定時器超時后的處理也很類似,即將變量pcb_remove加1,pcb_remove變量是超時處理中最核心的變量,當針對某個控制塊做完超時判斷后,函數(shù)通過判斷pcb_remove的值來處理TCP控制塊,當pcb_remove值大于1時,則表示該控制塊上有超時事件發(fā)生,該控制塊或被刪除或被掛起。

LwIP中包含兩個定時器相關(guān)函數(shù):一個是上述周期在500ms的慢速定時器函數(shù)tcp_slowtmr,它完成了基本所有TCP需要實現(xiàn)的定時功能;第二個是周期為250ms的快速定時器函數(shù)tcp_fasttmr,它完成的一個重要功能是讓連接上被延遲的ACK立即發(fā)送出去,同時未被成功遞交的數(shù)據(jù)也在這里被遞交,tcp_fasttmr的實現(xiàn)代碼如下:

// rt-thread\components\net\lwip-1.4.1\src\core\tcp.c /*** Is called every TCP_FAST_INTERVAL (250 ms) and process data previously* "refused" by upper layer (application) and sends delayed ACKs.** Automatically called from tcp_tmr().*/ void tcp_fasttmr(void) {struct tcp_pcb *pcb;++tcp_timer_ctr;tcp_fasttmr_start:pcb = tcp_active_pcbs;while(pcb != NULL) {if (pcb->last_timer != tcp_timer_ctr) {struct tcp_pcb *next;pcb->last_timer = tcp_timer_ctr;/* send delayed ACKs */if (pcb->flags & TF_ACK_DELAY) {tcp_ack_now(pcb);tcp_output(pcb);pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW);}next = pcb->next;/* If there is data which was previously "refused" by upper layer */if (pcb->refused_data != NULL) {tcp_active_pcbs_changed = 0;tcp_process_refused_data(pcb);if (tcp_active_pcbs_changed) {/* application callback has changed the pcb list: restart the loop */goto tcp_fasttmr_start;}}pcb = next;}} }

為了實現(xiàn)TCP的功能,TCP的上述兩個定時器函數(shù)需要被周期性的調(diào)用,在LwIP的實現(xiàn)中,內(nèi)核需要以250ms為周期調(diào)用tcp_tmr,這個函數(shù)會自動完成對tcp_slowtmr和tcp_fasttmr的調(diào)用。為了便于用戶程序的編寫,內(nèi)核已經(jīng)將tcp_timer以及其他所有定時調(diào)用函數(shù)封裝到了sys_check_timeouts中,因此在沒有操作系統(tǒng)模擬層的支持下,應用程序應至少每隔250ms調(diào)用sys_check_timeouts一次,以保證內(nèi)核機制的正常工作。下面給出tcp_timer的實現(xiàn)代碼:

// rt-thread\components\net\lwip-1.4.1\src\core\tcp.c/** Timer counter to handle calling slow-timer from tcp_tmr() */ static u8_t tcp_timer;/*** Called periodically to dispatch TCP timers.*/ void tcp_tmr(void) {/* Call tcp_fasttmr() every 250 ms */tcp_fasttmr();if (++tcp_timer & 1) {/* Call tcp_tmr() every 500 ms, i.e., every other timertcp_tmr() is called. */tcp_slowtmr();} }

2.5 SYN攻擊

SYN洪水攻擊是目前被廣泛使用的一種基于TCP的DDos攻擊技術(shù),通常受攻擊的機器是網(wǎng)絡(luò)中服務固定功能的TCP服務器,由于它們的端口號和IP地址都很容易得到,所以它們很容易成為黑客攻擊的對象。這種攻擊過程可以用前面介紹的tcp_listen_input的原理來解釋:當服務器接收到一個連接請求后,它無法判斷客戶端的合法性;另一方面,服務器需要為新連接申請一個控制塊內(nèi)存空間,然后向?qū)Ψ椒祷谹CK+SYN報文,并等待對方的握手ACK返回;如果這個連接請求是惡意者發(fā)起的,那么服務器永遠等不到這個ACK返回(SYN握手報文中的源IP地址是偽造的),服務器必須將這個連接維持足夠長的時間后,服務器才能清除它認為無效的連接。

假如網(wǎng)絡(luò)黑客控制了大量的計算機,并同時向服務器發(fā)送SYN請求,則此時服務器將占用大量的內(nèi)存空間和時間在等待對方的ACK返回上,而顯然這種等待都是徒勞的。如果這樣的連接達到了很大的數(shù)目,系統(tǒng)沒有更多的資源來響應新連接,那么正常用戶的TCP連接也就無法建立,服務器將無法提供正常的訪問服務。TCP協(xié)議連接建立握手過程存在的缺陷,注定了網(wǎng)絡(luò)中的TCP服務器很容易受到SYN攻擊。

更多文章

  • 《qemu-vexpress-a9 for LwIP stack》
  • 《TCP/IP協(xié)議棧之LwIP(五)— 網(wǎng)絡(luò)傳輸管理之UDP協(xié)議》
  • 《TCP/IP協(xié)議棧之LwIP(七)— 內(nèi)核定時事件管理》

總結(jié)

以上是生活随笔為你收集整理的TCP/IP协议栈之LwIP(六)---网络传输管理之TCP协议的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。

永久黄网站色视频免费直播 | 中文无码伦av中文字幕 | 国产精品18久久久久久麻辣 | 天天躁夜夜躁狠狠是什么心态 | 亚洲精品国产品国语在线观看 | 国产精品人妻一区二区三区四 | 国产成人无码a区在线观看视频app | 欧美第一黄网免费网站 | 亚洲 激情 小说 另类 欧美 | 天下第一社区视频www日本 | 国产人妻久久精品二区三区老狼 | 国产精品爱久久久久久久 | 日韩av激情在线观看 | 国产女主播喷水视频在线观看 | 国产又爽又猛又粗的视频a片 | 精品一区二区不卡无码av | 无码免费一区二区三区 | 激情内射亚州一区二区三区爱妻 | 国产又爽又猛又粗的视频a片 | 日日碰狠狠丁香久燥 | 久久久成人毛片无码 | 精品欧美一区二区三区久久久 | 久久国产精品二国产精品 | 又大又黄又粗又爽的免费视频 | 婷婷五月综合激情中文字幕 | 亚洲国产成人a精品不卡在线 | 女高中生第一次破苞av | 久久久国产精品无码免费专区 | 午夜福利一区二区三区在线观看 | 中文字幕无码乱人伦 | 国产无遮挡又黄又爽又色 | 亚洲人成网站在线播放942 | 丰满少妇弄高潮了www | 水蜜桃av无码 | 蜜臀av在线播放 久久综合激激的五月天 | 欧美性黑人极品hd | 日本精品久久久久中文字幕 | 无码国模国产在线观看 | 国产手机在线αⅴ片无码观看 | 国产人妻大战黑人第1集 | 久久久久久久女国产乱让韩 | 国产人妖乱国产精品人妖 | 丰满护士巨好爽好大乳 | 午夜免费福利小电影 | 男人扒开女人内裤强吻桶进去 | 婷婷色婷婷开心五月四房播播 | 国内揄拍国内精品少妇国语 | 人妻无码αv中文字幕久久琪琪布 | 丰满护士巨好爽好大乳 | 西西人体www44rt大胆高清 | 国产无套内射久久久国产 | 少妇邻居内射在线 | 九一九色国产 | 一区二区传媒有限公司 | 亚洲精品久久久久avwww潮水 | 中文无码成人免费视频在线观看 | 国产成人无码av片在线观看不卡 | 一区二区三区高清视频一 | 亚洲中文字幕久久无码 | 国产精品久久久久久久9999 | 午夜不卡av免费 一本久久a久久精品vr综合 | 亚洲一区av无码专区在线观看 | 极品嫩模高潮叫床 | 亚洲国产成人av在线观看 | 人妻少妇精品视频专区 | aⅴ在线视频男人的天堂 | 久久亚洲a片com人成 | 波多野结衣高清一区二区三区 | 亚洲国产精品久久久天堂 | 久久国产36精品色熟妇 | 国产精品手机免费 | 欧美午夜特黄aaaaaa片 | 国产亚洲精品久久久ai换 | 国产成人精品久久亚洲高清不卡 | 人妻夜夜爽天天爽三区 | 一本久道久久综合婷婷五月 | 牛和人交xxxx欧美 | 乱码午夜-极国产极内射 | 欧美日韩一区二区免费视频 | 精品无人区无码乱码毛片国产 | 亚洲精品无码人妻无码 | 亚洲中文字幕久久无码 | 久久精品一区二区三区四区 | 午夜免费福利小电影 | 久久99精品久久久久久 | 性色av无码免费一区二区三区 | 亚洲狠狠婷婷综合久久 | 国产av人人夜夜澡人人爽麻豆 | 一本色道久久综合亚洲精品不卡 | 人人爽人人澡人人高潮 | 亚洲中文字幕在线无码一区二区 | 在线成人www免费观看视频 | 在教室伦流澡到高潮hnp视频 | 欧美精品在线观看 | 国产精品美女久久久 | 亚洲啪av永久无码精品放毛片 | 丰满少妇熟乱xxxxx视频 | 无码毛片视频一区二区本码 | 国产乱人伦偷精品视频 | 51国偷自产一区二区三区 | 欧美三级不卡在线观看 | 亚洲精品中文字幕 | 天天拍夜夜添久久精品大 | 人妻无码αv中文字幕久久琪琪布 | 2020久久超碰国产精品最新 | 久久精品人人做人人综合 | 两性色午夜免费视频 | 麻豆国产97在线 | 欧洲 | 久久久久亚洲精品男人的天堂 | 亚洲精品一区二区三区在线观看 | 日本在线高清不卡免费播放 | 无码国产乱人伦偷精品视频 | 日本欧美一区二区三区乱码 | 久久99国产综合精品 | av无码久久久久不卡免费网站 | 中文精品无码中文字幕无码专区 | 少妇太爽了在线观看 | 国产亚洲精品久久久久久 | 中文字幕无码av波多野吉衣 | 无人区乱码一区二区三区 | 一区二区三区高清视频一 | 天天av天天av天天透 | 午夜男女很黄的视频 | 国产精品va在线播放 | 人妻无码αv中文字幕久久琪琪布 | 76少妇精品导航 | 中文字幕人妻丝袜二区 | 风流少妇按摩来高潮 | 亚洲精品一区国产 | 在线播放无码字幕亚洲 | 国产精品人人爽人人做我的可爱 | 黑人大群体交免费视频 | 国产激情无码一区二区app | 亚洲国产精品久久人人爱 | 俄罗斯老熟妇色xxxx | 国产猛烈高潮尖叫视频免费 | 狠狠综合久久久久综合网 | 国产又粗又硬又大爽黄老大爷视 | 99久久99久久免费精品蜜桃 | 日韩在线不卡免费视频一区 | 日韩欧美中文字幕公布 | 黑人玩弄人妻中文在线 | 人人妻人人澡人人爽欧美精品 | 久久久精品456亚洲影院 | 亚洲a无码综合a国产av中文 | 亚洲色偷偷偷综合网 | 成人欧美一区二区三区黑人免费 | 精品无码国产一区二区三区av | 曰本女人与公拘交酡免费视频 | 日韩欧美中文字幕公布 | 狂野欧美激情性xxxx | 中文字幕无线码免费人妻 | 福利一区二区三区视频在线观看 | 女高中生第一次破苞av | 欧美性生交活xxxxxdddd | www成人国产高清内射 | 九九久久精品国产免费看小说 | 夫妻免费无码v看片 | 国产精华av午夜在线观看 | 国产电影无码午夜在线播放 | 国产麻豆精品一区二区三区v视界 | 久激情内射婷内射蜜桃人妖 | 强伦人妻一区二区三区视频18 | 中文亚洲成a人片在线观看 | 麻豆国产人妻欲求不满谁演的 | 夜夜夜高潮夜夜爽夜夜爰爰 | 风流少妇按摩来高潮 | 中文字幕无码av激情不卡 | 亚洲精品久久久久久一区二区 | 两性色午夜免费视频 | 99在线 | 亚洲 | 在线欧美精品一区二区三区 | 少妇无码一区二区二三区 | 精品乱码久久久久久久 | 亲嘴扒胸摸屁股激烈网站 | 四虎影视成人永久免费观看视频 | 2020久久超碰国产精品最新 | 国产亚洲精品久久久ai换 | 高潮喷水的毛片 | 少妇高潮一区二区三区99 | 久久久久免费看成人影片 | ass日本丰满熟妇pics | 国产精品久久国产三级国 | 国产亚洲视频中文字幕97精品 | 性色av无码免费一区二区三区 | 未满小14洗澡无码视频网站 | 亚洲熟妇色xxxxx欧美老妇 | 欧美日本日韩 | 牛和人交xxxx欧美 | 婷婷色婷婷开心五月四房播播 | 久久精品中文字幕一区 | 巨爆乳无码视频在线观看 | 男人的天堂2018无码 | 欧美日韩一区二区免费视频 | 久久精品国产日本波多野结衣 | 中文字幕乱码人妻二区三区 | 全黄性性激高免费视频 | 在线成人www免费观看视频 | 久久国产劲爆∧v内射 | 亚洲国精产品一二二线 | 野狼第一精品社区 | 无码人妻精品一区二区三区下载 | 97精品国产97久久久久久免费 | 免费无码午夜福利片69 | 国产精品久久久久无码av色戒 | 日产精品99久久久久久 | 色窝窝无码一区二区三区色欲 | 午夜精品一区二区三区的区别 | 精品国产一区二区三区四区 | 伊在人天堂亚洲香蕉精品区 | 国产黄在线观看免费观看不卡 | 老太婆性杂交欧美肥老太 | 国产精品无码一区二区桃花视频 | 强伦人妻一区二区三区视频18 | 日本一卡2卡3卡四卡精品网站 | 青青青爽视频在线观看 | 少妇高潮喷潮久久久影院 | 国产精品高潮呻吟av久久 | 久久久久99精品成人片 | 人妻少妇精品无码专区动漫 | 久久久亚洲欧洲日产国码αv | 天天躁夜夜躁狠狠是什么心态 | 国产av无码专区亚洲awww | 国产在线无码精品电影网 | 亚洲狠狠婷婷综合久久 | 中文字幕中文有码在线 | 我要看www免费看插插视频 | 97精品国产97久久久久久免费 | 在线成人www免费观看视频 | 少女韩国电视剧在线观看完整 | 东北女人啪啪对白 | 国产又爽又黄又刺激的视频 | 国产偷自视频区视频 | 中文久久乱码一区二区 | 欧美精品国产综合久久 | 熟女体下毛毛黑森林 | 无码国产激情在线观看 | 亚洲爆乳精品无码一区二区三区 | 精品久久久中文字幕人妻 | 精品无码一区二区三区的天堂 | 久久国内精品自在自线 | 又粗又大又硬毛片免费看 | 日韩av无码一区二区三区不卡 | 鲁一鲁av2019在线 | 中国女人内谢69xxxxxa片 | 亚洲人亚洲人成电影网站色 | 丰满人妻翻云覆雨呻吟视频 | 色婷婷av一区二区三区之红樱桃 | 人妻少妇精品视频专区 | 亚洲一区二区三区四区 | 欧美35页视频在线观看 | 最近中文2019字幕第二页 | 欧美精品无码一区二区三区 | 丰满人妻被黑人猛烈进入 | 国产口爆吞精在线视频 | 人人妻人人澡人人爽欧美精品 | 色欲av亚洲一区无码少妇 | 国产亚洲tv在线观看 | 天堂а√在线中文在线 | 狂野欧美性猛交免费视频 | 综合激情五月综合激情五月激情1 | 亚洲欧美中文字幕5发布 | 搡女人真爽免费视频大全 | 国产97在线 | 亚洲 | 欧美兽交xxxx×视频 | 中文精品无码中文字幕无码专区 | 国产色视频一区二区三区 | 国产成人无码区免费内射一片色欲 | 天干天干啦夜天干天2017 | 欧美性生交活xxxxxdddd | 黑人大群体交免费视频 | 中文字幕无码日韩专区 | 一个人看的www免费视频在线观看 | 欧美性猛交xxxx富婆 | 久久成人a毛片免费观看网站 | 国产成人一区二区三区别 | 综合激情五月综合激情五月激情1 | 任你躁在线精品免费 | 久久国产精品偷任你爽任你 | 久久亚洲精品中文字幕无男同 | 久久亚洲a片com人成 | 国产精品手机免费 | 亚洲欧美日韩成人高清在线一区 | 在线看片无码永久免费视频 | 亚洲阿v天堂在线 | 国产精品久久久久7777 | 欧洲熟妇精品视频 | 精品偷自拍另类在线观看 | 中文字幕无码热在线视频 | 亲嘴扒胸摸屁股激烈网站 | 国产在线精品一区二区三区直播 | 内射巨臀欧美在线视频 | 亚洲日韩av片在线观看 | 亚洲精品国产精品乱码视色 | 美女毛片一区二区三区四区 | 欧美一区二区三区视频在线观看 | 人人妻人人澡人人爽欧美一区九九 | 激情爆乳一区二区三区 | 天干天干啦夜天干天2017 | 国内揄拍国内精品少妇国语 | 国产一区二区三区日韩精品 | 无码精品国产va在线观看dvd | 精品一二三区久久aaa片 | 国产99久久精品一区二区 | 日本成熟视频免费视频 | 国产精品鲁鲁鲁 | 欧洲欧美人成视频在线 | 午夜福利一区二区三区在线观看 | 丰满肥臀大屁股熟妇激情视频 | 性欧美牲交在线视频 | 亚洲自偷自偷在线制服 | 国产午夜亚洲精品不卡下载 | 国产熟女一区二区三区四区五区 | 精品欧美一区二区三区久久久 | 在线观看国产午夜福利片 | 97精品人妻一区二区三区香蕉 | 色五月丁香五月综合五月 | 亚洲精品国产精品乱码视色 | 国产三级久久久精品麻豆三级 | 国产农村妇女aaaaa视频 撕开奶罩揉吮奶头视频 | 中文字幕人妻无码一夲道 | 亚洲va中文字幕无码久久不卡 | 性欧美疯狂xxxxbbbb | 日韩人妻无码一区二区三区久久99 | 97精品人妻一区二区三区香蕉 | 亚洲精品综合一区二区三区在线 | 欧美精品一区二区精品久久 | 国产99久久精品一区二区 | 国内精品久久毛片一区二区 | 少妇无码吹潮 | 免费无码一区二区三区蜜桃大 | 国产网红无码精品视频 | 免费无码午夜福利片69 | 18黄暴禁片在线观看 | 中文字幕人成乱码熟女app | 亚洲中文字幕va福利 | 中文字幕av日韩精品一区二区 | 中文字幕无码日韩专区 | 国产精品怡红院永久免费 | 日本乱偷人妻中文字幕 | 久久精品国产大片免费观看 | 人人妻人人藻人人爽欧美一区 | 少妇高潮喷潮久久久影院 | 久久久久久亚洲精品a片成人 | 久久人人爽人人人人片 | 亚洲一区二区三区含羞草 | 亚洲经典千人经典日产 | 香蕉久久久久久av成人 | 一区二区三区乱码在线 | 欧洲 | 中文字幕 人妻熟女 | 牲欲强的熟妇农村老妇女视频 | 欧美性生交xxxxx久久久 | 在线亚洲高清揄拍自拍一品区 | 色一情一乱一伦一区二区三欧美 | 精品偷拍一区二区三区在线看 | 久久久久成人片免费观看蜜芽 | 无码免费一区二区三区 | 在线a亚洲视频播放在线观看 | 国产精品资源一区二区 | 青青青手机频在线观看 | 久久精品视频在线看15 | 久久综合给合久久狠狠狠97色 | 久久久久人妻一区精品色欧美 | 亚洲国产成人a精品不卡在线 | 久久久久久av无码免费看大片 | 久激情内射婷内射蜜桃人妖 | 国产肉丝袜在线观看 | 波多野结衣乳巨码无在线观看 | 无遮挡国产高潮视频免费观看 | 性开放的女人aaa片 | 丰满妇女强制高潮18xxxx | 亚洲中文字幕乱码av波多ji | 久久精品成人欧美大片 | 性欧美videos高清精品 | 国产精品久久久午夜夜伦鲁鲁 | 四虎影视成人永久免费观看视频 | 国产激情艳情在线看视频 | 成人欧美一区二区三区 | 最新国产乱人伦偷精品免费网站 | 麻豆蜜桃av蜜臀av色欲av | 日本一卡二卡不卡视频查询 | 日韩视频 中文字幕 视频一区 | 无码中文字幕色专区 | 大乳丰满人妻中文字幕日本 | 国产又爽又猛又粗的视频a片 | av无码久久久久不卡免费网站 | 亚洲熟女一区二区三区 | 亚无码乱人伦一区二区 | 色狠狠av一区二区三区 | 亚洲色成人中文字幕网站 | 欧美阿v高清资源不卡在线播放 | 久久国语露脸国产精品电影 | 人人妻人人澡人人爽欧美一区九九 | 无码av最新清无码专区吞精 | 国产精品嫩草久久久久 | 成人免费视频视频在线观看 免费 | 午夜福利不卡在线视频 | www成人国产高清内射 | 色情久久久av熟女人妻网站 | 亚洲综合在线一区二区三区 | 亚洲啪av永久无码精品放毛片 | 亚洲人成影院在线观看 | 欧美肥老太牲交大战 | 日韩视频 中文字幕 视频一区 | 日本精品人妻无码77777 天堂一区人妻无码 | 亚洲国产精品无码久久久久高潮 | 国产成人精品久久亚洲高清不卡 | 国产av一区二区三区最新精品 | 精品少妇爆乳无码av无码专区 | 国产亚洲视频中文字幕97精品 | 激情内射亚州一区二区三区爱妻 | 无码人妻丰满熟妇区毛片18 | 欧美国产日产一区二区 | 波多野结衣aⅴ在线 | 色一情一乱一伦 | 亚洲国产精品久久久天堂 | 男女超爽视频免费播放 | 欧美激情综合亚洲一二区 | 国产国语老龄妇女a片 | 88国产精品欧美一区二区三区 | 国内老熟妇对白xxxxhd | 久久精品无码一区二区三区 | 免费男性肉肉影院 | 欧美自拍另类欧美综合图片区 | 一本久久伊人热热精品中文字幕 | 麻豆国产人妻欲求不满 | 在线观看欧美一区二区三区 | 强辱丰满人妻hd中文字幕 | 婷婷综合久久中文字幕蜜桃三电影 | 欧美 日韩 人妻 高清 中文 | 97夜夜澡人人爽人人喊中国片 | 熟女少妇在线视频播放 | 亚欧洲精品在线视频免费观看 | 超碰97人人做人人爱少妇 | 好男人社区资源 | 久久亚洲日韩精品一区二区三区 | 中文亚洲成a人片在线观看 | 亚洲狠狠婷婷综合久久 | 激情国产av做激情国产爱 | 亚洲色欲色欲欲www在线 | 欧美刺激性大交 | 国产福利视频一区二区 | 欧美老妇与禽交 | 一本色道久久综合亚洲精品不卡 | 国产乡下妇女做爰 | 午夜福利不卡在线视频 | 欧美老妇交乱视频在线观看 | 国产亲子乱弄免费视频 | 青青青手机频在线观看 | 天堂亚洲免费视频 | 日本肉体xxxx裸交 | 国产97色在线 | 免 | 无码国内精品人妻少妇 | 国产精品久久久久无码av色戒 | 久久精品女人的天堂av | 少妇人妻av毛片在线看 | 露脸叫床粗话东北少妇 | 亚洲色大成网站www | 国产做国产爱免费视频 | 内射白嫩少妇超碰 | 亚洲中文字幕久久无码 | 国产精品自产拍在线观看 | 国产片av国语在线观看 | 鲁鲁鲁爽爽爽在线视频观看 | 少妇被粗大的猛进出69影院 | 兔费看少妇性l交大片免费 | 2020久久香蕉国产线看观看 | 无码人妻精品一区二区三区下载 | 九月婷婷人人澡人人添人人爽 | 色五月丁香五月综合五月 | 在线 国产 欧美 亚洲 天堂 | 日韩在线不卡免费视频一区 | 欧美阿v高清资源不卡在线播放 | 永久黄网站色视频免费直播 | 国产精品久久久av久久久 | 爱做久久久久久 | 99久久99久久免费精品蜜桃 | 红桃av一区二区三区在线无码av | 精品国产一区二区三区四区在线看 | 精品无码av一区二区三区 | 人人澡人人妻人人爽人人蜜桃 | 色综合久久久久综合一本到桃花网 | 久久五月精品中文字幕 | 图片区 小说区 区 亚洲五月 | 亚洲精品一区国产 | 4hu四虎永久在线观看 | 久久精品中文闷骚内射 | 青春草在线视频免费观看 | 国产精品igao视频网 | 日本免费一区二区三区最新 | 粗大的内捧猛烈进出视频 | 国产偷自视频区视频 | 成人亚洲精品久久久久 | 欧美 亚洲 国产 另类 | 国产精品久久久一区二区三区 | 骚片av蜜桃精品一区 | 天天拍夜夜添久久精品大 | 一本精品99久久精品77 | 精品国产青草久久久久福利 | 国产精品国产自线拍免费软件 | 麻豆国产人妻欲求不满 | 人人妻人人藻人人爽欧美一区 | 婷婷丁香五月天综合东京热 | 国产乱码精品一品二品 | 俺去俺来也在线www色官网 | 国内精品久久久久久中文字幕 | 久久久久久国产精品无码下载 | 亚洲一区二区三区香蕉 | 国产成人无码专区 | 欧美35页视频在线观看 | 久久亚洲精品中文字幕无男同 | 熟妇人妻无乱码中文字幕 | 久久精品一区二区三区四区 | 国产精品-区区久久久狼 | 国产精品久久国产三级国 | 亚洲国产精品久久久天堂 | 免费无码肉片在线观看 | 亚洲国产一区二区三区在线观看 | 波多野结衣aⅴ在线 | 在教室伦流澡到高潮hnp视频 | 蜜臀av在线播放 久久综合激激的五月天 | 国精品人妻无码一区二区三区蜜柚 | 99国产欧美久久久精品 | 午夜成人1000部免费视频 | 国产一区二区三区精品视频 | 日韩人妻少妇一区二区三区 | 欧美丰满老熟妇xxxxx性 | 久久www免费人成人片 | 精品 日韩 国产 欧美 视频 | 欧美老熟妇乱xxxxx | 亚洲七七久久桃花影院 | 高中生自慰www网站 | 国产成人无码a区在线观看视频app | 99久久精品日本一区二区免费 | 精品久久综合1区2区3区激情 | 午夜精品一区二区三区的区别 | 久热国产vs视频在线观看 | 中文字幕无码av激情不卡 | 国产片av国语在线观看 | 精品国产乱码久久久久乱码 | 十八禁真人啪啪免费网站 | 久久精品视频在线看15 | 乱码av麻豆丝袜熟女系列 | 荫蒂添的好舒服视频囗交 | 久久99精品久久久久久 | 国产成人无码一二三区视频 | 国产成人一区二区三区别 | 国产性生交xxxxx无码 | 国产女主播喷水视频在线观看 | 初尝人妻少妇中文字幕 | 日本va欧美va欧美va精品 | 永久免费精品精品永久-夜色 | 国产精品99久久精品爆乳 | 国产 浪潮av性色四虎 | 欧美成人午夜精品久久久 | 在线播放无码字幕亚洲 | 97精品人妻一区二区三区香蕉 | 亚洲a无码综合a国产av中文 | 国产免费久久精品国产传媒 | 一区二区传媒有限公司 | 日韩少妇内射免费播放 | 国产性猛交╳xxx乱大交 国产精品久久久久久无码 欧洲欧美人成视频在线 | 成人无码精品1区2区3区免费看 | 激情爆乳一区二区三区 | 精品成在人线av无码免费看 | 成人综合网亚洲伊人 | 77777熟女视频在线观看 а天堂中文在线官网 | 久久久精品人妻久久影视 | 好屌草这里只有精品 | 蜜臀aⅴ国产精品久久久国产老师 | 国产精品高潮呻吟av久久4虎 | 欧美日本精品一区二区三区 | 欧美freesex黑人又粗又大 | 国产超碰人人爽人人做人人添 | 亚洲国产精品无码一区二区三区 | 国产人妻久久精品二区三区老狼 | 九九久久精品国产免费看小说 | 亚洲成熟女人毛毛耸耸多 | 小鲜肉自慰网站xnxx | 日韩欧美中文字幕在线三区 | 国产精品爱久久久久久久 | 中文字幕无码免费久久99 | 午夜男女很黄的视频 | 精品成在人线av无码免费看 | 久久zyz资源站无码中文动漫 | 亚洲国产av美女网站 | 亚洲熟女一区二区三区 | aa片在线观看视频在线播放 | 午夜成人1000部免费视频 | 久久精品国产精品国产精品污 | 亚洲精品一区二区三区在线 | 亚洲毛片av日韩av无码 | 小泽玛莉亚一区二区视频在线 | 欧美变态另类xxxx | 午夜男女很黄的视频 | 少妇激情av一区二区 | 亚洲欧洲日本无在线码 | 日本饥渴人妻欲求不满 | 国产精品美女久久久久av爽李琼 | 天干天干啦夜天干天2017 | 国产色视频一区二区三区 | 午夜精品一区二区三区在线观看 | 激情内射亚州一区二区三区爱妻 | 人妻互换免费中文字幕 | 国产女主播喷水视频在线观看 | 亚洲小说春色综合另类 | 欧美人与善在线com | 亚洲の无码国产の无码步美 | 亚洲а∨天堂久久精品2021 | 国产无套粉嫩白浆在线 | 久久久www成人免费毛片 | 狠狠色色综合网站 | 亚洲人亚洲人成电影网站色 | 中文字幕无码视频专区 | 亚洲区欧美区综合区自拍区 | 天堂一区人妻无码 | 无码一区二区三区在线观看 | 国产成人精品必看 | 国产 精品 自在自线 | 300部国产真实乱 | 又湿又紧又大又爽a视频国产 | 伊人色综合久久天天小片 | 亚洲国产日韩a在线播放 | 亚洲成色www久久网站 | 国产精品a成v人在线播放 | 一区二区三区乱码在线 | 欧洲 | 国产精品人人爽人人做我的可爱 | 国产手机在线αⅴ片无码观看 | 青青久在线视频免费观看 | 巨爆乳无码视频在线观看 | 好爽又高潮了毛片免费下载 | 国内少妇偷人精品视频 | 好爽又高潮了毛片免费下载 | 欧美放荡的少妇 | 免费视频欧美无人区码 | 欧美黑人性暴力猛交喷水 | 中文亚洲成a人片在线观看 | 人妻熟女一区 | 日日躁夜夜躁狠狠躁 | 18无码粉嫩小泬无套在线观看 | 狂野欧美性猛xxxx乱大交 | 无码国模国产在线观看 | 乌克兰少妇性做爰 | 欧美 日韩 人妻 高清 中文 | 中文无码成人免费视频在线观看 | 欧美freesex黑人又粗又大 | 日日摸日日碰夜夜爽av | 国产精品视频免费播放 | 亚洲精品一区国产 | 美女毛片一区二区三区四区 | 老司机亚洲精品影院无码 | 亚洲欧美综合区丁香五月小说 | 欧美丰满少妇xxxx性 | 四虎国产精品一区二区 | 亚洲中文字幕乱码av波多ji | 日日摸天天摸爽爽狠狠97 | 丰满人妻被黑人猛烈进入 | 亚洲乱亚洲乱妇50p | 中文字幕久久久久人妻 | 精品无码国产自产拍在线观看蜜 | 漂亮人妻洗澡被公强 日日躁 | 18黄暴禁片在线观看 | 日本高清一区免费中文视频 | 夜夜躁日日躁狠狠久久av | 成人无码影片精品久久久 | 成 人影片 免费观看 | 香蕉久久久久久av成人 | 婷婷综合久久中文字幕蜜桃三电影 | 成年美女黄网站色大免费视频 | 亚洲欧美日韩国产精品一区二区 | 婷婷综合久久中文字幕蜜桃三电影 | 欧美 丝袜 自拍 制服 另类 | 免费无码午夜福利片69 | 亚洲一区二区三区香蕉 | 天干天干啦夜天干天2017 | 熟妇人妻无乱码中文字幕 | 国产肉丝袜在线观看 | 成人试看120秒体验区 | 娇妻被黑人粗大高潮白浆 | 天堂亚洲免费视频 | 亚洲爆乳无码专区 | 久久亚洲日韩精品一区二区三区 | 日韩精品无码免费一区二区三区 | 亚洲综合久久一区二区 | 欧美丰满少妇xxxx性 | 色综合久久久久综合一本到桃花网 | 成人精品一区二区三区中文字幕 | 波多野结衣乳巨码无在线观看 | 午夜男女很黄的视频 | 国产69精品久久久久app下载 | 老子影院午夜伦不卡 | 亚洲а∨天堂久久精品2021 | 中文字幕人妻无码一区二区三区 | 亚洲成av人综合在线观看 | 老太婆性杂交欧美肥老太 | 欧美人妻一区二区三区 | 国产精品自产拍在线观看 | 77777熟女视频在线观看 а天堂中文在线官网 | 日日夜夜撸啊撸 | 久久精品视频在线看15 | 永久免费观看美女裸体的网站 | 东京热无码av男人的天堂 | 色婷婷久久一区二区三区麻豆 | 国产av久久久久精东av | 亚洲精品鲁一鲁一区二区三区 | 国产精品久久国产三级国 | 免费观看的无遮挡av | 久久 国产 尿 小便 嘘嘘 | 欧洲美熟女乱又伦 | 又大又硬又爽免费视频 | 欧美人与善在线com | www国产亚洲精品久久网站 | 国产精品国产三级国产专播 | 国产av无码专区亚洲a∨毛片 | 成人无码影片精品久久久 | 美女毛片一区二区三区四区 | 亚洲日韩乱码中文无码蜜桃臀网站 | 永久免费精品精品永久-夜色 | 久久亚洲中文字幕精品一区 | 免费男性肉肉影院 | 欧洲欧美人成视频在线 | 国产人妻精品一区二区三区不卡 | 婷婷色婷婷开心五月四房播播 | 国产日产欧产精品精品app | 国产乱人无码伦av在线a | 亚洲自偷精品视频自拍 | 国产美女精品一区二区三区 | 精品aⅴ一区二区三区 | 18无码粉嫩小泬无套在线观看 | 久久久精品人妻久久影视 | 欧美大屁股xxxxhd黑色 | 少妇人妻大乳在线视频 | a片在线免费观看 | 亚洲成av人片在线观看无码不卡 | 色偷偷av老熟女 久久精品人妻少妇一区二区三区 | 中文字幕无码人妻少妇免费 | 荫蒂添的好舒服视频囗交 | 99国产欧美久久久精品 | 久久综合给合久久狠狠狠97色 | 国产精华av午夜在线观看 | 国内少妇偷人精品视频免费 | 99国产欧美久久久精品 | 国产特级毛片aaaaaa高潮流水 | 国产艳妇av在线观看果冻传媒 | 国产成人无码av在线影院 | 午夜性刺激在线视频免费 | 娇妻被黑人粗大高潮白浆 | 国精品人妻无码一区二区三区蜜柚 | 窝窝午夜理论片影院 | 任你躁国产自任一区二区三区 | 四虎永久在线精品免费网址 | 国产极品视觉盛宴 | 无码av免费一区二区三区试看 | 永久免费观看美女裸体的网站 | 亚洲欧美国产精品专区久久 | 精品国产一区av天美传媒 | 国产人成高清在线视频99最全资源 | 伊人久久大香线蕉午夜 | 给我免费的视频在线观看 | 国产成人综合色在线观看网站 | 亚洲爆乳无码专区 | 四十如虎的丰满熟妇啪啪 | 日本一区二区更新不卡 | 日本xxxx色视频在线观看免费 | 精品国产青草久久久久福利 | 国内揄拍国内精品少妇国语 | 国产精品国产三级国产专播 | 久久精品成人欧美大片 | 亚洲一区二区三区 | 精品国产精品久久一区免费式 | 国产99久久精品一区二区 | 国产肉丝袜在线观看 | 成人一在线视频日韩国产 | 国产sm调教视频在线观看 | 久久久久成人精品免费播放动漫 | 好爽又高潮了毛片免费下载 | 波多野结衣av在线观看 | 亚洲经典千人经典日产 | 麻花豆传媒剧国产免费mv在线 | 日本高清一区免费中文视频 | 国产精品爱久久久久久久 | 麻豆国产97在线 | 欧洲 | yw尤物av无码国产在线观看 | 国产亚洲视频中文字幕97精品 | 午夜精品一区二区三区在线观看 | 波多野42部无码喷潮在线 | 窝窝午夜理论片影院 | 久久综合给合久久狠狠狠97色 | 日韩人妻无码一区二区三区久久99 | 欧洲极品少妇 | 国产偷抇久久精品a片69 | 久久久国产一区二区三区 | 久久 国产 尿 小便 嘘嘘 | 永久免费观看国产裸体美女 | 久久精品人人做人人综合试看 | 亚洲精品成人av在线 | 亚洲 另类 在线 欧美 制服 | 亚洲精品成a人在线观看 | 98国产精品综合一区二区三区 | 亚洲熟妇色xxxxx欧美老妇 | 精品人妻中文字幕有码在线 | 久久久久亚洲精品中文字幕 | 国产精品-区区久久久狼 | 成人无码精品1区2区3区免费看 | 波多野结衣av一区二区全免费观看 | 免费看男女做好爽好硬视频 | 亚洲毛片av日韩av无码 | 国产特级毛片aaaaaaa高清 | 亚洲aⅴ无码成人网站国产app | 国产九九九九九九九a片 | 日韩欧美群交p片內射中文 | 国产成人精品无码播放 | 欧美日韩一区二区三区自拍 | 成人片黄网站色大片免费观看 | 国产在线一区二区三区四区五区 | 亚洲伊人久久精品影院 | 天堂а√在线地址中文在线 | 精品国产福利一区二区 | 久久亚洲中文字幕无码 | 国产亚洲tv在线观看 | 精品国产一区av天美传媒 | 国产成人无码a区在线观看视频app | 国产精品无码一区二区三区不卡 | 久久精品国产一区二区三区肥胖 | 国产卡一卡二卡三 | 亚洲综合伊人久久大杳蕉 | 人人妻人人藻人人爽欧美一区 | 色婷婷av一区二区三区之红樱桃 | 日本www一道久久久免费榴莲 | 精品日本一区二区三区在线观看 | 少妇性l交大片欧洲热妇乱xxx | 97夜夜澡人人爽人人喊中国片 | 中文字幕人成乱码熟女app | 日日夜夜撸啊撸 | 久久精品中文闷骚内射 | 中文字幕色婷婷在线视频 | 欧美zoozzooz性欧美 | 亚洲自偷自拍另类第1页 | 自拍偷自拍亚洲精品被多人伦好爽 | 午夜时刻免费入口 | 中文字幕久久久久人妻 | 麻豆精产国品 | 美女毛片一区二区三区四区 | 精品人妻人人做人人爽 | 久久人人爽人人人人片 | 亚洲а∨天堂久久精品2021 | 国产精品亚洲а∨无码播放麻豆 | 丝袜 中出 制服 人妻 美腿 | 特黄特色大片免费播放器图片 | 四十如虎的丰满熟妇啪啪 | 亚洲aⅴ无码成人网站国产app | 国产成人无码av一区二区 | 免费中文字幕日韩欧美 | 中文字幕乱码中文乱码51精品 | 宝宝好涨水快流出来免费视频 | 女人被爽到呻吟gif动态图视看 | 天天摸天天透天天添 | 在线精品国产一区二区三区 | 亚洲 a v无 码免 费 成 人 a v | yw尤物av无码国产在线观看 | 日产精品99久久久久久 | 免费观看激色视频网站 | 亚洲精品国偷拍自产在线麻豆 | 久久久久免费看成人影片 | 成在人线av无码免费 | 成人一区二区免费视频 | 国产精品.xx视频.xxtv | 亚洲精品中文字幕久久久久 | 国产又爽又猛又粗的视频a片 | 亚洲成av人综合在线观看 | 国产成人综合在线女婷五月99播放 | 亚洲国产av美女网站 | 国产激情精品一区二区三区 | 亚洲の无码国产の无码步美 | 欧美性色19p | 欧美 亚洲 国产 另类 | 丁香花在线影院观看在线播放 | 女人高潮内射99精品 | 国产精品对白交换视频 | 国产农村妇女高潮大叫 | 欧美freesex黑人又粗又大 | 国产97色在线 | 免 | 精品无人国产偷自产在线 | 国产午夜亚洲精品不卡 | 国内丰满熟女出轨videos | 强伦人妻一区二区三区视频18 | 精品一区二区三区波多野结衣 | 国产舌乚八伦偷品w中 | 性欧美大战久久久久久久 | 中文字幕日韩精品一区二区三区 | 少妇被粗大的猛进出69影院 | 久久国产精品偷任你爽任你 | 少妇性l交大片欧洲热妇乱xxx | 欧美熟妇另类久久久久久不卡 | 国产亚洲精品久久久久久国模美 | 精品久久综合1区2区3区激情 | 性史性农村dvd毛片 | 国精产品一品二品国精品69xx | 美女黄网站人色视频免费国产 | 亚洲中文字幕在线无码一区二区 | 成人无码视频在线观看网站 | 内射爽无广熟女亚洲 | 色老头在线一区二区三区 | 青青青爽视频在线观看 | 亚洲色成人中文字幕网站 | 97久久国产亚洲精品超碰热 | 亚洲日韩乱码中文无码蜜桃臀网站 | 131美女爱做视频 | 免费中文字幕日韩欧美 | 亚洲熟熟妇xxxx | 强辱丰满人妻hd中文字幕 | 中文字幕无码av激情不卡 | 国产农村乱对白刺激视频 | 国内精品一区二区三区不卡 | 大地资源中文第3页 | 夜夜躁日日躁狠狠久久av | 少妇无码一区二区二三区 | 亚洲人成网站免费播放 | 最新版天堂资源中文官网 | 国产在热线精品视频 | 国产av人人夜夜澡人人爽麻豆 | 国产人妻精品一区二区三区 | 午夜理论片yy44880影院 | 国内精品一区二区三区不卡 | 婷婷五月综合激情中文字幕 | 日本丰满熟妇videos | 中文字幕无码乱人伦 | 欧美国产日韩久久mv | 精品午夜福利在线观看 | 日日夜夜撸啊撸 | 东北女人啪啪对白 | 国产精品丝袜黑色高跟鞋 | 日产国产精品亚洲系列 | 国产成人一区二区三区在线观看 | 亚洲熟悉妇女xxx妇女av | 少妇性荡欲午夜性开放视频剧场 | 免费观看激色视频网站 | 日本丰满熟妇videos | 亚洲综合色区中文字幕 | 无码av免费一区二区三区试看 | 清纯唯美经典一区二区 | 男女爱爱好爽视频免费看 | 亚洲自偷精品视频自拍 | 成人无码精品1区2区3区免费看 | 亚洲小说春色综合另类 | 欧美精品免费观看二区 | 国产色视频一区二区三区 | 成人欧美一区二区三区 | 欧美性黑人极品hd | 国产欧美精品一区二区三区 | 亚洲人成影院在线观看 | 丰满护士巨好爽好大乳 | 纯爱无遮挡h肉动漫在线播放 | 中文无码成人免费视频在线观看 | 亚洲va中文字幕无码久久不卡 | 国产香蕉尹人综合在线观看 | 中文毛片无遮挡高清免费 | 色爱情人网站 | 99视频精品全部免费免费观看 | 亚洲娇小与黑人巨大交 | 国产精品久久福利网站 | 国内精品久久毛片一区二区 | 久久99精品久久久久久动态图 | 久久aⅴ免费观看 | 成人免费视频视频在线观看 免费 | 麻豆国产97在线 | 欧洲 | 国产精品99久久精品爆乳 | 亚洲欧洲日本综合aⅴ在线 | yw尤物av无码国产在线观看 | 无码午夜成人1000部免费视频 | www成人国产高清内射 | 国产成人精品无码播放 | 国产艳妇av在线观看果冻传媒 | 99久久婷婷国产综合精品青草免费 | 老子影院午夜伦不卡 | 久久精品无码一区二区三区 | 亚洲成a人片在线观看无码3d | 色一情一乱一伦一视频免费看 | 久久人妻内射无码一区三区 | 国产区女主播在线观看 | 亚洲国产欧美国产综合一区 | 女人和拘做爰正片视频 | 久久精品99久久香蕉国产色戒 | 亚洲 日韩 欧美 成人 在线观看 | 小sao货水好多真紧h无码视频 | 一本色道久久综合亚洲精品不卡 | 中文字幕日产无线码一区 | 亚洲色偷偷男人的天堂 | 成人精品视频一区二区三区尤物 | www国产精品内射老师 | 中文字幕 亚洲精品 第1页 | 欧美35页视频在线观看 | 人人妻人人澡人人爽精品欧美 | 久久99精品久久久久久动态图 | 成人无码视频在线观看网站 | 天天躁夜夜躁狠狠是什么心态 | 粗大的内捧猛烈进出视频 | 思思久久99热只有频精品66 | 亚洲性无码av中文字幕 | 亚洲国产欧美日韩精品一区二区三区 | 免费乱码人妻系列无码专区 | 2020久久香蕉国产线看观看 | 日韩精品乱码av一区二区 | 欧美性生交xxxxx久久久 | 亚洲欧美精品伊人久久 | 大地资源中文第3页 | 丰满少妇弄高潮了www | 中文字幕久久久久人妻 | 任你躁国产自任一区二区三区 | 久青草影院在线观看国产 | 国产精品理论片在线观看 | 精品久久8x国产免费观看 | 国产女主播喷水视频在线观看 | 少妇无码av无码专区在线观看 | 成人女人看片免费视频放人 | 色五月丁香五月综合五月 | 国产精品对白交换视频 | 国产三级久久久精品麻豆三级 | 午夜精品久久久内射近拍高清 | 亚洲欧美中文字幕5发布 | 暴力强奷在线播放无码 | 国产特级毛片aaaaaaa高清 | 曰本女人与公拘交酡免费视频 | 国产精品99爱免费视频 | 高潮喷水的毛片 | 欧美日本精品一区二区三区 | 131美女爱做视频 | 又粗又大又硬又长又爽 | 18禁黄网站男男禁片免费观看 | 国产精品欧美成人 | 一本无码人妻在中文字幕免费 | 亚洲成av人片天堂网无码】 | 搡女人真爽免费视频大全 | 性欧美videos高清精品 | 精品偷自拍另类在线观看 | 国产精品久久国产三级国 | 欧美国产日产一区二区 | 国产精品欧美成人 | 亚洲精品一区二区三区四区五区 | 牲欲强的熟妇农村老妇女视频 | 国产亚洲视频中文字幕97精品 | 亚洲自偷自偷在线制服 | 国产一精品一av一免费 | 麻豆国产人妻欲求不满 | 国产乱人伦app精品久久 国产在线无码精品电影网 国产国产精品人在线视 | 国内少妇偷人精品视频免费 | 亚洲综合在线一区二区三区 | 无码人妻丰满熟妇区五十路百度 | 99久久久无码国产aaa精品 | 美女黄网站人色视频免费国产 | 国产午夜视频在线观看 | 久久97精品久久久久久久不卡 | 亚洲欧洲日本综合aⅴ在线 | 久久天天躁狠狠躁夜夜免费观看 | 国产熟女一区二区三区四区五区 | 国产午夜无码视频在线观看 | 国产精品国产自线拍免费软件 | 中文精品无码中文字幕无码专区 | 久久久中文字幕日本无吗 | 久久综合给合久久狠狠狠97色 | 午夜精品一区二区三区在线观看 | 精品一区二区三区波多野结衣 | 中文字幕日产无线码一区 | 欧美人与善在线com | 亚洲综合伊人久久大杳蕉 | 一区二区传媒有限公司 | 永久免费观看美女裸体的网站 | 国产成人综合在线女婷五月99播放 | 亚洲欧洲日本无在线码 | 人人妻人人澡人人爽精品欧美 | 丰满少妇女裸体bbw | 中文字幕无线码 | 色偷偷人人澡人人爽人人模 | 亚洲人成人无码网www国产 | 久久99精品久久久久久 | 国产精品a成v人在线播放 | 丁香花在线影院观看在线播放 | 国产亚洲精品久久久久久久久动漫 | 日日摸天天摸爽爽狠狠97 | 性色av无码免费一区二区三区 | 亚洲欧洲无卡二区视頻 | 久在线观看福利视频 | 97se亚洲精品一区 | 亚洲精品国产第一综合99久久 | 日本一区二区三区免费播放 | 国产精品久久久久9999小说 | 99久久久无码国产精品免费 | 国产乱码精品一品二品 | 日本大乳高潮视频在线观看 | 俺去俺来也www色官网 | 牲欲强的熟妇农村老妇女 | 国产午夜手机精彩视频 | 精品国产精品久久一区免费式 | 夜夜影院未满十八勿进 | 日本一区二区三区免费高清 | 国产乱人无码伦av在线a | 国产性猛交╳xxx乱大交 国产精品久久久久久无码 欧洲欧美人成视频在线 | 日日夜夜撸啊撸 | 亚洲高清偷拍一区二区三区 | 大地资源网第二页免费观看 | 国产又爽又黄又刺激的视频 | 国内精品一区二区三区不卡 | 欧美日韩综合一区二区三区 | 黑人玩弄人妻中文在线 | 免费无码av一区二区 | 日韩 欧美 动漫 国产 制服 | 国产精品多人p群无码 | 日日摸夜夜摸狠狠摸婷婷 | 国产午夜无码视频在线观看 | 强辱丰满人妻hd中文字幕 | 东京一本一道一二三区 | 亚洲精品美女久久久久久久 | 久久久精品欧美一区二区免费 | 在线亚洲高清揄拍自拍一品区 | 欧美日韩亚洲国产精品 | 无码帝国www无码专区色综合 | 国产精品无套呻吟在线 | 波多野结衣高清一区二区三区 | 最新国产麻豆aⅴ精品无码 | 国产一区二区三区日韩精品 | 久久99精品国产麻豆 | 国产精品第一区揄拍无码 | 一区二区三区高清视频一 | 亚洲爆乳无码专区 | 精品国产国产综合精品 | √天堂资源地址中文在线 | 欧美日韩综合一区二区三区 | 99久久久无码国产精品免费 | 人妻无码久久精品人妻 | 人妻插b视频一区二区三区 | 欧美日韩亚洲国产精品 | 国产精品沙发午睡系列 | 高清无码午夜福利视频 | 免费国产成人高清在线观看网站 | 麻豆国产丝袜白领秘书在线观看 | 色欲综合久久中文字幕网 | 成人欧美一区二区三区黑人免费 | 国产亚洲tv在线观看 | 人妻与老人中文字幕 | 国产农村妇女高潮大叫 | 亚洲娇小与黑人巨大交 | 亚洲乱亚洲乱妇50p | 亚洲国产精品毛片av不卡在线 | 免费中文字幕日韩欧美 | 欧美 日韩 人妻 高清 中文 | √天堂中文官网8在线 | 国产精品人人爽人人做我的可爱 | 国产精品毛多多水多 | 午夜男女很黄的视频 | 中文字幕 亚洲精品 第1页 | 欧美熟妇另类久久久久久多毛 | 无码毛片视频一区二区本码 | 亚洲国产成人a精品不卡在线 | 99在线 | 亚洲 | 又大又硬又爽免费视频 | 人人澡人摸人人添 | 久久综合香蕉国产蜜臀av | 中文字幕人妻无码一区二区三区 | 久久综合网欧美色妞网 | 亚洲色偷偷男人的天堂 | 人妻插b视频一区二区三区 | 人人妻人人澡人人爽人人精品 | 国产成人精品久久亚洲高清不卡 | 亚洲中文字幕无码中字 | 无码中文字幕色专区 | 娇妻被黑人粗大高潮白浆 | 18精品久久久无码午夜福利 | 欧洲极品少妇 | 久久精品人人做人人综合试看 | 狠狠亚洲超碰狼人久久 | 麻豆精产国品 | 日本一区二区三区免费高清 | 亚洲精品无码国产 | 亚洲精品久久久久久久久久久 | 日韩av无码一区二区三区 | 成人毛片一区二区 | 色偷偷人人澡人人爽人人模 | 国产精品a成v人在线播放 | 久久久精品欧美一区二区免费 | 国产真人无遮挡作爱免费视频 | 亚洲精品国产精品乱码视色 | 久久亚洲日韩精品一区二区三区 | 亚洲熟妇色xxxxx欧美老妇 | 亚洲熟妇色xxxxx欧美老妇 | 欧美zoozzooz性欧美 | 成人亚洲精品久久久久 | 精品国产一区二区三区四区在线看 | 国产乱子伦视频在线播放 | 亚洲自偷精品视频自拍 | 国产欧美熟妇另类久久久 | 精品国产一区二区三区av 性色 | 性开放的女人aaa片 | 国产美女极度色诱视频www | 2019nv天堂香蕉在线观看 | 黑森林福利视频导航 | 亚洲伊人久久精品影院 | 纯爱无遮挡h肉动漫在线播放 | а√天堂www在线天堂小说 | 男女超爽视频免费播放 | 少妇无码av无码专区在线观看 | 少妇高潮一区二区三区99 | 无套内谢老熟女 | 色老头在线一区二区三区 | 高潮毛片无遮挡高清免费视频 | 午夜精品一区二区三区在线观看 | 蜜臀aⅴ国产精品久久久国产老师 | 国产另类ts人妖一区二区 | 日本熟妇大屁股人妻 | 无码一区二区三区在线 | 在线а√天堂中文官网 | 欧美丰满少妇xxxx性 | 一本久久a久久精品亚洲 | 黑人巨大精品欧美黑寡妇 | 97色伦图片97综合影院 | 亚洲乱码中文字幕在线 | 露脸叫床粗话东北少妇 | 国产口爆吞精在线视频 | 亚洲小说春色综合另类 | 欧美野外疯狂做受xxxx高潮 | 国产无遮挡又黄又爽免费视频 | 国产农村妇女aaaaa视频 撕开奶罩揉吮奶头视频 | 亚洲国产成人a精品不卡在线 | 国产精品亚洲专区无码不卡 | 性色欲网站人妻丰满中文久久不卡 | 亚洲a无码综合a国产av中文 | 亚洲aⅴ无码成人网站国产app | 久久久精品456亚洲影院 | 麻花豆传媒剧国产免费mv在线 | 最新国产乱人伦偷精品免费网站 | 午夜性刺激在线视频免费 | 精品午夜福利在线观看 | 人人妻人人澡人人爽欧美一区九九 | 欧美三级不卡在线观看 | 水蜜桃av无码 | 日本一区二区三区免费播放 | 成人无码影片精品久久久 | 99久久人妻精品免费一区 | 人妻无码αv中文字幕久久琪琪布 | 国内少妇偷人精品视频免费 | 蜜桃av蜜臀av色欲av麻 999久久久国产精品消防器材 | 久激情内射婷内射蜜桃人妖 | 亚洲欧美综合区丁香五月小说 | 婷婷五月综合激情中文字幕 | 狂野欧美性猛xxxx乱大交 | 综合网日日天干夜夜久久 | 野狼第一精品社区 | 自拍偷自拍亚洲精品被多人伦好爽 | 伊在人天堂亚洲香蕉精品区 | 色五月丁香五月综合五月 | 亚洲中文字幕成人无码 | 久久精品国产一区二区三区 | 宝宝好涨水快流出来免费视频 | 色综合天天综合狠狠爱 | 欧美日本日韩 | 国产av无码专区亚洲awww | 国产偷国产偷精品高清尤物 | 国产人妻人伦精品 | 欧美人与牲动交xxxx | 内射老妇bbwx0c0ck | 亚洲人成网站在线播放942 | 亚洲va中文字幕无码久久不卡 | 夜夜夜高潮夜夜爽夜夜爰爰 | 蜜臀aⅴ国产精品久久久国产老师 | 亚洲精品午夜无码电影网 | 精品日本一区二区三区在线观看 | 欧美丰满少妇xxxx性 | 国产熟妇高潮叫床视频播放 | 强开小婷嫩苞又嫩又紧视频 | av无码久久久久不卡免费网站 | 国产精品爱久久久久久久 | 欧美第一黄网免费网站 | 丁香啪啪综合成人亚洲 | 377p欧洲日本亚洲大胆 | 欧美性猛交xxxx富婆 | 亚洲狠狠色丁香婷婷综合 | 国产精品人妻一区二区三区四 | 欧美精品在线观看 | 大肉大捧一进一出视频出来呀 | 亚洲人亚洲人成电影网站色 | 日韩亚洲欧美精品综合 | 国产成人午夜福利在线播放 | 大胆欧美熟妇xx | 丝袜人妻一区二区三区 | 人妻少妇精品久久 | 亚洲成a人片在线观看日本 | 国产精品久久久久久亚洲影视内衣 | 狠狠cao日日穞夜夜穞av | 67194成是人免费无码 | 精品国产av色一区二区深夜久久 | 自拍偷自拍亚洲精品10p | 亚洲色无码一区二区三区 | 久久天天躁狠狠躁夜夜免费观看 | 扒开双腿疯狂进出爽爽爽视频 | 久久久久成人片免费观看蜜芽 | 亚洲人交乣女bbw | 人人妻人人澡人人爽欧美一区 | 亚洲综合伊人久久大杳蕉 | 欧美日韩综合一区二区三区 | 欧洲熟妇色 欧美 | 香蕉久久久久久av成人 | 久久久成人毛片无码 | 67194成是人免费无码 | 国产又爽又黄又刺激的视频 | 欧美变态另类xxxx | 97se亚洲精品一区 | 国产人妻久久精品二区三区老狼 | 亚洲日韩中文字幕在线播放 | 久久精品中文字幕大胸 | 欧美日韩视频无码一区二区三 | 少妇无码一区二区二三区 | 欧美日韩一区二区三区自拍 | 丰满少妇熟乱xxxxx视频 | 中文字幕日产无线码一区 | 亚洲精品成a人在线观看 | 熟妇人妻激情偷爽文 | 一本久久a久久精品vr综合 | 性生交片免费无码看人 | 久久亚洲精品成人无码 | 特大黑人娇小亚洲女 | 国产电影无码午夜在线播放 | 日本护士毛茸茸高潮 | 97久久国产亚洲精品超碰热 | 麻豆成人精品国产免费 | 成人三级无码视频在线观看 | 黑人大群体交免费视频 | 狠狠色丁香久久婷婷综合五月 | 久久人人爽人人爽人人片ⅴ | 在线精品亚洲一区二区 | 3d动漫精品啪啪一区二区中 | 亚洲欧美日韩成人高清在线一区 | 欧美性生交xxxxx久久久 | 精品偷拍一区二区三区在线看 | 欧美国产日产一区二区 | 日产精品高潮呻吟av久久 | 无码人妻丰满熟妇区五十路百度 | 成在人线av无码免观看麻豆 | 久久97精品久久久久久久不卡 | 婷婷丁香五月天综合东京热 | 成人无码精品一区二区三区 | 88国产精品欧美一区二区三区 | 国产成人无码av一区二区 | 精品无码国产自产拍在线观看蜜 | 亚洲精品午夜国产va久久成人 | 亚洲欧美日韩成人高清在线一区 | 无码人妻出轨黑人中文字幕 | 人妻尝试又大又粗久久 | 色欲人妻aaaaaaa无码 | 久久久久成人片免费观看蜜芽 | 999久久久国产精品消防器材 | 亚洲国产一区二区三区在线观看 | 国产成人无码av片在线观看不卡 | 婷婷六月久久综合丁香 | 亚洲日韩乱码中文无码蜜桃臀网站 | 丰满人妻精品国产99aⅴ | 真人与拘做受免费视频一 | 亚洲午夜福利在线观看 | 无遮无挡爽爽免费视频 | 亚洲国产欧美日韩精品一区二区三区 | 久久亚洲日韩精品一区二区三区 | 白嫩日本少妇做爰 | 欧美亚洲日韩国产人成在线播放 | 日日鲁鲁鲁夜夜爽爽狠狠 | 免费看男女做好爽好硬视频 | 国产精品99爱免费视频 | 在线观看国产一区二区三区 | 精品亚洲成av人在线观看 | 四虎国产精品一区二区 | 亚洲欧洲中文日韩av乱码 | 亚洲无人区一区二区三区 | 欧美 日韩 人妻 高清 中文 | 国产激情一区二区三区 | 日韩人妻系列无码专区 | 51国偷自产一区二区三区 | 丰满少妇弄高潮了www | 99麻豆久久久国产精品免费 | 一本加勒比波多野结衣 | 国产在线无码精品电影网 | 日本乱偷人妻中文字幕 | 国产精品18久久久久久麻辣 | 国产精品二区一区二区aⅴ污介绍 | 精品欧洲av无码一区二区三区 | 少妇无码一区二区二三区 | 日韩欧美中文字幕在线三区 | 青青草原综合久久大伊人精品 | 亚洲区小说区激情区图片区 | 国内精品九九久久久精品 | 亚洲另类伦春色综合小说 | 欧美日韩人成综合在线播放 | 女高中生第一次破苞av | 国产人妖乱国产精品人妖 | 风流少妇按摩来高潮 | 欧美乱妇无乱码大黄a片 | 亚洲男人av香蕉爽爽爽爽 | 亚洲成av人在线观看网址 | 亚洲人成网站免费播放 | 男人的天堂av网站 | 18禁止看的免费污网站 | 亚洲色大成网站www国产 | 亚洲成熟女人毛毛耸耸多 | 国产精品无码久久av | 欧美精品国产综合久久 | 成人欧美一区二区三区黑人 | 国产综合色产在线精品 | 漂亮人妻洗澡被公强 日日躁 | 国产真人无遮挡作爱免费视频 | 乱中年女人伦av三区 | 永久免费精品精品永久-夜色 | 中国女人内谢69xxxxxa片 | 亚洲一区二区三区 | 日韩精品乱码av一区二区 | 俺去俺来也在线www色官网 | 亚洲成在人网站无码天堂 | 国产一区二区不卡老阿姨 | 国产亚洲欧美在线专区 | 内射老妇bbwx0c0ck | 久久久精品456亚洲影院 | 亚洲熟悉妇女xxx妇女av | 大肉大捧一进一出好爽视频 | 3d动漫精品啪啪一区二区中 | 丰满人妻被黑人猛烈进入 | 免费国产成人高清在线观看网站 | 国产女主播喷水视频在线观看 | 国产亚洲人成a在线v网站 | 男女猛烈xx00免费视频试看 | 免费播放一区二区三区 | аⅴ资源天堂资源库在线 | 秋霞特色aa大片 | 色欲综合久久中文字幕网 | 无码av最新清无码专区吞精 | 中国大陆精品视频xxxx | 成人免费视频一区二区 | 色综合视频一区二区三区 | 亚洲欧洲日本综合aⅴ在线 | 在线视频网站www色 | 色婷婷欧美在线播放内射 | 亚洲国产欧美日韩精品一区二区三区 | 天海翼激烈高潮到腰振不止 | 动漫av一区二区在线观看 | 无码人妻少妇伦在线电影 | 少妇的肉体aa片免费 | 免费观看激色视频网站 | 亚洲国精产品一二二线 | 日韩精品a片一区二区三区妖精 | 亚洲午夜久久久影院 | 300部国产真实乱 | 国产无套粉嫩白浆在线 | 国内精品九九久久久精品 | 色 综合 欧美 亚洲 国产 | 好屌草这里只有精品 | 黑人大群体交免费视频 | 人人澡人人妻人人爽人人蜜桃 | 欧美freesex黑人又粗又大 | 亚洲精品久久久久avwww潮水 | 成人动漫在线观看 | 亚洲区小说区激情区图片区 | 麻豆国产丝袜白领秘书在线观看 | 美女黄网站人色视频免费国产 | 一本大道伊人av久久综合 | 欧美日本免费一区二区三区 | 中文字幕人成乱码熟女app | 国产极品美女高潮无套在线观看 | 亚洲伊人久久精品影院 | 中文精品久久久久人妻不卡 | 乱人伦人妻中文字幕无码 | 国产精品爱久久久久久久 | 精品久久久无码中文字幕 | 亚洲国产精品一区二区第一页 | 天堂а√在线地址中文在线 | 亚洲色欲色欲天天天www | 亚洲自偷精品视频自拍 | 久久久中文字幕日本无吗 | 乱码av麻豆丝袜熟女系列 | 老太婆性杂交欧美肥老太 | 中文字幕av无码一区二区三区电影 | 国产精品二区一区二区aⅴ污介绍 | 国产口爆吞精在线视频 | 伊人久久大香线焦av综合影院 | av无码不卡在线观看免费 | 国产三级久久久精品麻豆三级 | 97无码免费人妻超级碰碰夜夜 | 免费无码肉片在线观看 | 亚洲成av人影院在线观看 | 国产精品第一国产精品 | 亚洲男女内射在线播放 | 久久亚洲精品中文字幕无男同 | av无码电影一区二区三区 | 国产9 9在线 | 中文 | 国产无遮挡又黄又爽免费视频 | 国产精品高潮呻吟av久久 | 熟女少妇在线视频播放 | 亚洲精品一区二区三区婷婷月 | 亚洲一区二区观看播放 | 无码福利日韩神码福利片 | 久久久成人毛片无码 | 色窝窝无码一区二区三区色欲 | 国产成人无码午夜视频在线观看 | 亚洲狠狠色丁香婷婷综合 | 国产无av码在线观看 | 国产xxx69麻豆国语对白 | 国产乱人偷精品人妻a片 | 亚洲第一网站男人都懂 | 中文字幕无码人妻少妇免费 | 久久熟妇人妻午夜寂寞影院 | 乱人伦中文视频在线观看 | 男人的天堂av网站 | 国产亚洲精品久久久闺蜜 | 国产黑色丝袜在线播放 | 欧美三级a做爰在线观看 | 又黄又爽又色的视频 | 婷婷丁香六月激情综合啪 | 中文字幕无码日韩欧毛 | 人人澡人摸人人添 | 成人片黄网站色大片免费观看 | 美女黄网站人色视频免费国产 | 一本无码人妻在中文字幕免费 | 在线视频网站www色 | 亚洲中文字幕成人无码 | 国产精品高潮呻吟av久久 | 99精品久久毛片a片 | 在线视频网站www色 | 激情内射日本一区二区三区 | 天堂а√在线地址中文在线 | 中国大陆精品视频xxxx | 久久精品人妻少妇一区二区三区 | 亚洲爆乳精品无码一区二区三区 | 成人精品视频一区二区 | 又大又硬又爽免费视频 | 亚洲日韩中文字幕在线播放 | 女人高潮内射99精品 | 国内精品人妻无码久久久影院蜜桃 | 久久亚洲精品中文字幕无男同 | 免费播放一区二区三区 | 欧美野外疯狂做受xxxx高潮 | 久久亚洲精品中文字幕无男同 | 国产成人综合色在线观看网站 | 任你躁在线精品免费 | 宝宝好涨水快流出来免费视频 | 鲁大师影院在线观看 | 无码人妻av免费一区二区三区 | 性欧美熟妇videofreesex | 国产日产欧产精品精品app | 亚洲一区二区三区偷拍女厕 | 四虎4hu永久免费 | 亚洲成在人网站无码天堂 | 精品久久久无码中文字幕 | 日日噜噜噜噜夜夜爽亚洲精品 | 无码人妻精品一区二区三区不卡 | 无遮无挡爽爽免费视频 | 国精产品一品二品国精品69xx | 夜精品a片一区二区三区无码白浆 | 国产人妻人伦精品1国产丝袜 | 精品水蜜桃久久久久久久 | 少妇被粗大的猛进出69影院 | 性做久久久久久久免费看 | 久久久中文字幕日本无吗 | 99精品视频在线观看免费 | 成人欧美一区二区三区黑人 | 亚洲乱亚洲乱妇50p | 欧美熟妇另类久久久久久多毛 | 粉嫩少妇内射浓精videos | 四虎永久在线精品免费网址 | 成在人线av无码免费 | 免费人成网站视频在线观看 | 成人综合网亚洲伊人 | 鲁鲁鲁爽爽爽在线视频观看 | 奇米影视888欧美在线观看 | 国产97在线 | 亚洲 | 98国产精品综合一区二区三区 | 黑人粗大猛烈进出高潮视频 | 久久这里只有精品视频9 | 亚洲色无码一区二区三区 | 亚洲爆乳精品无码一区二区三区 | 国产情侣作爱视频免费观看 | 无码福利日韩神码福利片 | 亚洲男女内射在线播放 | 动漫av一区二区在线观看 | 久久久久成人精品免费播放动漫 | 精品久久久无码中文字幕 | 人人超人人超碰超国产 | 亚洲精品www久久久 | 国产精品无码久久av | 免费观看又污又黄的网站 | 一本精品99久久精品77 | 撕开奶罩揉吮奶头视频 | 中文无码精品a∨在线观看不卡 | 久精品国产欧美亚洲色aⅴ大片 | 亚洲欧美中文字幕5发布 | 人妻无码αv中文字幕久久琪琪布 | 综合激情五月综合激情五月激情1 | 少妇邻居内射在线 | 久久精品国产99久久6动漫 | 97夜夜澡人人双人人人喊 | 久久久久久久久888 | 婷婷丁香五月天综合东京热 | 国产精品亚洲lv粉色 | 丰满人妻一区二区三区免费视频 | 丁香啪啪综合成人亚洲 | 国产精品香蕉在线观看 | 久久精品国产精品国产精品污 | 国产黄在线观看免费观看不卡 | 成人精品视频一区二区三区尤物 | 亚洲精品久久久久久久久久久 | 国精产品一品二品国精品69xx | 内射后入在线观看一区 | 人人妻人人澡人人爽欧美精品 | 国产suv精品一区二区五 | 亚洲自偷自偷在线制服 | 亚洲综合在线一区二区三区 | 亚洲小说春色综合另类 | 精品国产一区二区三区四区 | 99精品国产综合久久久久五月天 | 免费看男女做好爽好硬视频 | 国产av一区二区三区最新精品 | 日产国产精品亚洲系列 | 扒开双腿吃奶呻吟做受视频 | 久久精品丝袜高跟鞋 | 大地资源网第二页免费观看 | 正在播放东北夫妻内射 | 欧美日韩色另类综合 | 亚洲欧美色中文字幕在线 | 乱码av麻豆丝袜熟女系列 | 国产极品视觉盛宴 | 精品人妻人人做人人爽夜夜爽 | 国语精品一区二区三区 | 精品人妻人人做人人爽 | 日本一区二区三区免费播放 | 国产又爽又黄又刺激的视频 | 精品国精品国产自在久国产87 | 麻花豆传媒剧国产免费mv在线 | 国产特级毛片aaaaaaa高清 | 草草网站影院白丝内射 | 亚洲 日韩 欧美 成人 在线观看 | 国产黑色丝袜在线播放 | 国产成人无码专区 | 日韩精品a片一区二区三区妖精 | 人人爽人人澡人人人妻 | 俺去俺来也在线www色官网 | 18禁黄网站男男禁片免费观看 | 欧美老人巨大xxxx做受 | 国产成人无码av在线影院 | 乱人伦人妻中文字幕无码久久网 | 在线视频网站www色 | 精品人妻av区 | 无码人妻丰满熟妇区毛片18 | 久久97精品久久久久久久不卡 | 2020久久超碰国产精品最新 | 成熟人妻av无码专区 | 精品无码国产自产拍在线观看蜜 | 亚洲精品一区二区三区四区五区 | www成人国产高清内射 | 高清国产亚洲精品自在久久 | 国产疯狂伦交大片 | 欧美日韩一区二区三区自拍 | 国产特级毛片aaaaaaa高清 | 风流少妇按摩来高潮 | 欧美丰满熟妇xxxx | 水蜜桃亚洲一二三四在线 | 国产疯狂伦交大片 | 久久国产精品萌白酱免费 | 欧洲精品码一区二区三区免费看 | 狂野欧美性猛xxxx乱大交 | 最近的中文字幕在线看视频 | 夜夜高潮次次欢爽av女 | 麻豆国产丝袜白领秘书在线观看 | 精品久久久久久亚洲精品 | 久久久久成人精品免费播放动漫 | 国产特级毛片aaaaaa高潮流水 | 午夜精品久久久久久久 | 亚洲日韩中文字幕在线播放 | 亚洲国产日韩a在线播放 | 久久国产精品_国产精品 | 人人妻人人澡人人爽欧美精品 | 国产av人人夜夜澡人人爽麻豆 | 精品久久久中文字幕人妻 | 久久99精品国产麻豆蜜芽 | 男人的天堂2018无码 |