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

yehao's Blog

CreateIoCompletionPort和完成端口

 

本文來自CSDN博客,轉(zhuǎn)載請標(biāo)明出處:http://blog.csdn.net/hionceshine/archive/2008/11/25/3362669.aspx


摘自《Networking Programming for Microsoft Windows》第八章

“完成端口”模型是迄今為止最為復(fù)雜的一種I/O模型。然而,假若一個應(yīng)用程序同時需要管理為數(shù)眾多的套接字,那么采用這種模型,往往可以達(dá)到最佳的系統(tǒng)性能!

從本質(zhì)上說,完成端口模型要求我們創(chuàng)建一個Win32完成端口對象,通過指定數(shù)量的線程,對重疊I/O請求進行管理,以便為已經(jīng)完成的重疊I/O請求提供服務(wù)。

使用這種模型之前,首先要創(chuàng)建一個I/O完成端口對象,用它面向任意數(shù)量的套接字句柄,管理多個I/O請求。要做到這一點,需要調(diào)用CreateCompletionPort函數(shù)。
該函數(shù)定義如下:


HANDLE CreateIoCompletionPort(
    HANDLE FileHandle,
    HANDLE ExistingCompletionPort,
    ULONG_PTR CompletionKey,
    DWORD NumberOfConcurrentThreads
);

在我們深入探討其中的各個參數(shù)之前,首先要注意該函數(shù)實際用于兩個明顯有別的目的:
1. 用于創(chuàng)建一個完成端口對象。
2. 將一個句柄同完成端口關(guān)聯(lián)到一起。

最開始創(chuàng)建一個完成端口時,唯一感興趣的參數(shù)便是NumberOfConcurrentThreads(并發(fā)線程的數(shù)量);前面三個參數(shù)都會被忽略。NumberOfConcurrentThreads參數(shù)的特殊之處在于,它定義了在一個完成端口上,同時允許執(zhí)行的線程數(shù)量。理想情況下,我們希望每個處理器各自負(fù)責(zé)一個線程的運行,為完成端口提供服務(wù),避免過于頻繁的線程“場景”切換。若將該參數(shù)設(shè)為0,表明系統(tǒng)內(nèi)安裝了多少個處理器,便允許同時運行多少個線程!可用下述代碼創(chuàng)建一個I/O完成端口:


hIOCP = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0);

該語句的作用是返回一個句柄,在為完成端口分配了一個套接字句柄后,用來對那個端口進行標(biāo)定(引用)。

