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

S.l.e!ep.¢%

像打了激速一樣,以四倍的速度運轉,開心的工作
簡單、開放、平等的公司文化;尊重個性、自由與個人價值;
posts - 1098, comments - 335, trackbacks - 0, articles - 1
  C++博客 :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理

封裝了IOCP

Posted on 2009-01-31 19:47 S.l.e!ep.¢% 閱讀(3296) 評論(8)  編輯 收藏 引用 所屬分類: C++
1. 不使用線程池
2.? 暫時只封裝了 win32 的 icop
3.? 暫時還未寫測試用例,因為不知道怎么寫 -_-!!!

//?networksocket.h:?interface?for?the?CNetworkSocket?class.
//
//////////////////////////////////////////////////////////////////////

#if?!defined(NETWORKSOCKET_H__A63ED8A5_7ED1_463D_A0F0_41F6E9C79441__INCLUDED_)
#define?NETWORKSOCKET_H__A63ED8A5_7ED1_463D_A0F0_41F6E9C79441__INCLUDED_

#if?_MSC_VER?>?1000
#pragma?once
#endif?//?_MSC_VER?>?1000

#include?
<vector>

#include?
<winsock2.h>
#include?
<process.h>
#pragma??comment(lib,?
"ws2_32.lib")

#define?BUFFER_SIZE?4096

enum?OPERATION_TYPE
{
????OPERATION_TYPE_RECV?
=?0,
????OPERATION_TYPE_SEND?
=?1
}
;

//IO操作數據
typedef?struct?_PER_IO_OPERATION_DATA
{
????OVERLAPPED?OverLapped;
????WSABUF?DataBuf;
????
char?szBuf[BUFFER_SIZE];
????OPERATION_TYPE?OperationType;??????
//?操作類型表示

}
PER_IO_OPERATION_DATA,*PPER_IO_OPERATION_DATA;

class?CNetworkSocket??
{
public:
????CNetworkSocket();
????
virtual?~CNetworkSocket();

????
bool?init();
????
bool?uninit();

????
bool?initNetWork(unsigned?short?nPort);
????
bool?unitNetWork();

????
bool?send(SOCKET?s,?const?char*?pBuf,?int?nLen);

private:
????SOCKET?m_listensock;
????HANDLE?m_hIocpPort;
????std::vector
<HANDLE>?m_vectorThreadHandle;

????
static?unsigned?__stdcall?_WorkerThreadProc(void*?pVoid);????
????
static?unsigned?__stdcall?_AcceptThreadProc(void*?pVoid);
}
;

#endif?//?!defined(NETWORKSOCKET_H__A63ED8A5_7ED1_463D_A0F0_41F6E9C79441__INCLUDED_)

//?networksocket.cpp:?implementation?of?the?CNetworkSocket?class.
//
//////////////////////////////////////////////////////////////////////

#include?
"networksocket.h"

//////////////////////////////////////////////////////////////////////
//?Construction/Destruction
//////////////////////////////////////////////////////////////////////

CNetworkSocket::CNetworkSocket()
{
????m_listensock?
=?INVALID_SOCKET;
????m_hIocpPort??
=?INVALID_HANDLE_VALUE;
}


CNetworkSocket::
~CNetworkSocket()
{

}


bool?CNetworkSocket::init()
{
????WORD?wVersionRequested;
????WSADATA?wsaData;
????
int?nErrCode?=?0;
????
????wVersionRequested?
=?MAKEWORD(2,?2);
????
????nErrCode?
=?::WSAStartup(wVersionRequested,?&wsaData);
????
if?(?nErrCode?!=?0?)?
????
{
????????
return?false;
????}


????
if?(?LOBYTE(wsaData.wVersion)?!=?2?||?HIBYTE(wsaData.wVersion)?!=?2?)?
????
{
????????
bool?b?=?uninit();
????????
return?false;
????}

????
else
????
{
????????
return?true;
????}

}


bool?CNetworkSocket::uninit()
{
????
int?nErrCode?=?0;
????nErrCode?
=?::WSACleanup();

????
return?true;
}


