青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

yehao's Blog

WinSock重疊I/O模型

轉自http://blog.csdn.net/phunxm/archive/2009/12/27/5085915.aspx
一.重疊I/O模型的概念

當調用ReadFile()和WriteFile()時,如果最后一個參數lpOverlapped設置為NULL,那么線程就阻塞在這里,直到讀寫完指定的數據后,它們才返回。這樣在讀寫大文件的時候,很多時間都浪費在等待ReadFile()和WriteFile()的返回上面。如果ReadFile()和WriteFile()是往管道里讀寫數據,那么有可能阻塞得更久,導致程序性能下降。

為了解決這個問題,Windows引進了重疊I/O的概念,它能夠同時以多個線程處理多個I/O。其實你自己開多個線程也可以處理多個I/O,但是系統內部對I/O的處理在性能上有很大的優化。它是Windows下實現異步I/O最常用的方式。

Windows為幾乎全部類型的文件提供這個工具:磁盤文件、通信端口、命名管道和套接字。通常,使用ReadFile()和WriteFile()就可以很好地執行重疊I/O。

重疊模型的核心是一個重疊數據結構。若想以重疊方式使用文件,必須用 FILE_FLAG_OVERLAPPED標志打開它,例如:

HANDLE hFile = CreateFile(lpFileName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);

如果沒有規定該標志,則針對這個文件(句柄),重疊I/O是不可用的。如果設置了該標志,當調用ReadFile()和WriteFile()操作這個文件(句柄)時,必須為最后一個參數提供OVERLAPPED結構:

// WINBASE.H

typedef struct _OVERLAPPED{

        DWORD   Internal;

        DWORD   InternalHigh;

        DWORD   Offset;

        DWORD   OffsetHigh;

        HANDLE  hEvent; //關鍵的一個參數

}OVERLAPPED, *LPOVERLAPPED;

頭兩個32位的結構字Internal和InternalHigh由系統內部使用;其次兩個32位結構字Offset和OffsetHigh使得可以設置64位的偏移量,該偏移量是要文件中讀或寫的地方。

因為I/O異步發生,就不能確定操作是否按順序完成。因此,這里沒有當前位置的概念。對于文件的操作,總是規定該偏移量。在數據流下(如COM端口或socket),沒有尋找精確偏移量的方法,所以在這些情況中,系統忽略偏移量。這四個字段不應由應用程序直接進行處理或使用,OVERLAPPED結構的最后一個參數是可選的事件句柄,當I/O完成時,該事件對象受信(signaled)。程序通過等待該對事件對象受信來做善后處理。

設置了OVERLAPPED參數后,ReadFile()/WriteFile()的調用會立即返回,這時候你可以去做其他的事(所謂異步),系統會自動替你完成ReadFile()/WriteFile()相關的I/O操作。你也可以同時發出幾個ReadFile()/WriteFile()的調用(所謂重疊)。當系統完成I/O操作時,會將OVERLAPPED.hEvent置信,我們可以通過調用WaitForSingleObject/WaitForMultipleObjects來等待這個I/O完成通知,在得到通知信號后,就可以調用GetOverlappedResult來查詢I/O操作的結果,并進行相關處理。由此可以看出,OVERLAPPED結構在一個重疊I/O請求的初始化及其后續的完成之間,提供了一種溝通或通信機制。注意OVERLAPPED結構的生存周期,一般動態分配,待I/O完成后,回收重疊結構。

以Win32重疊I/O機制為基礎,自WinSock 2發布開始,重疊I/O便已集成到新的WinSock API中,比如WSARecv()/WSASend()。這樣一來,重疊I/O模型便能適用于安裝了WinSock 2的所有Windows平臺。可以一次投遞一個或多個WinSock I/O請求。針對那些提交的請求,在它們完成之后,應用程序可為它們提供服務(對I/O的數據進行處理)。

相應的,要想在一個套接字上使用重疊I/O模型來處理網絡數據通信,首先必須使用 WSA_FLAG_OVERLAPPED這個標志來創建一個套接字。如下所示:

SOCKET s = WSASocket(AF_INET, SOCK_STEAM, 0, NULL, 0,  WSA_FLAG_OVERLAPPED);