一、工作者線程與完成端口
成功創(chuàng)建一個完成端口后,便可開始將套接字句柄與對象關(guān)聯(lián)到一起。但在關(guān)聯(lián)套接字之前,首先必須創(chuàng)建一個或多個“工作者線程”,以便在I/O請求投遞給完成端口對象后,為完成端口提供服務(wù)。在這個時候,大家或許會覺得奇怪,到底應(yīng)創(chuàng)建多少個線程,以便為完成端口提供服務(wù)呢?這實際正是完成端口模型顯得頗為“復(fù)雜”的一個方面,因為服務(wù)I/O請求所需的數(shù)量取決于應(yīng)用程序的總體設(shè)計情況。在此要記住的一個重點在于,在我們調(diào)用CreateIoCompletionPort時指定的并發(fā)線程數(shù)量,與打算創(chuàng)建的工作者線程數(shù)量相比,它們代表的并非同一件事情。早些時候,我們曾建議大家用CreateIoCompletionPort函數(shù)為每個處理器
都指定一個線程(處理器的數(shù)量有多少,便指定多少線程)以避免由于頻繁的線程“場景”交換活動,從而影響系統(tǒng)的整體性能。CreateIoCompletionPort函數(shù)的NumberOfConcurrentThreads參數(shù)明確指示系統(tǒng):在一個完成端口上,一次只允許n個工作者線程運行。假如在完成端口上創(chuàng)建的工作者線程數(shù)量超出n個,那么在同一時刻,最多只允許n個線程運行。但實際上,在一段較短的時間內(nèi),系統(tǒng)有可能超過這個值,但很快便會把它減少至事先在CreateIoCompletionPort函數(shù)中設(shè)定的值。那么,為何實際創(chuàng)建的工作者線程數(shù)量有時要比CreateIoCompletionPort函數(shù)設(shè)定的多一些呢?這樣做有必要嗎?如先前所述,這主要取決于
應(yīng)用程序的總體設(shè)計情況。假定我們的某個工作者線程調(diào)用了一個函數(shù),比如Sleep或WaitForSingleObject,但卻進入了暫停(鎖定或掛起)狀態(tài),那么允許另一個線程代替它的位置。換言之,我們希望隨時都能執(zhí)行盡可能多的線程;當(dāng)然,最大的線程數(shù)量是事先在CreateIoCompletionPort調(diào)用里設(shè)定好的。這樣一來,假如事先預(yù)計到自己的線程有可能暫時處于停頓狀態(tài),那么最好能夠創(chuàng)建比CreateIoCompletionPort的NumberOfConcurrentThreads參數(shù)的值多的線程,以便到時候充分發(fā)揮系統(tǒng)的潛力。一旦在完成端口上擁有足夠多的工作者線程來為I/O請求提供服務(wù),便可著手將套接字句柄同完成端口關(guān)聯(lián)到一起。這要求我們在一個現(xiàn)有的完成端口上,調(diào)用CreateIoCompletionPort函數(shù),同時為前三個參數(shù)——FileHandle,ExistingCompletionPort和CompletionKey——提供套接字的信息。其中, FileHandle參數(shù)指定一個要同完成端口關(guān)聯(lián)在一起的套接字句柄。ExistingCompletionPort參數(shù)指定的是一個現(xiàn)有的完成端口。CompletionKey(完成鍵)參數(shù)則指定要與某個特定套接字句柄關(guān)聯(lián)在一起的“單句柄數(shù)據(jù)”;在這個參數(shù)中,應(yīng)用程序可保存與一個套接字對應(yīng)的任意類型的信息。之所以把它叫作“單句柄數(shù)據(jù)”,是由于它只對
應(yīng)著與那個套接字句柄關(guān)聯(lián)在一起的數(shù)據(jù)。可將其作為指向一個數(shù)據(jù)結(jié)構(gòu)的指針,來保存套接字句柄;在那個結(jié)構(gòu)中,同時包含了套接字的句柄,以及與那個套接字有關(guān)的其他信息。

根據(jù)我們到目前為止學(xué)到的東西,首先來構(gòu)建一個基本的應(yīng)用程序框架。下面闡述了如何使用完成端口模型,來開發(fā)一個ECHO服務(wù)器應(yīng)用。在這個程序中,我們基本上按下述步驟行事:

1) 創(chuàng)建一個完成端口。第四個參數(shù)保持為0,指定在完成端口上,每個處理器一次只允許執(zhí)行一個工作者線程。
2) 判斷系統(tǒng)內(nèi)到底安裝了多少個處理器。
3) 創(chuàng)建工作者線程,根據(jù)步驟2)得到的處理器信息,在完成端口上,為已完成的I/O請求提供服務(wù)。
4) 準(zhǔn)備好一個監(jiān)聽套接字,在端口5150上監(jiān)聽進入的連接請求。
5) 使用accept函數(shù),接受進入的連接請求。
6) 創(chuàng)建一個數(shù)據(jù)結(jié)構(gòu),用于容納“單句柄數(shù)據(jù)”,同時在結(jié)構(gòu)中存入接受的套接字句柄。
7) 調(diào)用CreateIoCompletionPort,將自accept返回的新套接字句柄同完成端口關(guān)聯(lián)到一起。通過完成鍵(CompletionKey)參數(shù),將單句柄數(shù)據(jù)結(jié)構(gòu)傳遞給CreateIoCompletionPort。
8) 開始在已接受的連接上進行I/O操作。在此,我們希望通過重疊I/O機制,在新建的套接字上投遞一個或多個異步WSARecv或WSASend請求。這些I/O請求完成后,一個工作者線程會為I/O請求提供服務(wù),同時繼續(xù)處理未來的I/O請求,稍后便會在步驟3 )指定的工作者例程中,體驗到這一點。
9) 重復(fù)步驟5 ) ~ 8 ),直至服務(wù)器中止。