bool?CNetworkSocket::initNetWork(unsigned?short?nPort)
{
????
int?nErrCode?=?0;

????
//?創建?socket
????m_listensock?=?::WSASocket(AF_INET,?SOCK_STREAM,?0,?NULL,?0,?WSA_FLAG_OVERLAPPED);
????
????
if(?INVALID_SOCKET?==?m_listensock?)
????
{
????????nErrCode?
=?::WSAGetLastError();
????????
return?false;
????}


????
//?綁定端口
????sockaddr_in?InternetAddr;
????InternetAddr.sin_family?
=?AF_INET;
????InternetAddr.sin_addr.S_un.S_addr?
=?::htonl(INADDR_ANY);
????InternetAddr.sin_port?
=?htons(nPort);

????
if(?::bind(?m_listensock,?(PSOCKADDR)&InternetAddr,?sizeof(InternetAddr))?==?SOCKET_ERROR?)
????
{
????????nErrCode?
=?::WSAGetLastError();
????????
return?false;
????}


????
//?開始監聽
????if(????::listen(m_listensock,?5)?==?SOCKET_ERROR?)
????
{
????????nErrCode?
=?::WSAGetLastError();
????????
return?false;
????}


????
//?創建完成端口
????m_hIocpPort?=?::CreateIoCompletionPort(INVALID_HANDLE_VALUE,?NULL,?0,?0);
????????
????
if(?m_hIocpPort?==?INVALID_HANDLE_VALUE?)
????
{
????????nErrCode?
=?::WSAGetLastError();
????????
return?false;
????}


????
//?啟動工作線程,線程數為CPU處理器數量*2+2
????SYSTEM_INFO?sys_Info;
????::GetSystemInfo(
&sys_Info);

????
for(int?i?=?0;?i?<?(int(sys_Info.dwNumberOfProcessors)?*?2?+?2);?i++)
????
{
????????HANDLE?ThreadHandle?
=?INVALID_HANDLE_VALUE;
????????DWORD?ThreadID??????
=?0;
????????
????????unsigned?
int?nThreadId??=???0?;
????????ThreadHandle?
=?(HANDLE)_beginthreadex(NULL,?0,?_WorkerThreadProc,?(void?*)this,??0,?&nThreadId);
????????
????????
if?(?ThreadHandle?==?0?)
????????????
return?false;

????????m_vectorThreadHandle.push_back(ThreadHandle);
????}


????
//?啟動偵聽線程
????HANDLE?ThreadHandle?=?INVALID_HANDLE_VALUE;
????unsigned?
int?nThreadId?=?0?;

????ThreadHandle?
=?(HANDLE)_beginthreadex(NULL,?0,?_AcceptThreadProc,?(void?*)this,??0,?&nThreadId);
????
????
if?(?ThreadHandle?==?0?)
????????????
return?false;

????m_vectorThreadHandle.push_back(ThreadHandle);

????
return?true;
}


bool?CNetworkSocket::unitNetWork()
{
????
//?啟動工作線程,線程數為CPU處理器數量*2+2
????SYSTEM_INFO?sys_Info;
????::GetSystemInfo(
&sys_Info);
????
????
for(int?i?=?0;?i?<?(int(sys_Info.dwNumberOfProcessors)?*?2?+?2);?i++)
????
{
????????
//寄出退出消息
????????::PostQueuedCompletionStatus(m_hIocpPort,????-1,????-1,?NULL);
????}


????std::vector
<HANDLE>::iterator?iter_t;
????
for?(?iter_t?=?m_vectorThreadHandle.begin();?iter_t?!=?m_vectorThreadHandle.end();?iter_t++?)
????
{?
????????DWORD?dwRet?
=?::WaitForSingleObject(*iter_t,?INFINITE);
????}


????
//關閉網絡的偵聽
????::shutdown(m_listensock,?0);
????::closesocket(m_listensock);
????
????
return?true;
}