創建套接字的時候,假如使用的是socket()函數,而非WSASocket()函數,那么會默認設置WSA_FLAG_OVERLAPPED標志。成功創建好了一個套接字,將其與一個本地接口綁定到一起后,便可開始進行這個套接字上的重疊I/O操作,方法是調用下述的WinSock 2函數,同時為它們指定一個WSAOVERLAPPED結構參數(#define WSAOVERLAPPED OVERLAPPED// WINSOCK2.H):

(1)WSASend()

(2)WSASendTo()

(3)WSARecv()

(4)WSARecvFrom()

(5)WSAIoctl()

(6)AcceptEx()

(7)TransmitFile()

若隨一個WSAOVERLAPPED結構一起調用這些函數,函數會立即返回,無論套接字是否設為鎖定模式。它們依賴于WSAOVERLAPPED結構來返回一個I/O請求操作的結果。

比起阻塞、select、WSAAsyncSelect以及WSAEventSelect等模型,WinSock的重疊I/O(Overlapped I/O)模型使應用程序能達到更佳的系統性能。因為它和這4種模型不同的是,使用重疊模型的應用程序通知緩沖區收發系統直接使用數據。也就是說,如果應用程序投遞了一個10KB大小的緩沖區來接收數據,且數據已經到達套接字,則該數據將直接被拷貝到投遞的緩沖區。而這4種模型中,數據到達并拷貝到單套接字接收緩沖區(Per Socket Buffer)中,此時應用程序會被系統通知可以讀入的字節數。當應用程序調用接收函數之后,數據才從單套接字緩沖區拷貝到應用程序的緩沖區。這樣就減少了一次從I/O緩沖區到應用程序緩沖區的拷貝,差別就在于此。

實際編程時,可以投遞一個0字節緩沖區的WSARecv/WSASend操作,這樣就沒有用戶緩沖區與I/O操作相關聯,避免了用戶緩沖區的鎖定(過多的鎖定可能導致非分頁內存池耗盡,即WSAENOBUFS),應用程序繞開單套接字緩沖區而直接與TCP Stack進行數據交互,從而避免了內存拷貝。當然,只要投遞了足夠多的重疊發送/接收操作,就能避免額外的內存拷貝,這時將單套接字緩沖區設置為0并不能提升性能。因為應用程序的發送緩沖區將始終被鎖定直到可以下傳給TCP,所以停用套接字的發送緩沖區對性能的影響比停用接收緩沖區小。然而,如果接收緩沖區被設置為0,而又未投遞重疊接收操作,則進來的數據都只能停留在TCP Stack中,而TCP驅動程序的緩沖區最多只能接收窗口大小。TCP緩沖區被定位在非分頁內存池中,假如很多連接發數據過來,但我們根本沒有投遞接收操作,則將消耗大量的非分頁內存池。非分頁內存池是一種有限的資源,過多的鎖定可能導致非分頁內存池耗盡,即WSAENOBUFS。

在Windows NT和Windows 2000中,重疊I/O模型也允許應用程序以一種重疊方式實現對套接字連接的處理。具體的做法是在監聽套接字上調用AcceptEx函數。AcceptEx是一個特殊的WinSock擴展函數,由mswsock.dll實現,使用時需包含Mswsock.h頭文件,鏈接Mswsock.lib庫文件。該函數最初的設計宗旨是在Windows NT與Windows 2000操作系統上使用Win 32的重疊I/O機制。但事實上,它也適用于WinSock 2中的重疊I/O。AcceptEx的定義如下:

// MSWSOCK.H

AcceptEx(

       IN SOCKET sListenSocket,

       IN SOCKET sAcceptSocket,

       IN PVOID lpOutputBuffer,

       IN DWORD dwReceiveDataLength,

       IN DWORD dwLocalAddressLength,

       IN DWORD dwRemoteAddressLength,

       OUT LPDWORD lpdwBytesReceived,

       IN LPOVERLAPPED lpOverlapped);

參數一sListenSocket參數指定的是一個監聽套接字。

參數二sAcceptSocket參數指定的是另一個套接字,負責對進入連接請求的“接受”。 AcceptEx()函數和accept()函數的區別在于,我們必須提供接受的套接字,而不是讓函數自動為我們創建。正是由于要提供套接字,所以要求我們事先調用socket()或WSASocket()函數創建一個套接字,以便通過sAcceptSocket參數,將其傳遞給AcceptEx()。

參數三lpOutputBuffer指定的是一個特殊的緩沖區,因為它要負責三種數據的接收:服務器的本地地址,客戶機的遠程地址,以及在新建連接上接收的第一個數據塊。存儲順序是:接收到的數據塊→本地地址→遠程地址。

參數四dwReceiveDataLength以字節為單位,指定了在lpOutputBuffer緩沖區開頭保留多大的空間,用于數據的接收。如這個參數設為0,那么只接受連接,不伴隨接收數據。

參數五dwLocalAddressLength和參數六dwRemoteAddressLength也是以字節為單位,指定在lpOutputBuffer緩沖區中,保留多大的空間,在一個套接字被接受的時候,用于本地和遠程地址信息的保存。要注意的是,和當前采用的傳送協議允許的最大地址長度比較起來,這里指定的緩沖區大小至少應多出16字節。舉個例子來說,假定正在使用的是TCP/IP協議,那么這里的大小應設為“SOCKADDR_IN結構的長度+16字節”。

參數七lpdwBytesReceived參數用于返回接收到的實際數據量,以字節為單位。只有在操作以同步方式完成的前提下,才會設置這個參數。假如AcceptEx()函數返回ERROR_IO_PENDING,那么這個參數永遠都不會設置,我們必須利用完成事件通知機制,獲知實際讀取的字節量。

最后一個參數是lpOverlapped,它對應的是一個OVERLAPPED結構,允許AcceptEx()以一種異步方式工作。如我們早先所述,只有在一個重疊I/O應用中,該函數才需要使用事件對象通知機制(hEvent字段),這是由于此時沒有一個完成例程參數可供使用。

 

二.獲取重疊I/O操作完成結果

當異步I/O請求掛起后,最終要知道I/O操作是否完成。一個重疊I/O請求最終完成后,應用程序要負責讀取重疊I/O操作的結果。對于讀,直到I/O完成,接收緩沖器才有效(參考IRP緩沖區管理)。對于寫,要知道寫是否成功,有幾種方法可以做到這點,最直接的方法是調用(WSA)GetOverlappedResult,其函數原型如下:

WINBASEAPI BOOL WINAPI

GetOverlappedResult(

HANDLE hFile,

LPOVERLAPPED lpOverlapped,

LPDWORD lpNumberOfBytesTransferred,

BOOL bWait);

BOOL WSAAPI WSAGetOverlappedResult(

SOCKET s,

LPWSAOVERLAPPED lpOverlapped,

LPDWORD lpcbTransfer,

BOOL fWait,

LPDWORD lpdwFlags);

參數一為的文件/套接字句柄。

參數二為參數一關聯的(WSA) OVERLAPPED結構,在調用CreateFile()、WSASocket()或AcceptEx()時指定。

參數三指向字節計數指針,負責接收一次重疊發送或接收操作實際傳輸的字節數。

參數四是確定命令是否等待的標志。Wait參數用于決定函數是否應該等待一次重疊操作完成。若將Wait設為TRUE,那么直到操作完成函數才返回;若設為FALSE,而且操作仍然處于未完成狀態,那么(WSA)GetOverlappedResult()函數會返回FALSE值。

如(WSA)GetOverlappedResult()函數調用成功,返回值就是TRUE。這意味著我們的重疊I/O操作已成功完成,而且由參數三BytesTransfered參數指向的值已進行了更新。若返回值是FALSE,那么可能是由下述任何一種原因造成的:

■ 重疊I/O操作仍處在“待決”狀態。

■ 重疊操作已經完成,但含有錯誤。

■ 重疊操作的完成狀態不可判決,因為在提供給 WSAGetOverlappedResult函數的一個或多個參數中,存在著錯誤。

失敗后,由BytesTransfered參數指向的值不會進行更新,而且我們的應用程序應調用(WSA)GetLastError()函數,檢查到底是何種原因造成了調用失敗以使用相應容錯處理。如果錯誤碼為SOCKET_ERROR/WSA_IO_INCOMPLETE(Overlapped I/O event is not in a signaled state)或SOCKET_ERROR/WSA_IO_PENDING(Overlapped I/O operation is in progress),則表明I/O仍在進行。當然,這不是真正錯誤,任何其他錯誤碼則真正表明一個實際錯誤。

下面介紹兩種常用重疊I/O完成通知的方法。

1.使用事件通知

使用(WSA)GetOverlappedResult()是直截了當的,它吻合重疊I/O的概念。畢竟,如果要等待I/O,也許使用常規I/O命令更好。對于大多數程序,反復檢查I/O是否完成,并非最佳。解決方案之一是使用(WSA)OVERLAPPED結構中的hEvent字段,使應用程序將一個事件對象句柄同一個文件/套接字關聯起來。

當指定OVERLAPPED參數給ReadFile()/WriteFile()或WSARecv()/WSASend()后,可以再為(WSA)OVERLAPPED最后一個參數提供自定義的事件對象(通過(WSA)CreateEvent()創建)。

當I/O完成時,系統更改(WSA)OVERLAPPED結構對應的事件對象的傳信狀態,使其從“未傳信”(unsignaled)變成“已傳信”(signaled)。由于我們之前將事件對象分配給了(WSA)OVERLAPPED結構,所以只需簡單地調用WaitForSingleObject/WaitForMultipleObjects或WSAWaitForMultipleEvents函數,從而判斷出一個(一些)重疊I/O在什么時候完成。通過WaitForSingleObject/WaitForMultipleObjects或WSAWaitForMultipleEvents函數返回的索引可以知道這個重疊I/O完成事件是在哪個HANDLE(File或Socket)上發生的。

然后調用(WSA)GetOverlappedResult()函數,將發生事件的HANDLE(FILE或SOCKET)傳給參數一,將這個HANDLE對應的(WSA)OVERLAPPED結構傳給參數二,這樣判斷重疊調用到底是成功還是失敗。如果返回FALSE值,則重疊操作已經完成但含有錯誤。或者重疊操作的完成狀態不可判決,因為在提供給(WSA)GetOverlappedResult()函數的一個或多個參數中存在著錯誤。失敗后,由BytesTransfered參數指向的值不會進行更新,應用程序應調用(WSA)GetLastError()函數,調查到底是何種原因造成了調用失敗。

若(WSA)GetOverlappedResult()函數返回TRUE,則根據先前調用異步I/O函數時設置的緩沖區(ReadFile/WriteFile或WSARecv/WSASend的lpBuffer字段)和BytesTransfered,使用指針偏移定位就可以準確操作接受到的數據了。

利用事件對象來完成同步通知的方法比重復調用(WSA)GetOverlappedResult()浪費處理器時間的方案要高效得多。但WaitForMultipleObjects/WSAaitForMultipleEvent支持的事件對象個數的上限為MAXIMUM_WAIT_OBJECTS/WSA_MAXIMUM_WAIT_EVENTS=64!

2.使用完成例程

對于文件重疊I/O操作,等待I/O操作結束的另外方法是使用ReadFileEx()和WriteFileEx()。這些命令只用于重疊I/O,當為它們的最后一個參數lpCompletionRoutine傳遞了一個完成例程指針(回調函數地址)時,I/O操作結束時將調用此函數進行處理。

完成例程指針LPOVERLAPPED_COMPLETION_ROUTINE定義如下:

// WINBASE.H

typedef  VOID (WINAPI *LPOVERLAPPED_COMPLETION_ROUTINE)(

        DWORD dwErrorCode,

        DWORD dwNumberOfBytesTransfered,

        LPOVERLAPPED lpOverlapped );

相應在WinSock 2中,WSARecv()/WSASend()最后一個參數lpCompletionROUTINE是一個可選的指針,它指向一個完成例程。若指定此參數(自定義函數地址),在重疊請求完成后,將調用完成例程處理。完成例程本質上是一種APC(Asynchronous Procedure Calls)。

WinSock 2中完成例程指針LPWSAOVERLAPPED_COMPLETION_ROUTINE定義略有不同:

// WINSOCK2.H

typedef void (CALLBACK * LPWSAOVERLAPPED_COMPLETION_ROUTINE)(

        DWORD dwError,

        DWORD cbTransferred,

        LPWSAOVERLAPPED lpOverlapped,

        DWORD dwFlags );

     前三個參數同LPOVERLAPPED_COMPLETION_ROUTINE,參數四一般不用,置0。用完成例程完成一個重疊I/O請求之后,參數中會包含下述信息:

參數一dwError表明了一個重疊操作(由lpOverlapped指定)的完成狀態是什么。

參數二BytesTransferred參數指定了在重疊操作實際傳輸的字節量是多大。

參數三lpOverlapped參數指定的是調用這個完成例程的異步I/O操作函數(ReadFileEx()/WriteFileEx()或WSARecv()/WSASend())的(WSA)OVERLAPPED結構參數。

提交帶有完成例程的重疊I/O請求時,(WSA)OVERLAPPED結構的事件字段hEvent一般不再使用。使用一個含有完成例程指針參數的異步I/O函數發出一個重疊I/O請求之后,一旦重疊I/O操作完成,作為我們的調用線程,必須能夠通知完成例程指針所指向的自定義函數開始執行,提供數據處理服務。這樣一來,便要求將調用線程置于一種“可警告的等待狀態”,在I/O操作完成后,能自動調用完成例程。WSAWaitForMultipleEvents()函數可用來將線程置于一種可警告的等待狀態。這樣做的代價是必須創建一個事件對象可用于WSAWaitForMultipleEvents()函數。假定應用程序只用完成例程對重疊請求進行處理,便不需要引入事件對象。作為一種變通方法,我們的應用程序可用Win32的SleepEx()函數將自己的線程置為一種可警告的等待狀態。當然,亦可創建一個偽事件對象,不將它與任何東西關聯在一起。假如調用線程經常處于繁忙狀態,而且并不處于一種可警告的等待狀態,那么完成例程根本不會被通知執行。

如前面所述,WSAWaitForMultipleEvents()通常會等待同(WSA)OVERLAPPED結構關聯在一起的事件對象。該函數也可用于將我們的線程設置為一種可警告的等待狀態,為已經完成的重疊I/O請求調用完成例程進行處理(前提是將fAlertable參數設為TRUE)。使用一個含有完成例程指針的異步I/O函數提交了重疊I/O請求之后, WSAWaitForMultipleEvents()的期望返回值是WAIT_IO_COMPLETION(One or more I/O completion routines are queued for execution),而不再是事件對象索引。從宏WAIT_IO_COMPLETION的注解可知,它的意思是有完成例程需要執行。SleepEx()函數的行為實際上和WSAWaitForMultipleEvents()差不多,只是它不需要任何事件對象。對SleepEx函數的定義如下:

WINBASEAPI DWORD WINAPI

SleepEx(

    DWORD dwMilliseconds,

    BOOL bAlertable );

其中,dwMilliseconds參數定義了SleepEx()函數的等待時間,以毫秒為單位。假如將dwMilliseconds設為INFINITE,那么SleepEx()會無休止地等待下去。bAlertable參數規定了一個完成例程的執行方式,若將它設置為FALSE,則使用一個含有完成例程指針的異步I/O函數提交了重疊I/O請求后,I/O完成例程不會被通知執行,而且SleepEx()函數不會返回,除非超過由dwMilliseconds規定的時間;若將它設置為TRUE,則完成例程會被通知執行,同時SleepEx()函數返回WAIT_IO_COMPLETION。

在完成例程處理模型中,投遞重疊I/O請求的同時注冊完成例程,待I/O完成時由系統回調,并克服了事件通知模型的個數限制。利用完成例程處理重疊I/O的WinSock程序的編寫步驟如下:

(1) 新建一個監聽套接字,在指定端口上監聽客戶端的連接請求。

(2) 接受一個客戶端的連接請求,并返回一個會話套接字負責與客戶端通信。

(3) 為會話套接字關聯一個WSAOVERLAPPED結構。

(4) 在套接字上投遞一個異步WSARecv請求,方法是將WSAOVERLAPPED指定成為參數,同時提供一個完成例程。

(5) 在將fAlertable參數設為TRUE的前提下,調用WSAWaitForMultipleEvents,并等待一個重疊I/O請求完成。重疊請求完成后,完成例程會自動執行,而且WSAWaitForMultipleEvents會返回一個WAIT_IO_COMPLETION。在完成例程內,可隨一個完成例程一道投遞另一個重疊WSARecv請求。

(6) 檢查WSAWaitForMultipleEvents是否返回WAIT_IO_COMPLETION。

(7) 重復步驟(5)和(6)。

當調用accept處理連接時,一般創建一個AcceptEvent偽事件,當有客戶連接時,需要手動SetEvent(AcceptEvent);當調用AcceptEx處理重疊的連接時,一般為ListenSocket創建一個ListenOverlapped結構,并為其指定一個偽事件,當有客戶連接時,系統自動將其置信。這些偽事件的作用在于,當含有完成例程指針的異步I/O操作(如WSARecv)完成時,設置了fAlertable的WSAWaitForMultipleEvents返回WAIT_IO_COMPLETION,并調用完成例程指針指向的完成例程對數據進行處理。

重疊I/O模型的缺點是它一般要為每一個I/O請求都開一個線程,當同時有成千上萬個請求發生時,系統處理線程上下文切換是非常耗時的。所以這也就引出了更為先進的完成端口模型IOCP,用線程池來解決這個問題。

 

參考:

《Windows 2000 Systems Programming Black Book》  Al Williams

《Network Programming for Microsoft Windows》  Anthony Jones,Jim Ohlund

 

本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/phunxm/archive/2009/12/27/5085915.aspx

posted on 2011-05-23 17:25 厚積薄發 閱讀(1803) 評論(0)  編輯 收藏 引用 所屬分類: 網絡編程

導航

<2025年11月>
2627282930311
2345678
9101112131415
16171819202122
23242526272829
30123456

統計

常用鏈接

留言簿

隨筆分類

文章分類

文章檔案

搜索

最新評論

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            一区二区日韩伦理片| 最新国产精品拍自在线播放| 99国产麻豆精品| 欧美凹凸一区二区三区视频| 这里是久久伊人| 国产欧美va欧美va香蕉在| 久久精品国产久精国产思思| 久久精品99国产精品酒店日本| 激情六月综合| 亚洲电影毛片| 国产精品第2页| 久久久噜噜噜久久久| 欧美gay视频激情| 亚洲一区免费| 久久精品噜噜噜成人av农村| av成人国产| 午夜视黄欧洲亚洲| 亚洲破处大片| 亚洲一区三区电影在线观看| 国内精品久久久久久| 亚洲激情偷拍| 国产香蕉97碰碰久久人人| 欧美激情 亚洲a∨综合| 国产精品美腿一区在线看| 免费成人av在线| 国产精品久久久久婷婷| 欧美国产欧美亚洲国产日韩mv天天看完整 | 在线一区观看| 国产真实乱子伦精品视频| 亚洲激情在线视频| 国产一区二区三区的电影| 亚洲精品一区二区三区在线观看 | 久久久噜噜噜久久人人看| 一本色道久久综合精品竹菊| 欧美一级在线播放| 亚洲桃色在线一区| 免费成人高清在线视频| 久久成人这里只有精品| 欧美日韩美女一区二区| 久久综合久色欧美综合狠狠| 国产精品久久久99| 亚洲欧洲日韩综合二区| 在线观看久久av| 午夜久久一区| 亚洲影院免费观看| 欧美激情一区二区久久久| 久久视频在线视频| 国产麻豆91精品| 宅男精品视频| 亚洲小视频在线| 欧美紧缚bdsm在线视频| 欧美国产日韩精品免费观看| 黄色亚洲大片免费在线观看| 亚洲综合色网站| 亚洲永久在线观看| 欧美三级日韩三级国产三级| 亚洲黄页视频免费观看| 国产在线欧美日韩| 午夜视频一区在线观看| 午夜在线观看免费一区| 欧美亚洲第一页| 一本久久综合亚洲鲁鲁| 亚洲亚洲精品三区日韩精品在线视频| 欧美成人亚洲成人日韩成人| 欧美成人免费全部| 伊人婷婷久久| 欧美成人免费观看| 亚洲区免费影片| 一区二区三区www| 欧美日产一区二区三区在线观看 | 一本高清dvd不卡在线观看| 农夫在线精品视频免费观看| 欧美激情a∨在线视频播放| 亚洲国产片色| 欧美精品尤物在线| 日韩特黄影片| 午夜精品福利一区二区蜜股av| 国产精品日韩专区| 午夜日韩在线| 老司机67194精品线观看| 在线国产亚洲欧美| 欧美激情1区2区| 亚洲蜜桃精久久久久久久| 亚洲男人天堂2024| 国产午夜精品理论片a级大结局 | 一区二区日韩欧美| 欧美在线1区| 亚洲国产另类 国产精品国产免费| 女仆av观看一区| 亚洲视频香蕉人妖| 久久免费观看视频| 日韩亚洲不卡在线| 国产精品亚洲人在线观看| 久久久国产一区二区三区| 亚洲激情二区| 久久黄色小说| 日韩视频在线一区| 国产视频不卡| 欧美人与禽性xxxxx杂性| 亚洲欧美精品suv| 亚洲第一网站| 久久成人亚洲| 亚洲最新在线视频| 好看的亚洲午夜视频在线| 欧美精品一区三区| 久久黄色网页| 在线视频欧美日韩精品| 欧美大片免费观看| 欧美一区二区三区啪啪| 日韩视频三区| 激情av一区二区| 国产精品久久综合| 欧美国产欧美亚洲国产日韩mv天天看完整 | 欧美午夜精品一区二区三区| 久久久久久久97| 一区二区高清视频| 欧美激情精品久久久久久| 欧美伊人影院| 亚洲一区二区三区777| 亚洲国产乱码最新视频| 国产日韩精品久久久| 欧美三区免费完整视频在线观看| 久久亚洲春色中文字幕久久久| 亚洲一二区在线| 日韩午夜免费| 亚洲欧洲另类| 亚洲电影中文字幕| 久热精品视频在线观看一区| 亚洲曰本av电影| av成人免费观看| 日韩午夜三级在线| 亚洲精品一区在线观看| 亚洲国产高潮在线观看| 国语自产偷拍精品视频偷 | 欧美成人一区二区三区在线观看 | 亚洲欧美一区二区三区久久 | 亚洲国产精品va在线看黑人动漫 | 亚洲人午夜精品免费| 久久字幕精品一区| 久久成人一区| 久久超碰97人人做人人爱| 午夜激情综合网| 亚洲一区日韩| 亚洲视频中文| 亚洲一区精彩视频| 亚洲一区二区三区四区视频| av成人国产| 一区二区欧美日韩视频| 日韩亚洲视频| 亚洲视屏在线播放| 亚洲欧美国产视频| 午夜精品美女自拍福到在线| 亚洲一区在线免费观看| 亚洲欧美三级伦理| 欧美一级黄色网| 久久精品视频免费观看| 久久人人97超碰国产公开结果| 久久亚洲影音av资源网| 欧美成人免费在线| 亚洲激情专区| 国产精品99久久不卡二区| 亚洲欧美制服另类日韩| 久久久久五月天| 欧美韩日一区二区| 国产精品国产a| 国内久久精品| 亚洲最快最全在线视频| 欧美影院视频| 欧美国产高潮xxxx1819| 99re视频这里只有精品| 亚洲欧美中文字幕| 久久综合给合| 国产精品theporn88| 国语自产偷拍精品视频偷 | 欧美日韩直播| 国产一区二区观看| 99pao成人国产永久免费视频| 亚洲欧美日韩在线综合| 久久伊人免费视频| 艳妇臀荡乳欲伦亚洲一区| 欧美亚洲三级| 欧美日韩大片| 激情综合自拍| 亚洲欧美视频在线观看视频| 老司机午夜精品视频| 日韩视频专区| 毛片基地黄久久久久久天堂| 国产精品久久久久9999| 亚洲国产精品精华液网站| 欧美亚洲免费在线| 亚洲日本黄色| 久久综合成人精品亚洲另类欧美| 国产精品av久久久久久麻豆网| 在线免费观看日本欧美| 欧美一级大片在线免费观看| 91久久综合亚洲鲁鲁五月天| 欧美在线视频免费观看| 欧美性大战久久久久久久蜜臀| 亚洲人成毛片在线播放| 久久一区二区三区超碰国产精品|