二、完成端口和重疊I/O
將套接字句柄與一個完成端口關(guān)聯(lián)在一起后,便可以套接字句柄為基礎(chǔ),投遞發(fā)送與接收請求,開始對I/O請求的處理。接下來,可開始依賴完成端口,來接收有關(guān)I/O操作完成情況的通知。從本質(zhì)上說,完成端口模型利用了Win32重疊I/O機制。在這種機制中,象WSASend和WSARecv這樣的Winsock API調(diào)用會立即返回。此時,需要由我們的應(yīng)用程序負(fù)責(zé)在以后的某個時間,通過一個OVERLAPPED結(jié)構(gòu),來接收調(diào)用的結(jié)果。在完成端口模型中,要想做到這一點,需要使用GetQueuedCompletionStatus(獲取排隊完成狀態(tài))函數(shù),讓一個或多個工作者線程在完成端口上等待。該函數(shù)的定義如下:


BOOL GetQueuedCompletionStatus(
    HANDLE CompletionPort,
    LPDWORD lpNumberOfBytes,
    PULONG_PTR lpCompletionKey,
    LPOVERLAPPED* lpOverlapped,
    DWORD dwMilliseconds
);

其中,CompletionPort參數(shù)對應(yīng)于要在上面等待的完成端口。lpNumberOfBytes參數(shù)負(fù)責(zé)在完成了一次I/O操作后(如WSASend或WSARecv),接收實際傳輸?shù)淖止?jié)數(shù)。lpCompletionKey參數(shù)為原先傳遞進入CreateIoCompletionPort函數(shù)的套接字返回“單句柄數(shù)據(jù)”。如我們早先所述,大家最好將套接字句柄保存在這個“鍵”(Key)中。lpOverlapped參數(shù)用于接收完成的I/O操作的重疊結(jié)果。這實際是一個相當(dāng)重要的參數(shù),因為可用它獲取每個I/O操作的數(shù)據(jù)。而最后一個參數(shù),dwMilliseconds,用于指定調(diào)用者希望等待一個完成數(shù)據(jù)包在完成端口上出現(xiàn)的時間。假如將其設(shè)為INFINITE,調(diào)用會無休止地等待下去。

三、單句柄數(shù)據(jù)和單I/O操作數(shù)據(jù)
一個工作者線程從GetQueuedCompletionStatus這個API調(diào)用接收到I/O完成通知后,在lpCompletionKey和lpOverlapped參數(shù)中,會包含一些必要的套接字信息。利用這些信息,可通過完成端口,繼續(xù)在一個套接字上的I/O處理。通過這些參數(shù),可獲得兩方面重要的套接字?jǐn)?shù)據(jù):單句柄數(shù)據(jù),以及單I/O操作數(shù)據(jù)。其中,lpCompletionKey參數(shù)包含了“單句柄數(shù)據(jù)”,因為在一個套接字首次與完成端口關(guān)聯(lián)到一起的時候,那些數(shù)據(jù)便與一個特定的套接字句柄對應(yīng)起來了。這些數(shù)據(jù)正是我們在進行CreateIoCompletionPort API調(diào)用的時候,通過CompletionKey參數(shù)傳遞的。如早先所述,應(yīng)用程序可通過該參數(shù)傳遞任意類型的數(shù)據(jù)。通常情況下,應(yīng)用程序會將與I/O請求有關(guān)的套接字句柄保存在這里。lpOverlapped參數(shù)則包含了一個OVERLAPPED結(jié)構(gòu),在它后面跟隨“單I/O操作數(shù)據(jù)”。我們的工作者線程處理一個完成數(shù)據(jù)包時(將數(shù)據(jù)原封不動打轉(zhuǎn)回去,接受連接,投遞另一個線程,等等),這些信息是它必須要知道的。單I/O操作數(shù)據(jù)可以是追加到一個OVERLAPPED結(jié)構(gòu)末尾的、任意數(shù)量的字節(jié)。假如一個函數(shù)要求用到一個OVERLAPPED結(jié)構(gòu),我們便必須將這樣的一個結(jié)構(gòu)傳遞進去,以滿足它的要求。要想做到這一點,一個簡單的方法是定義一個結(jié)構(gòu),然后將OVERLAPPED結(jié)構(gòu)作為新結(jié)構(gòu)的第一個元素使用。舉個例子來說,可定義下述數(shù)據(jù)結(jié)構(gòu),實現(xiàn)對單I/O操作數(shù)據(jù)的管理:


typedef struct
{
    OVERLAPPED Overlapped;
    WSABUF     DataBuf;
    CHAR       Buffer[DATA_BUFSIZE];
    BOOL       OperationType;
}PER_IO_OPERATION_DATA