unsigned?__stdcall?CNetworkSocket::_WorkerThreadProc(
void*?pVoid)
{
????CNetworkSocket
*?pThis?=?(CNetworkSocket*)pVoid;
????DWORD?dwByteTransferred?
=?0;
????unsigned?
long?nFlag?=?0;
????DWORD?RecvByte?
=?0;

????SOCKET?ClientSock?
=?INVALID_SOCKET;
?????PPER_IO_OPERATION_DATA?PerIoData;

?????
while?(?true?)
?????
{
????????BOOL?bSuccess?
=?::GetQueuedCompletionStatus(pThis->m_hIocpPort,
???????????????????????????????????????????????????????
&dwByteTransferred,
?????????????????????????????????????????????????????(LPDWORD)
&ClientSock,
?????????????????????????????????????????????????????(LPOVERLAPPED
*)&PerIoData,
?????????????????????????????????????????????????????INFINITE);

????????
//退出信號到達,退出線程
????????if(?dwByteTransferred?==?-1?&&?PerIoData?==?NULL?)
????????????
return?1;

????????
//客戶機已經斷開連接或者連接出現錯誤
????????if(?dwByteTransferred?==?0?&&?(PerIoData->OperationType?==?OPERATION_TYPE_RECV?||?PerIoData->OperationType?==?OPERATION_TYPE_SEND?)?)
????????
{
????????????::closesocket(ClientSock);
????????????::GlobalFree(PerIoData);
????????????
continue;
????????}


????????
//?接收完成
????????if?(?PerIoData->OperationType?==?OPERATION_TYPE_RECV?)
????????
{
????????????
//?處理接收數據
????????????
//?pThis->OnRecv(ClientSock,?PerIoData->szBuf,?dwByteTransferred);

????????????
//將源數據置空
????????????::memset(PerIoData->szBuf,?0,?BUFFER_SIZE);
????????????dwByteTransferred
=0;

????????????
//重置IO操作數據
????????????unsigned?long?Flag=0;
????????????::ZeroMemory(
&(PerIoData->OverLapped),?sizeof(OVERLAPPED));
????????????
????????????PerIoData
->DataBuf.buf????=?PerIoData->szBuf;
????????????PerIoData
->DataBuf.len????=?BUFFER_SIZE;
????????????PerIoData
->OperationType?=?OPERATION_TYPE_RECV;

????????????
//?再投遞另一個Recv請求
????????????::WSARecv(ClientSock,?&(PerIoData->DataBuf),?1,?&RecvByte,?&Flag,?&(PerIoData->OverLapped),????NULL);
????????}


????????
//?發送完成,置空緩沖區,釋放緩沖區
????????if(?PerIoData->OperationType?==?OPERATION_TYPE_SEND?)
????????
{
????????????::memset(PerIoData,?
0,?sizeof(PER_IO_OPERATION_DATA));
????????????::GlobalFree(PerIoData);
????????????dwByteTransferred?
=?0;
????????}

?
?????}
//?while?(?true?)

????
return?0;
}


unsigned?__stdcall?CNetworkSocket::_AcceptThreadProc(
void*?pVoid)
{
????CNetworkSocket
*?pThis?=?(CNetworkSocket*)pVoid;

????SOCKET?AcceptSock?
=?INVALID_SOCKET;

????
while?(?true?)
????
{
????????AcceptSock?
=?::WSAAccept(pThis->m_listensock,?NULL,?NULL,?NULL,?0);

????????
//關聯客戶端口到完成端口,句柄數據在此時被綁定到完成端口
????????::CreateIoCompletionPort((HANDLE)AcceptSock,?pThis->m_hIocpPort,?(DWORD)AcceptSock,?0);

????????PPER_IO_OPERATION_DATA?PerIoData?
=?(PPER_IO_OPERATION_DATA)::GlobalAlloc(GPTR,?sizeof(PER_IO_OPERATION_DATA));
????????unsigned?
long?nFlag?=?0;
????????DWORD?RecvByte?
=?0;
????????::ZeroMemory(
&(PerIoData->OverLapped),sizeof(OVERLAPPED));
????????
????????PerIoData
->DataBuf.buf?????=?PerIoData->szBuf;
????????PerIoData
->DataBuf.len?????=?BUFFER_SIZE;
????????PerIoData
->OperationType??=?OPERATION_TYPE_RECV;

????????
//提交首個接收數據請求
????????
//這時
????????
//如果客戶端斷開連接
????????
//則也可以以接收數據時得到通知????
????????::WSARecv(AcceptSock,?&(PerIoData->DataBuf),?1,?&RecvByte,?&nFlag,?&(PerIoData->OverLapped),?NULL);

????}
//?while?(?true?)

????
return?0;
}