該結(jié)構(gòu)演示了通常要與I/O操作關(guān)聯(lián)在一起的某些重要數(shù)據(jù)元素,比如剛才完成的那個I/O操作的類型(發(fā)送或接收請求)。在這個結(jié)構(gòu)中,我們認(rèn)為用于已完成I/O操作的數(shù)據(jù)緩沖區(qū)是非常有用的。要想調(diào)用一個Winsock API函數(shù),同時為其分配一個OVERLAPPED結(jié)構(gòu),既可將自己的結(jié)構(gòu)“造型”為一個OVERLAPPED指針,亦可簡單地撤消對結(jié)構(gòu)中的OVERLAPPED元素的引用。如下例所示:

PER_IO_OPERATION_DATA PerIoData;
// 可像下面這樣調(diào)用一個函數(shù)
  WSARecv(socket, ..., (OVERLAPPED *)&PerIoData);
// 或像這樣
  WSARecv(socket, ..., &(PerIoData.Overlapped));

在工作線程的后面部分,等GetQueuedCompletionStatus函數(shù)返回了一個重疊結(jié)構(gòu)(和完成鍵)后,便可通過撤消對OperationType成員的引用,調(diào)查到底是哪個操作投遞到了這個句柄之上(只需將返回的重疊結(jié)構(gòu)造型為自己的PER_IO_OPERATION_DATA結(jié)構(gòu))。對單I/O操作數(shù)據(jù)來說,它最大的一個優(yōu)點便是允許我們在同一個句柄上,同時管理多個I/O操作(讀/寫,多個讀,多個寫,等等)。大家此時或許會產(chǎn)生這樣的疑問:在同一個套接字上,真的有必要同時投遞多個I/O操作嗎?答案在于系統(tǒng)的“伸縮性”,或者說“擴展能力”。例如,假定我們的機器安裝了多個中央處理器,每個處理器都在運行一個工作者線程,那么在同一個時
候,完全可能有幾個不同的處理器在同一個套接字上,進行數(shù)據(jù)的收發(fā)操作。

最后要注意的一處細(xì)節(jié)是如何正確地關(guān)閉I/O完成端口—特別是同時運行了一個或多個線程,在幾個不同的套接字上執(zhí)行I/O操作的時候。要避免的一個重要問題是在進行重疊I/O操作的同時,強行釋放一個OVERLAPPED結(jié)構(gòu)。要想避免出現(xiàn)這種情況,最好的辦法是針對每個套接字句柄,調(diào)用closesocket函數(shù),任何尚未進行的重疊I/O操作都會完成。一旦所有套接字句柄都已關(guān)閉,便需在完成端口上,終止所有工作者線程的運行。要想做到這一點, 需要使用PostQueuedCompletionStatus函數(shù),向每個工作者線程都發(fā)送一個特殊的完成數(shù)據(jù)包。該函數(shù)會指示每個線程都“立即結(jié)束并退出”。下面是PostQueuedCompletionStatus函數(shù)的定義:


BOOL PostQueuedCompletionStatus(
    HANDLE CompletionPort,
    DWORD dwNumberOfBytesTransferred,
    ULONG_PTR dwCompletionKey,
    LPOVERLAPPED lpOverlapped
);

其中,CompletionPort參數(shù)指定想向其發(fā)送一個完成數(shù)據(jù)包的完成端口對象。而就dwNumberOfBytesTransferred、dwCompletionKey和lpOverlapped這三個參數(shù)來說,每一個都允許我們指定一個值,直接傳遞給GetQueuedCompletionStatus函數(shù)中對應(yīng)的參數(shù)。這樣一來,一個工作者線程收到傳遞過來的三個GetQueuedCompletionStatus函數(shù)參數(shù)后,便可根據(jù)由這三個參數(shù)的某一個設(shè)置的特殊值,決定何時應(yīng)該退出。例如,可用dwCompletionPort參數(shù)傳遞0值,而一個工作者線程會將其解釋成中止指令。一旦所有工作者線程都已關(guān)閉,便可使用CloseHandle函數(shù),關(guān)閉完成端口,最終安全退出程序。

注:CreateIoCompletionPort ,PostQueuedCompletionStatus ,GetQueuedCompletionStatus 等函數(shù)的用法說明。

Platform SDK: Storage

 

 

I/O Completion Ports

I/O completion ports are the mechanism by which an application uses a pool of threads that was created when the application was started to process asynchronous I/O requests. These threads are created for the sole purpose of processing I/O requests. Applications that process many concurrent asynchronous I/O requests can do so more quickly and efficiently by using I/O completion ports than by using creating threads at the time of the I/O request.

 

 

 

 

 

I/O完成端口(s)是一種機制,通過這個機制,應(yīng)用程序在啟動時會首先創(chuàng)建一個線程池,然后該應(yīng)用程序使用線程池處理異步I/O請求。這些線程被創(chuàng)建的唯一目的就是用于處理I/O請求。對于處理大量并發(fā)異步I/O請求的應(yīng)用程序來說,相比于在I/O請求發(fā)生時創(chuàng)建線程來說,使用完成端口(s)它就可以做的更快且更有效率。

 

 

 

 

 

The CreateIoCompletionPort function associates an I/O completion port with one or more file handles. When an asynchronous I/O operation started on a file handle associated with a completion port is completed, an I/O completion packet is queued to the port. This can be used to combine the synchronization point for multiple file handles into a single object.

 

 

 

 

 

CreateIoCompletionPort函數(shù)會使一個I/O完成端口與一個或多個文件句柄發(fā)生關(guān)聯(lián)。當(dāng)與一個完成端口相關(guān)的文件句柄上啟動的異步I/O操作完成時,一個I/O完成包就會進入到該完成端口的隊列中。對于多個文件句柄來說,就可以把這些多個文件句柄合并成一個單獨的對象,這個可以被用來結(jié)合同步點?

 

 

 

 

 

A thread uses the GetQueuedCompletionStatus function to wait for a completion packet to be queued to the completion port, rather than waiting directly for the asynchronous I/O to complete. Threads that block their execution on a completion port are released in last-in-first-out (LIFO) order. This means that when a completion packet is queued to the completion port, the system releases the last thread to block its execution on the port.

 

 

調(diào)用GetQueuedCompletionStatus函數(shù),某個線程就會等待一個完成包進入到完成端口的隊列中,而不是直接等待異步I/O請求完成。線程(們)就會阻塞于它們的運行在完成端口(按照后進先出隊列順序的被釋放)。這就意味著當(dāng)一個完成包進入到完成端口的隊列中時,系統(tǒng)會釋放最近被阻塞在該完成端口的線程。

 

 

 

 

 

When a thread calls GetQueuedCompletionStatus, it is associated with the specified completion port until it exits, specifies a different completion port, or frees the completion port. A thread can be associated with at most one completion port.

 

 

調(diào)用GetQueuedCompletionStatus,線程就會將會與某個指定的完成端口建立聯(lián)系,一直延續(xù)其該線程的存在周期,或被指定了不同的完成端口,或者釋放了與完成端口的聯(lián)系。一個線程只能與最多不超過一個的完成端口發(fā)生聯(lián)系。

 

 

 

 

 

The most important property of a completion port is the concurrency value. The concurrency value of a completion port is specified when the completion port is created. This value limits the number of runnable threads associated with the completion port. When the total number of runnable threads associated with the completion port reaches the concurrency value, the system blocks the execution of any subsequent threads that specify the completion port until the number of runnable threads associated with the completion port drops below the concurrency value. The most efficient scenario occurs when there are completion packets waiting in the queue, but no waits can be satisfied because the port has reached its concurrency limit. In this case, when a running thread calls GetQueuedCompletionStatus, it will immediately pick up the queued completion packet. No context switches will occur, because the running thread is continually picking up completion packets and the other threads are unable to run.

 

 

完成端口最重要的特性就是并發(fā)量。完成端口的并發(fā)量可以在創(chuàng)建該完成端口時指定。該并發(fā)量限制了與該完成端口相關(guān)聯(lián)的可運行線程的數(shù)目。當(dāng)與該完成端口相關(guān)聯(lián)的可運行線程的總數(shù)目達(dá)到了該并發(fā)量,系統(tǒng)就會阻塞任何與該完成端口相關(guān)聯(lián)的后續(xù)線程的執(zhí)行,直到與該完成端口相關(guān)聯(lián)的可運行線程數(shù)目下降到小于該并發(fā)量為止。最有效的假想是發(fā)生在有完成包在隊列中等待,而沒有等待被滿足,因為此時完成端口達(dá)到了其并發(fā)量的極限。此時,一個正在運行中的線程調(diào)用GetQueuedCompletionStatus時,它就會立刻從隊列中取走該完成包。這樣就不存在著環(huán)境的切換,因為該處于運行中的線程就會連續(xù)不斷地從隊列中取走完成包,而其他的線程就不能運行了。

 

 

 

 

 