bool?CNetworkSocket::send(SOCKET?s,?const?char*?pBuf,?int?nLen)
{
????
if(?s?==?INVALID_SOCKET?||?pBuf?==?NULL?||?nLen?==?0?)
????????
return?false;
????
????PPER_IO_OPERATION_DATA?PerIoData?
=?(PPER_IO_OPERATION_DATA)::GlobalAlloc(GPTR,?sizeof(PER_IO_OPERATION_DATA));
????
????unsigned?
long?nFlag?=?0;
????DWORD?dwSendByte?
=?0;
????::ZeroMemory(
&(PerIoData->OverLapped),?sizeof(OVERLAPPED));
????::memcpy(PerIoData
->szBuf,?pBuf,?nLen);

????PerIoData
->DataBuf.buf?=?PerIoData->szBuf;
????PerIoData
->DataBuf.len?=?nLen;
????PerIoData
->OperationType??=?OPERATION_TYPE_SEND;

????
int?nRet?=?::WSASend(s,?&(PerIoData->DataBuf),?1,?&dwSendByte,?nFlag,?&(PerIoData->OverLapped),?NULL);

????
if(?nRet==SOCKET_ERROR?&&?GetLastError()?!=?WSA_IO_PENDING?)
????
{
????????
return?false;
????}

????
else
????
{
????????
return?true;
????}

}

Feedback

# re: 封裝了IOCP  回復  更多評論   

2009-01-31 19:56 by nn
在send時,重新分配了一個IO對象,這個對象也許不會在你想象中那樣被釋放了。

在GET中的釋放的地方,好像沒問題,但如果達到上千個連接,而且每個連接的數據非量密的時候,會發現GET時總是在判斷Recv的情況而沒有判斷Send的情況。

# re: 封裝了IOCP  回復  更多評論   

2009-01-31 19:56 by nn
這種情況,send時分配的對象就堆在服務器了。

# re: 封裝了IOCP  回復  更多評論   

2009-01-31 19:59 by 苦丁茶
現在我一直在懷疑WSASend后,GET一直沒有取得完成的事件。
雖然都說肯定會有完成事件的。

總這,你這個類可以應付小型的網絡應用,但無法應付上規模的應用。

# re: 封裝了IOCP  回復  更多評論   

2009-01-31 20:37 by 苦丁茶
這個類還有一個問題,
就是當連接斷開后,沒有清理資源。
還有沒有主動檢測無效連接的功能。

# re: 封裝了IOCP  回復  更多評論   