The best value to pick for the concurrency value is the number of CPUs on the machine. If your transaction required a lengthy computation, a larger concurrency value will allow more threads to run. Each transaction will take longer to complete, but more transactions will be processed at the same time. It is easy to experiment with the concurrency value to achieve the best effect for your application.

 

 

對于并發(fā)量最好的挑選值就是您計算機中cpu的數(shù)目。如果您的事務(wù)處理需要一個漫長的計算時間,一個比較大的并發(fā)量可以允許更多線程來運行。雖然完成每個事務(wù)處理需要花費更長的時間,但更多的事務(wù)可以同時被處理。對于應(yīng)用程序來說,很容易通過測試并發(fā)量來獲得最好的效果。

 

 

 

 

 

The PostQueuedCompletionStatus function allows an application to queue its own special-purpose I/O completion packets to the completion port without starting an asynchronous I/O operation. This is useful for notifying worker threads of external events.

 

 

PostQueuedCompletionStatus函數(shù)允許應(yīng)用程序可以針對自定義的專用I/O完成包進行排隊,而無需啟動一個異步I/O操作。這點對于通知外部事件的工作者線程來說很有用。

 

 

 

 

 

The completion port is freed when there are no more references to it. The completion port handle and every file handle associated with the completion port reference the completion port. All the handles must be closed to free the completion port. To close the port handle, call the CloseHandle function.

 

 

在沒有更多的引用針對某個完成端口時,需要釋放該完成端口。該完成端口句柄以及與該完成端口相關(guān)聯(lián)的所有文件句柄都需要被釋放。調(diào)用CloseHandle可以釋放完成端口的句柄。

 

posted on 2011-06-06 21:09 厚積薄發(fā) 閱讀(639) 評論(0)  編輯 收藏 引用 所屬分類: 網(wǎng)絡(luò)編程

導(dǎo)航

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

統(tǒng)計

常用鏈接

留言簿

隨筆分類

文章分類

文章檔案

搜索