2009-01-31 20:42 by 85093103
在WinSock上使用IOCP
本文章假設你已經理解WindowsNT的I/O模型以及I/O完成端口(IOCP),并且比較熟悉將要用到的API,如果你打算學習IOCP,請參考Jeffery Richter的Advanced Windows(第三版),第15章I/O設備,里面有極好的關于完成端口的討論以及對即將使用API的說明。
IOCP提供了一個用于開發高效率和易擴展程序的模型。Winsock2提供了對IOCP的支持,并在WindowsNT平臺得到了完整的實現。然而IOCP是所有WindowsNT I/O模型中最難理解和實現的,為了幫助你使用IOCP設計一個更好的Socket服務,本文提供了一些訣竅。
Tip 1:使用Winsock2 IOCP函數例如WSASend和WSARecv,如同Win32文件I/O函數,例如WriteFile和ReadFile。
微軟提供的Socket句柄是一個可安裝文件系統(IFS)句柄,因此你可以使用Win32的文件I/O函數調用這個句柄,然而,將Socket句柄和文件系統聯系起來,你不得不陷入很多的Kernal/User模式轉換的問題中,例如線程的上下文轉換,花費的代價還包括參數的重新排列導致的性能降低。
因此你應該使用只被Winsock2中IOCP允許的函數來使用IOCP。在ReadFile和WriteFile中會發生的額外的參數重整以及模式轉換只會發生在一種情況下,那就是如果句柄的提供者并沒有將自己的WSAPROTOCOL_INFO結構中的DwServiceFlags1設置為XP1_IFS_HANDLES。
注解:即使使用WSASend和WSARecv,這些提供者仍然具有不可避免的額外的模式轉換,當然ReadFile和WriteFile需要更多的轉換。
TIP 2: 確定并發工作線程數量和產生的工作線程總量。
并發工作線程的數量和工作線程的數量并不是同一概念。你可以決定IOCP使用最多2個的并發線程以及包括10個工作線程的線程池。工作線程池擁有的線程多于或者等于并發線程的數量時,工作線程處理隊列中一個封包的時候可以調用win32的Wait函數,這樣可以無延遲的處理隊列中另外的封包。
如果隊列中有正在等待被處理的封包,系統將會喚醒一個工作線程處理他,最后,第一個線程確認正在休眠并且可以被再次調用,此時,可調用線程數量會多于IOCP允許的并發線程數量(例如,NumberOFConcurrentThreads)。然而,當下一個線程調用GetQueueCompletionStatus并且進入等待狀態,系統不會喚醒他。一般來說,系統會試圖保持你設定的并發工作線程數量。
一般來講,每擁有一個CPU,在IOCP中你可以使用一個并發工作線程,要做到這點,當你第一次初始化IOCP的時候,可以在調用CreateIOCompletionPort的時候將NumberOfConcurrentThreads設置為0。
TIP 3:將一個提交的I/O操作和完成封包的出列聯系起來。
當對一個封包進行出列,可以調用GetQueuedCompletionStatus返回一個完成Key和一個復合的結構體給I/O。你可以分別的使用這兩個結構體來返回一個句柄和一個I/O操作信息,當你將IOCP提供的句柄信息注冊給Socket,那么你可以將注冊的Socket句柄當做一個完成Key來使用。為每一個I/O的"extend"操作提供一個包含你的應用程序IO狀態信息的復合結構體。當然,必須確定你為每個的I/O提供的是唯一的復合結構體。當I/O完成的時候,會返回一個指向結構體的指針。
TIP 4:I/O完成封包隊列的行為
IOCP中完成封包隊列的等待次序并不決定于Winsock2 I/O調用產生的順序。如果一個Winsock2的I/O調用返回了SUCCESS或者IO_PENDING,那么他保證當I/O操作完成后,完成封包會進入IOCP的等待隊列,而不管Socket句柄是否已經關閉。如果你關閉了socket句柄,那么將來調用WSASend,WSASendTo,WSARecv和WSARecvFrom會失敗并返回一個不同于SUCCES或者IO_PENDING的代碼,這時將不會產生一個完成封包。而在這種情況下,前一次使用GetQueuedCompletionStatus提交的I/O操作所得到的完成封包,會顯示一個失敗的信息。
如果你刪除了IOCP本身,那么不會有任何I/O請求發送給IOCP,因為IOCP的句柄已經不可用,盡管系統底層的IOCP核心結構并不會在所有已提交I/O請求完成之前被移除。
TIP5:IOCP的清除
很重要的一件事是使用復合I/O時候的IOCP清除:如果一個I/O操作尚未完成,那么千萬不要釋放該操作創建的復合結構體。HasOverlappedIoCompleted函數可以幫助你檢查一個I/O操作是否已經完成。
關閉服務一般有兩種情況,第一種你并不關心尚未結束的I/O操作的完成狀態,你只希望盡可能快的關閉他。第二種,你打算關閉服務,但是你需要獲知未結束I/O操作的完成狀態。
第一種情況你可以調用PostQueueCompletionStatus(N次,N等于你的工作線程數量)來提交一個特殊的完成封包,他通知所有的工作線程立即退出,關閉所有socket句柄和他們關聯的復合結構體,然后關閉完成端口(IOCP)。在關閉復合結構體之前使用HasOverlappedIOCompleted檢查他的完成狀態。如果一個socket關閉了,所有基于他的未結束的I/O操作會很快的完成。
在第二種情況,你可以延遲工作線程的退出來保證所有的完成封包可以被適當的出列。你可以首先關閉所有的socket句柄和IOCP??墒?,你需要維護一個未完成I/O的數字,以便你的線程可以知道可以安全退出的時間。盡管當隊列中有很多完成封包在等待的時候,活動的工作線程不能立即退出,但是在IOCP服務中使用全局I/O計數器并且使用臨界區保護他的代價并不會象你想象的那樣昂貴。

# re: 封裝了IOCP  回復  更多評論   

2009-01-31 20:42 by 85093103
看看iocp的清除。

# re: 封裝了IOCP  回復  更多評論   

2009-01-31 21:00 by 苦丁茶
因為我發現當大理recv后,就沒機會處理send的完成事件了。
如果在recv有同步或有復雜的邏輯,比如recv后需要send幾個,此時可能產生死鎖,以致永遠沒機會get到send的完成事件。
而如果IOCP本身就能將這兩個事件用兩個不同的GET分開,那業務邏輯就也好處理一些。

# re: 封裝了IOCP  回復  更多評論   

2009-04-12 15:30 by cbm
@苦丁茶
我也在寫iocp,對于你的評論,我認為非常正確,但是到現在為止,還沒有找到一個好的辦法處理send的完成事件。你找到了嗎
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            国自产拍偷拍福利精品免费一| 国产视频久久久久| 欧美激情在线播放| 久久婷婷亚洲| 亚洲第一黄色| 欧美成人一区二区三区| 亚洲电影免费观看高清完整版在线 | 亚洲国产影院| 亚洲人成精品久久久久| 亚洲私拍自拍| 国产精品你懂的| 麻豆精品视频在线观看| 欧美成人一区二区在线| 亚洲国产免费看| 亚洲视频在线观看三级| 久久国产精彩视频| 欧美精品一区在线播放| 国产精品一区久久久| 在线成人欧美| 亚洲视屏在线播放| 米奇777在线欧美播放| 99xxxx成人网| 久久综合福利| 国产日韩av高清| 日韩视频专区| 免费观看成人鲁鲁鲁鲁鲁视频| 艳妇臀荡乳欲伦亚洲一区| 亚洲女同在线| 亚洲第一精品夜夜躁人人爽| 亚洲视频观看| 欧美精品一区二区精品网| 国产一区二区视频在线观看| 日韩亚洲国产精品| 欧美成人精品在线| 欧美一区二区性| 欧美午夜视频网站| 亚洲国产女人aaa毛片在线| 欧美一区二区三区在线| 999亚洲国产精| 欧美国产精品人人做人人爱| 国产一区二区高清视频| 亚洲综合国产精品| 亚洲精品一区二区三区福利| 久久午夜电影| 在线不卡亚洲| 久久这里只有| 久久精品女人| 国产一区二区在线观看免费| 亚洲欧美国产视频| 一本大道久久a久久精品综合| 99国产精品久久| 嫩草国产精品入口| 亚洲黄色一区| 欧美黑人国产人伦爽爽爽| 欧美一级理论性理论a| 国产麻豆精品theporn| 亚洲永久免费av| 亚洲无亚洲人成网站77777 | 亚洲在线第一页| 欧美va亚洲va香蕉在线| 在线电影欧美日韩一区二区私密| 国产一区二区精品| 亚洲欧美亚洲| 亚洲伊人久久综合| 国产欧美视频一区二区| 久久福利影视| 久久国产黑丝| 国产日韩欧美在线播放| 欧美日韩天堂| 久久免费一区| 国产伦精品一区二区三区高清版 | 欧美日韩中文字幕精品| 欧美午夜精品| 99综合在线| 亚洲精品三级| 国产精品久久久久一区二区| 亚洲少妇一区| 亚洲欧美一区二区视频| 国模叶桐国产精品一区| 欧美成人a∨高清免费观看| 久久综合久久综合久久综合| 亚洲国产免费看| 日韩视频在线观看免费| 国产精品视频网址| 猛男gaygay欧美视频| 欧美精品一区二| 午夜在线精品偷拍| 欧美在线三级| 99国产精品一区| 欧美一级电影久久| 亚洲美女黄网| 欧美亚洲日本一区| 99精品免费网| 久久精品国产免费看久久精品| 欧美在线一二三区| 亚洲国产综合在线| 亚洲精品美女久久7777777| 欧美日韩精品系列| 久久精品人人做人人爽电影蜜月| 亚洲第一级黄色片| 欧美日韩在线第一页| 久久网站免费| 国产精品久久国产三级国电话系列 | 浪潮色综合久久天堂| 亚洲精品在线二区| 欧美在线免费观看亚洲| 日韩视频一区二区三区在线播放免费观看 | 亚洲乱码国产乱码精品精 | 国产女人18毛片水18精品| 久久综合色影院| 国产精品久久久一本精品| 欧美国产日韩亚洲一区| 国产日韩av高清| 一本色道久久综合一区| 亚洲高清色综合| 欧美一区二区三区精品| 久久久777| 国产精品99免费看| 美女成人午夜| 国产日本欧洲亚洲| 9人人澡人人爽人人精品| 国产精品自在线| 99香蕉国产精品偷在线观看| 激情一区二区| 亚洲欧美日韩在线不卡| 宅男精品视频| 欧美日本国产精品| 亚洲国产成人久久| 曰韩精品一区二区| 久久精品国产久精国产思思| 亚洲尤物精选| 国产精品jizz在线观看美国 | 欧美精品成人一区二区在线观看| 国产视频自拍一区| 99精品国产热久久91蜜凸| 91久久久在线| 久久综合伊人77777麻豆| 久久久久久亚洲综合影院红桃 | 99在线热播精品免费| 亚洲精品日本| 欧美激情一区| 99精品国产一区二区青青牛奶| 欧美久久视频| 91久久国产自产拍夜夜嗨| 最新国产成人在线观看 | 欧美中文字幕不卡| 欧美亚洲日本一区| 国产在线拍偷自揄拍精品| 欧美一级片在线播放| 美日韩精品视频免费看| 亚洲精品国产精品乱码不99| 免费高清在线视频一区·| 亚洲国产一区二区三区a毛片| 欧美日韩国产综合一区二区| 老司机午夜免费精品视频| 亚洲经典在线| 欧美日韩精品综合| 亚洲一区999| 久热精品视频在线| 一区二区三区黄色| 国产欧美日韩精品一区| 久久久久www| 亚洲精品一区二区网址| 小嫩嫩精品导航| 在线观看日韩国产| 欧美日韩免费观看一区二区三区| 免费观看亚洲视频大全| 极品少妇一区二区三区精品视频| 99国产精品| 久久精品一区二区三区不卡| 亚洲国产精品久久久久秋霞不卡| 在线一区亚洲| 久久精品日产第一区二区| 亚洲激情在线观看| 国产精品亚洲综合色区韩国| 久久久久久网站| 久久精品av麻豆的观看方式| 久久久久久免费| 亚洲免费观看高清完整版在线观看熊| 国产精品亚发布| 久久久天天操| 亚洲视频电影图片偷拍一区| 免费日韩av| 久久爱另类一区二区小说| 亚洲精品一区在线| 国内外成人免费激情在线视频网站 | 欧美久久九九| 欧美一级二级三级蜜桃| 一本久道久久综合狠狠爱| 免费观看不卡av| 久久精品在线观看| 亚洲一区二区免费| 亚洲精品裸体| 亚洲第一综合天堂另类专| 国产免费成人在线视频| 欧美日韩一二三四五区| 麻豆亚洲精品| 久久久综合网站| 欧美夜福利tv在线| 亚洲在线观看视频|