最新評論

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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国产精品视频免费观看一公开 | 午夜在线播放视频欧美| 欧美久久久久久蜜桃| 亚洲国产精品视频| 欧美国产91| 欧美日韩三区四区| 亚洲天堂网在线观看| 亚洲午夜视频在线| 国产日韩视频| 欧美国产激情| 欧美日韩精品一区二区在线播放| 亚洲一区在线免费观看| 亚洲小视频在线观看| 国外精品视频| 亚洲国产午夜| 欧美日韩伊人| 欧美有码在线视频| 麻豆精品传媒视频| 在线中文字幕一区| 欧美一区二区免费视频| 亚洲人成精品久久久久| 亚洲一区二区精品在线观看| 国产一区二区三区在线观看视频 | 亚洲精品一二区| 国产精品美女久久久久久2018 | 欧美在线播放高清精品| 久久网站热最新地址| 亚洲专区在线| 老司机久久99久久精品播放免费| av成人免费在线观看| 性欧美大战久久久久久久久| 最近看过的日韩成人| 亚洲专区一区| 99这里只有精品| 久久国内精品自在自线400部| 一本久道综合久久精品| 欧美一区二区视频在线| 一区二区三区黄色| 久久久久久久网站| 午夜亚洲影视| 欧美精品在线免费观看| 裸体歌舞表演一区二区| 国产精品电影网站| 亚洲国产一二三| 韩国v欧美v日本v亚洲v| 中国女人久久久| 亚洲精品字幕| 久久伊人精品天天| 久久久久国产精品厨房| 欧美日韩中文| 亚洲精品国产精品乱码不99按摩| 狠狠色狠狠色综合日日五| 99视频+国产日韩欧美| 亚洲激情在线| 久久久久久尹人网香蕉| 久久动漫亚洲| 国产精品综合色区在线观看| 99热精品在线| 一区二区三区www| 欧美巨乳在线| 亚洲人成绝费网站色www| 亚洲国产成人av| 久久久91精品国产| 麻豆精品在线观看| 激情久久久久久| 久久久久成人精品| 美女网站在线免费欧美精品| 国产亚洲精品久久久久久| 亚洲欧美在线播放| 久久av资源网| 狠狠入ady亚洲精品| 欧美中文在线观看国产| 久久夜色精品国产| 伊人婷婷欧美激情| 免费成人av| 91久久久亚洲精品| 亚洲最黄网站| 国产精品视频导航| 性做久久久久久久免费看| 欧美综合国产| 精品51国产黑色丝袜高跟鞋| 久久综合久久久久88| 欧美国产日韩免费| 99热这里只有精品8| 国产精品国产三级国产专播精品人 | 亚洲国产精品ⅴa在线观看| 久久中文字幕导航| 亚洲精品视频啊美女在线直播| 亚洲人成网站影音先锋播放| 欧美日韩国产探花| 亚洲一区欧美二区| 毛片一区二区| 一区二区三区日韩精品| 国产伦精品一区二区三区视频孕妇| 亚洲欧美日韩综合aⅴ视频| 久久在线视频| 亚洲免费观看在线观看| 国产精品人成在线观看免费 | 亚洲高清一区二| 亚洲一二三区在线| 国产一级久久| 欧美日韩精品久久| 久久国产免费看| 99天天综合性| 久久天堂国产精品| 一本色道久久精品| 韩国精品主播一区二区在线观看| 欧美成人自拍| 欧美在线免费| 一本色道婷婷久久欧美| 久久综合中文字幕| 亚洲一区二区三区乱码aⅴ| 影视先锋久久| 国产精品视频免费| 欧美大片在线看免费观看| 亚洲欧美日韩中文视频| 亚洲国产欧美一区二区三区久久| 欧美怡红院视频一区二区三区| 91久久久久久| 精品1区2区| 国产亚洲精品久| 国产精品大片| 欧美日本高清视频| 久热re这里精品视频在线6| 亚洲天堂久久| 99国产精品久久久久久久久久| 美日韩在线观看| 久久久国产精彩视频美女艺术照福利| 一本色道久久99精品综合| 在线国产精品播放| 国产综合色在线| 国产伦精品一区二区三区视频孕妇| 欧美国产日韩精品| 另类人畜视频在线| 欧美在线国产| 欧美亚洲一区二区在线| 亚洲综合精品四区| 一本一本久久a久久精品综合妖精| 亚洲观看高清完整版在线观看| 久久久欧美一区二区| 久久精品国产亚洲高清剧情介绍| 亚洲伊人伊色伊影伊综合网| 一区二区三区**美女毛片| 日韩网站免费观看| 日韩一级精品| 在线一区视频| 亚洲午夜免费福利视频| 亚洲砖区区免费| 午夜精品视频| 欧美尤物一区| 久久亚洲一区二区| 欧美成人精品在线视频| 久久只精品国产| 欧美成年视频| 亚洲黄色一区二区三区| 亚洲黄色视屏| 在线综合视频| 午夜欧美电影在线观看| 久久国产精品亚洲77777| 久久一区二区三区四区| 免费美女久久99| 欧美日韩四区| 国产欧美日韩另类一区| 国产一级久久| 亚洲人成在线观看网站高清| 日韩午夜激情av| 亚洲欧美电影院| 久久久青草婷婷精品综合日韩| 久久天天躁狠狠躁夜夜av| 男人的天堂亚洲| 亚洲精品国产精品国自产观看| 一区二区三区日韩欧美精品| 午夜久久美女| 免费h精品视频在线播放| 欧美视频在线视频| 国产一区二区精品久久91| 91久久国产综合久久91精品网站| 一本色道久久加勒比88综合| 欧美在线视频观看| 美日韩精品免费| 一区二区三区鲁丝不卡| 久久精品论坛| 国产精品99免费看| 在线精品视频免费观看| 一区二区日韩免费看| 久久婷婷激情| 一区二区日本视频| 久久在线免费观看视频| 国产精品久久久久久久久久三级| 尤物精品国产第一福利三区| 一区二区三区高清不卡| 快she精品国产999| 一二三四社区欧美黄| 久久婷婷影院| 国产亚洲欧美日韩一区二区| 一区二区三区免费在线观看| 久久亚洲精品视频| 亚洲无限乱码一二三四麻| 欧美国产日韩一区二区在线观看| 国产视频综合在线|