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

山寨:不是最好的,是最適合我們的!歡迎體驗山寨 中文版MSDN

Blog @ Blog

當華美的葉片落盡,生命的脈絡(luò)才歷歷可見。 -- 聶魯達

常用鏈接

統(tǒng)計

積分與排名

BBS

Blog

Web

最新評論

端口技術(shù) GetOverlappedResult [轉(zhuǎn)]

以一個文件傳輸服務(wù)端為例,在我的機器上它只起兩個線程就可以為很多個個客戶端同時提供文件下載服務(wù),程序的性能會隨機器內(nèi)CPU個數(shù)的增加而線性增長,我盡可能做到使它清晰易懂,雖然程序很小卻用到了NT 5的一些新特性,重疊IO,完成端口以及線程池,基于這種模型的服務(wù)端程序應(yīng)該是NT系統(tǒng)上性能最好的了.

首先.做為完成端口的基礎(chǔ),我們應(yīng)該理解重疊IO,這需要你已經(jīng)理解了內(nèi)核對象及操作系統(tǒng)的一些概念概念,什么是信號/非信號態(tài),什么是等待函數(shù),什么是成功等待的副作用,什么是線程掛起等,如果這些概令還沒有理解,你應(yīng)該先看一下Windows 核心編程中的相關(guān)內(nèi)容.如果已經(jīng)理解這些,那么重疊IO對你來說并不難.

你可以這樣認為重疊IO,現(xiàn)在你已經(jīng)進入一個服務(wù)器/客戶機環(huán)境,請不要混淆概念,這里的服務(wù)器是指操作系統(tǒng),而客戶機是指你的程序(它進行IO操作),是當你進行IO操作(send,recv,writefile,readfile….)時你發(fā)送一個IO請求給服務(wù)器(操作系統(tǒng)),由服務(wù)器來完成你需要的操作,然后你什么事都沒有了,當服務(wù)器完成IO請求時它會通知你,當然在這期間你可以做任何事,一個常用的技巧是在發(fā)送重疊IO請求后,程序在一個循環(huán)中一邊調(diào)用PeekMessage,TranslateMessage和DispatchMessage更新界面,同時調(diào)用 GetOverlappedResult等待服務(wù)器完成IO操作,更高效一點的做法是使用IO完成例程來處理服務(wù)器(操作系統(tǒng))返回的結(jié)果,但并不是每個支持重疊IO操作的函數(shù)都支持完成例程如TransmitFile函數(shù).

例1.一次重疊寫操作過程(GetOverlappedResult方法):
1.填寫一個OVERLAPPED結(jié)構(gòu)
2.進行一次寫操作,并指定重疊操作參數(shù)(上面的OVERLAPPED結(jié)構(gòu)變量的指針)
3.做其它事(如更新界面)
4.GetOverlappedResult取操作結(jié)果
5.如果IO請求沒有完成,并且沒有出錯則回到3
6.處理IO操作結(jié)果

例2.一次重疊寫操作過程(完成例程方法):
1.填寫一個OVERLAPPED結(jié)構(gòu)
2.進行一次寫操作,并指定重疊操作參數(shù)(上面的OVERLAPPED結(jié)構(gòu)變量的指針),并指定完成例程
3.做其它事(如更新界面)
4.當完成例程被調(diào)用說明IO操作已經(jīng)完成或出錯,現(xiàn)在可以對操作結(jié)果進行處理了

如果你已經(jīng)理解上面的概念,就已經(jīng)很接近IO完成端口了,當然這只是很常規(guī)的重疊操作它已經(jīng)非常高效,但如果再結(jié)合多線程對一個File或是Socket進行重疊IO操作就會非常復雜,通常程序員很難把握這種復雜度.完成端口可以說就是為了充分發(fā)揮多線程和重疊IO操作相結(jié)合的性能而設(shè)計的.很多人都說它復雜,其實如果你自己實現(xiàn)一個多線程的對一個File或是Socket進行重疊IO操作的程序(注意是多個線程對一個HANDLE或SOCKET進行重疊 IO操作,而不是啟一個線程對一個HANDLE進行重疊IO操作)就會發(fā)現(xiàn)完成端口實際上簡化了多線程里使用重疊IO的復雜度,并且性能更高,性能高在哪?下面進行說明.

我們可能寫過這樣的服務(wù)端程序:

例3.主程序:
1.監(jiān)聽一個端口
2.等待連接
3.當有連接來時
4.啟一個線程對這個客戶端進行處理
5.回到2

服務(wù)線程:
1.讀客戶端請求
2.如果客戶端不再有請求,執(zhí)行6
3.處理請求
4.返回操作結(jié)果
5.回到1
6.退出線程

這是一種最簡單的網(wǎng)絡(luò)服務(wù)器模型,我們把它優(yōu)化一下

例4.主程序:
1.開一個線程池,里面有機器能承受的最大線程數(shù)個線程,線程都處于掛起(suspend)狀態(tài)
1.監(jiān)聽一個端口
2.等待連接
3.當有連接來時
4.從線程池里Resume一個線程對這個客戶端進行處理
5.回到2

服務(wù)線程與例3模型里的相同,只是當線程處理完客戶端所有請求后,不是退出而是回到線程池,再次掛起讓出CPU時間,并等待為下一個客戶機服務(wù).當然在此期間線程會因為IO操作(服務(wù)線程的第1,5操作,也許還有其它阻塞操作)掛起自己,但不會回到線程池,也就是說它一次只能為一個客戶端服務(wù).

這可能是你能想到的最高效的服務(wù)端模型了吧!它與第一個服務(wù)端模型相比少了很多個用戶態(tài)到內(nèi)核態(tài)的CONTEXT Switch,反映也更加快速,也許你可能覺得這很微不足道,這說明你缺少對大規(guī)模高性能服務(wù)器程序(比如網(wǎng)游服務(wù)端)的認識,如果你的服務(wù)端程序要對幾千萬個客戶端進行服務(wù)呢?這也是微軟Windows NT開發(fā)組在NT 5以上的系統(tǒng)中添加線程池的原因.

思考一下什么樣的模型可以讓一個線程為多個客戶端服務(wù)呢!那就要跳出每來一個連接啟線程為其服務(wù)的固定思維模式,我們把線程服務(wù)的最小單元分割為單獨的讀或?qū)懖僮?注意是讀或?qū)懖皇亲x和寫),而不是一個客戶端從連接到斷開期間的所有讀寫操作.每個線程都使用重疊IO進行讀寫操作,投遞了讀寫請求后線程回到線程池,等待為其它客戶機服務(wù),當操作完成或出錯時再回來處理操作結(jié)果,然后再回到線程池.

看看這樣的服務(wù)器模型:
例5.主程序:
1.開一個線程池,里面有機器內(nèi)CPU個數(shù)兩倍的線程,線程都處于掛起(suspend)狀態(tài),它們在都等處理一次重疊IO操作的完成結(jié)果
1.監(jiān)聽一個端口
2.等待連接
3.當有連接來時
4.投遞一個重疊讀操作讀取命令
5.回到2

服務(wù)線程:
1.如果讀完成,則處理讀取的內(nèi)容(如HTTP GET命令),否則執(zhí)行3
2.投遞一個重疊寫操作(如返回HTTP GET命令需要的網(wǎng)頁)
3.如果是一個寫操作完成,可以再投遞一個重疊讀操作,讀取客戶機的下一個請求,或者是關(guān)閉連接(如HTTP協(xié)議里每發(fā)完一個網(wǎng)頁就斷開)
4.取得下一個重疊IO操作結(jié)果,如果IO操作沒有完成或沒有IO操作則回到線程池

假設(shè)這是一個WEB服務(wù)器程序,可以看到工作者線程是以讀或?qū)憺樽钚〉墓ぷ鲉卧\行的,在主程序里面進行了一次重疊讀操作

當讀操作完成時一個線程池中的一個工作者線程被激活取得了操作結(jié)果,處理GET或POST命令,然后發(fā)送一個網(wǎng)頁內(nèi)容,發(fā)送也是一個重疊操作,然后處理對其它客戶機的IO操作結(jié)果,如果沒有其它的東西需要處理時回到線程池等待.可以看到使用這種模型發(fā)送和接收可以是也可以不是一個線程.

當發(fā)送操作完成時,線程池中的一個工作者線程池激活,它關(guān)閉連接(HTTP協(xié)議),然后處理其它的IO操作結(jié)果,如果沒有其它的東西需要處理時回到線程池等待.

看看在這樣的模型中一個線程怎么為多個客戶端服務(wù),同樣是模擬一個WEB服務(wù)器例子:

假如現(xiàn)在系統(tǒng)中有兩個線程,ThreadA,ThreadB它們在都等處理一次重疊IO操作的完成結(jié)果

當一個客戶機ClientA連接來時主程序投遞一個重疊讀操作,然后等待下一個客戶機連接,當讀操作完成時ThreadA被激活,它收到一個HTTP GET命令,然后ThreadA使用重疊寫操作發(fā)送一個網(wǎng)頁給ClientA,然后立即回到線程池等待處理下一個IO操作結(jié)果,這時發(fā)送操作還沒有完成, 又有一個客戶機ClientB連接來,主程序再投遞一個重疊讀操作,當讀操作完成時ThreadA(當然也可能是ThreadB)再次被激活,它重復同樣步驟,收到一個GET命令,使用重疊寫操作發(fā)送一個網(wǎng)頁給ClientB,這次它沒有來得及回到線程池時,又有一個連接ClientC連入,主程序再投遞一個重疊讀操作,讀操作完成時ThreadB被激活(因為ThreadA還沒有回到線程池)它收到一個HTTP GET命令,然后ThreadB使用重疊寫操作發(fā)送一個網(wǎng)頁給ClientC,然后ThreadB回到線程池,這時ThreadA也回到了線程池.

可以想象現(xiàn)在有三個掛起的發(fā)送操作分別是ThreadA發(fā)送給ClientA和ClientB的網(wǎng)頁,以及ThreadB發(fā)送給ClientC的網(wǎng)頁,它們由操作系統(tǒng)內(nèi)核來處理.ThreadA和ThreadB現(xiàn)在已經(jīng)回到線程池,可以繼續(xù)為其它任何客戶端服務(wù).

當對ClientA的重疊寫操作已經(jīng)完成,ThreadA(也可以是ThreadB)又被激活,它關(guān)閉與ClientA連接,但還沒有回到線程池,與此同時發(fā)送給ClientB的重疊寫操作也完成,ThreadB被激活(因為ThreadA還沒有回到線程池)它關(guān)閉與ClientB的連接,然后回到線程池, 這時ClientC的寫操作也完成,ThreadB再次被激活(因為ThreadA還是沒有回到線程池),它再關(guān)閉與ClientC的連接,這時 ThreadA回到線程池,ThreadB也回到線程池.這時對三個客戶端的服務(wù)全部完成.可以看到在整個服務(wù)過程中,”建立連接”,”讀數(shù)據(jù)”,”寫數(shù)據(jù)”和”關(guān)閉連接”等操作是邏輯上連續(xù)而實際上分開的.

到現(xiàn)在為止兩個線程處理了三次讀操作和三次寫操作,在這些讀寫操作過程中所出現(xiàn)的狀態(tài)機(state machine)是比較復雜的,我們模擬的是經(jīng)過我簡化過的,實際上的狀態(tài)要比這個還要復雜很多,然而這樣的服務(wù)端模型在客戶端請求越多時與前兩個模型相比的性能越高.而使用完成端口我們可以很容易實現(xiàn)這樣的服務(wù)器模型.

微軟的IIS WEB服務(wù)器就是使用這樣的服務(wù)端模型,很多人說什么阿帕奇服務(wù)器比IIS的性能好什么什么的我表示懷疑,除非阿帕奇服務(wù)器可以將線程分割成,為更小的單元服務(wù),我覺得不太可能!這種完成端口模型已經(jīng)將單個讀或?qū)懖僮髯鳛樽钚〉姆?wù)單元,我覺得在相同機器配置的情況下IIS的性能要遠遠高于其它WEB服務(wù)器,這也是從實現(xiàn)機理上來分析的,如果出現(xiàn)性能上的差別可能是在不同的操作系統(tǒng)上,也許Linux的內(nèi)核比Windows的要好,有人真的研究過嗎?還是大家一起在炒作啊.

對于狀態(tài)機概念,在很多方面都用到,TCPIP中有,編譯原理中有,OpengGL中有等等,我的離散數(shù)學不好 (我是會計專業(yè)不學這個),不過還是搞懂了些,我想如果你多花些時間看,還是可以搞懂的.最后是一個簡單的文件傳輸服務(wù)器程序代碼,只用了兩個線程(我的機器里只有一塊CPU)就可以服務(wù)多個客戶端.我調(diào)試時用它同時為6個nc客戶端提供文件下載服務(wù)都沒有問題,當然更多也不會有問題,只是略為使用了一下 NT 5的線程池和完成端口技術(shù)就可以有這樣高的性能,更不用說IIS的性能咯!

希望大家不要陷在這個程序的框架中,Ctrl+C, Ctrl+V沒有什么意義,要理解它的實質(zhì).程序使用Visual C++ 6.0 SP5+2003 Platform SDK編譯通過,在Windows XP Professional下調(diào)試運行通過.程序運行的最低要求是Windows 2000操作系統(tǒng).

/********************************************************************
created:??? 2005/12/24
created:??? 24:12:2005?? 20:25
modified:??? 2005/12/24
filename:???? d:\vcwork\iocomp\iocomp.cpp
file path:??? d:\vcwork\iocomp
file base:??? iocomp
file ext:??? cpp
author:??????? kruglinski(kruglinski_at_gmail_dot_com)

purpose:??? 利用完成端口技術(shù)實現(xiàn)的高性能文件下載服務(wù)程序
********************************************************************
*/


#define _WIN32_WINNT??? 0×0500

#include 
<cstdlib>
#include 
<clocale>
#include 
<ctime>
#include 
<iostream>//一使用輸入輸出流程序頓時增大70K
#include <vector>
#include 
<algorithm>
#include 
<winsock2.h>
#include 
<mswsock.h>

using namespace std;

#pragma comment(lib,”ws2_32.lib”)
#pragma comment(lib,”mswsock.lib”)

const int MAX_BUFFER_SIZE=1024;
const int PRE_SEND_SIZE=1024;
const int QUIT_TIME_OUT=3000;
const int PRE_DOT_TIMER=QUIT_TIME_OUT/80;

typedef 
enum{IoTransFile,IoSend,IoRecv,IoQuit} IO_TYPE;

typedef 
struct
{
SOCKET hSocket;
SOCKADDR_IN ClientAddr;
}
PRE_SOCKET_DATA,*PPRE_SOCKET_DATA;

typedef 
struct
{
OVERLAPPED
??? oa;
WSABUF
??????? DataBuf;
char??????? Buffer[MAX_BUFFER_SIZE];
IO_TYPE
??????? IoType;
}
PRE_IO_DATA,*PPRE_IO_DATA;

typedef vector
<PPRE_SOCKET_DATA>??? SocketDataVector;
typedef vector
<PPRE_IO_DATA>??????? IoDataVector;

SocketDataVector
??? gSockDataVec;
IoDataVector
??????? gIoDataVec;

CRITICAL_SECTION
??? csProtection;

char* TimeNow(void)
{
time_t t
=time(NULL);
tm 
*localtm=localtime(&t);
static char timemsg[512]={0};

strftime(timemsg,
512,”%Z: %%%X,%Y”,localtm);
return timemsg;
}


BOOL TransFile(PPRE_IO_DATA pIoData,PPRE_SOCKET_DATA pSocketData,DWORD dwNameLen)
{
//這一句是為nc做的,你可以修改它
pIoData->Buffer[dwNameLen-1]=”;

HANDLE hFile
=CreateFile(pIoData->Buffer,GENERIC_READ,0,NULL,OPEN_EXISTING,0,NULL);
BOOL bRet
=FALSE;

if(hFile!=INVALID_HANDLE_VALUE)
{
cout
<<”Transmit File “<<pIoData->Buffer<<” to client”<<endl;
pIoData
->IoType=IoTransFile;
memset(
&pIoData->oa,0,sizeof(OVERLAPPED));
*reinterpret_cast<HANDLE*>(pIoData->Buffer)=hFile;
TransmitFile(pSocketData
->hSocket,hFile,GetFileSize(hFile,NULL),PRE_SEND_SIZE,reinterpret_cast<LPOVERLAPPED>(pIoData),NULL,TF_USE_SYSTEM_THREAD);
bRet
=WSAGetLastError()==WSA_IO_PENDING;
}

else
cout
<<”Transmit File “<<”Error:”<<GetLastError()<<endl;

return bRet;
}


DWORD WINAPI ThreadProc(LPVOID IocpHandle)
{
DWORD dwRecv
=0;
DWORD dwFlags
=0;

HANDLE hIocp
=reinterpret_cast<HANDLE>(IocpHandle);
DWORD dwTransCount
=0;
PPRE_IO_DATA pPreIoData
=NULL;
PPRE_SOCKET_DATA pPreHandleData
=NULL;

while(TRUE)
{
if(GetQueuedCompletionStatus(hIocp,&dwTransCount,
reinterpret_cast
<LPDWORD>(&pPreHandleData),
reinterpret_cast
<LPOVERLAPPED*>(&pPreIoData),INFINITE))
{
if(0==dwTransCount&&IoQuit!=pPreIoData->IoType)
{
cout
<<”Client:”
<<inet_ntoa(pPreHandleData->ClientAddr.sin_addr)
<<”:”<<ntohs(pPreHandleData->ClientAddr.sin_port)
<<” is closed”<<endl;

closesocket(pPreHandleData
->hSocket);

EnterCriticalSection(
&csProtection);
IoDataVector::iterator itrIoDelete
=find(gIoDataVec.begin(),gIoDataVec.end(),pPreIoData);
SocketDataVector::iterator itrSockDelete
=find(gSockDataVec.begin(),gSockDataVec.end(),pPreHandleData);
delete 
*itrIoDelete;
delete 
*itrSockDelete;
gIoDataVec.erase(itrIoDelete);
gSockDataVec.erase(itrSockDelete);
LeaveCriticalSection(
&csProtection);

continue;
}


switch(pPreIoData->IoType){
case IoTransFile:
cout
<<”Client:”
<<inet_ntoa(pPreHandleData->ClientAddr.sin_addr)
<<”:”<<ntohs(pPreHandleData->ClientAddr.sin_port)
<<” Transmit finished”<<endl;
CloseHandle(
*reinterpret_cast<HANDLE*>(pPreIoData->Buffer));
goto LRERECV;

case IoSend:
cout
<<”Client:”
<<inet_ntoa(pPreHandleData->ClientAddr.sin_addr)
<<”:”<<ntohs(pPreHandleData->ClientAddr.sin_port)
<<” Send finished”<<endl;

LRERECV:
pPreIoData
->IoType=IoRecv;
pPreIoData
->DataBuf.len=MAX_BUFFER_SIZE;
memset(
&pPreIoData->oa,0,sizeof(OVERLAPPED));

WSARecv(pPreHandleData
->hSocket,&pPreIoData->DataBuf,1,
&dwRecv,&dwFlags,
reinterpret_cast
<LPWSAOVERLAPPED>(pPreIoData),NULL);

break;

case IoRecv:
cout
<<”Client:”
<<inet_ntoa(pPreHandleData->ClientAddr.sin_addr)
<<”:”<<ntohs(pPreHandleData->ClientAddr.sin_port)
<<” recv finished”<<endl;
pPreIoData
->IoType=IoSend;

if(!TransFile(pPreIoData,pPreHandleData,dwTransCount))
{
memset(
&pPreIoData->oa,0,sizeof(OVERLAPPED));
strcpy(pPreIoData
->DataBuf.buf,”File transmit error!\r\n”);
pPreIoData
->DataBuf.len=strlen(pPreIoData->DataBuf.buf);

WSASend(pPreHandleData
->hSocket,&pPreIoData->DataBuf,1,
&dwRecv,dwFlags,
reinterpret_cast
<LPWSAOVERLAPPED>(pPreIoData),NULL);
}

break;

case IoQuit:
goto LQUIT;

default:
;
}

}

}


LQUIT:
return 0;
}


HANDLE hIocp
=NULL;
SOCKET hListen
=NULL;

BOOL WINAPI ShutdownHandler(DWORD dwCtrlType)
{
PRE_SOCKET_DATA PreSockData
={0};
PRE_IO_DATA PreIoData
={0};

PreIoData.IoType
=IoQuit;

if(hIocp)
{
PostQueuedCompletionStatus(hIocp,
1,
reinterpret_cast
<ULONG_PTR>(&PreSockData),
reinterpret_cast
<LPOVERLAPPED>(&PreIoData));

cout
<<”Shutdown at “<<TimeNow()<<endl<<”wait for a moment please”<<endl;

//讓出CPU時間,讓線程退出
for(int t=0;t<80;t+=1)
{
Sleep(PRE_DOT_TIMER);
cout
<<”.”;
}


CloseHandle(hIocp);
}


int i=0;

for(;i<gSockDataVec.size();i++)
{
PPRE_SOCKET_DATA pSockData
=gSockDataVec[i];
closesocket(pSockData
->hSocket);
delete pSockData;
}


for(i=0;i<gIoDataVec.size();i++)
{
PPRE_IO_DATA pIoData
=gIoDataVec[i];
delete pIoData;
}


DeleteCriticalSection(
&csProtection);
if(hListen)
closesocket(hListen);

WSACleanup();
exit(
0);
return TRUE;
}


LONG WINAPI MyExceptionFilter(
struct _EXCEPTION_POINTERS *ExceptionInfo)
{
ShutdownHandler(
0);
return EXCEPTION_EXECUTE_HANDLER;
}


u_short DefPort
=8182;

int main(int argc,char **argv)
{
if(argc==2)
DefPort
=atoi(argv[1]);

InitializeCriticalSection(
&csProtection);
SetUnhandledExceptionFilter(MyExceptionFilter);
SetConsoleCtrlHandler(ShutdownHandler,TRUE);

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

WSADATA data
={0};
WSAStartup(
0×0202,&data);

hListen
=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if(INVALID_SOCKET==hListen)
{
ShutdownHandler(
0);
}


SOCKADDR_IN addr
={0};
addr.sin_family
=AF_INET;
addr.sin_port
=htons(DefPort);

if(bind(hListen,reinterpret_cast<PSOCKADDR>(&addr),
sizeof(addr))==SOCKET_ERROR)
{
ShutdownHandler(
0);
}


if(listen(hListen,256)==SOCKET_ERROR)
ShutdownHandler(
0);

SYSTEM_INFO si
={0};
GetSystemInfo(
&si);
si.dwNumberOfProcessors
<<=1;

for(int i=0;i<si.dwNumberOfProcessors;i++)
{

QueueUserWorkItem(ThreadProc,hIocp,WT_EXECUTELONGFUNCTION);
}


cout
<<”Startup at “<<TimeNow()<<endl
<<”work on port “<<DefPort<<endl
<<”press CTRL+C to shutdown”<<endl<<endl<<endl;

while(TRUE)
{
int namelen=sizeof(addr);
memset(
&addr,0,sizeof(addr));
SOCKET hAccept
=accept(hListen,reinterpret_cast<PSOCKADDR>(&addr),&namelen);

if(hAccept!=INVALID_SOCKET)
{
cout
<<”accept a client:”<<inet_ntoa(addr.sin_addr)<<”:”<<ntohs(addr.sin_port)<<endl;

PPRE_SOCKET_DATA pPreHandleData
=new PRE_SOCKET_DATA;
pPreHandleData
->hSocket=hAccept;
memcpy(
&pPreHandleData->ClientAddr,&addr,sizeof(addr));

CreateIoCompletionPort(reinterpret_cast
<HANDLE>(hAccept),hIocp,reinterpret_cast<DWORD>(pPreHandleData),0);

PPRE_IO_DATA pPreIoData
=new(nothrow) PRE_IO_DATA;

if(pPreIoData)
{
EnterCriticalSection(
&csProtection);
gSockDataVec.push_back(pPreHandleData);
gIoDataVec.push_back(pPreIoData);
LeaveCriticalSection(
&csProtection);

memset(pPreIoData,
0,sizeof(PRE_IO_DATA));
pPreIoData
->IoType=IoRecv;
pPreIoData
->DataBuf.len=MAX_BUFFER_SIZE;
pPreIoData
->DataBuf.buf=pPreIoData->Buffer;
DWORD dwRecv
=0;
DWORD dwFlags
=0;
WSARecv(hAccept,
&pPreIoData->DataBuf,1,&dwRecv,&dwFlags,reinterpret_cast<WSAOVERLAPPED*>(pPreIoData),NULL);
}

else
{
delete pPreHandleData;
closesocket(hAccept);
}

}

}


return 0;
}

posted on 2008-01-07 16:47 isabc 閱讀(5507) 評論(0)  編輯 收藏 引用 所屬分類: 串口通信

廣告信息(免費廣告聯(lián)系)

中文版MSDN:
歡迎體驗

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            欧美吻胸吃奶大尺度电影| 亚洲女女女同性video| 日韩一区二区精品葵司在线| 欧美在线观看视频在线 | 噜噜噜久久亚洲精品国产品小说| 亚洲午夜一区二区三区| 中文精品视频| 亚洲欧美偷拍卡通变态| 久久激情五月激情| 欧美成人高清| 欧美色综合网| 国产午夜精品在线观看| 伊人精品在线| 一区二区三区精密机械公司| 亚洲欧美制服另类日韩| 久久久久久夜| 亚洲精品系列| 久久精品九九| 欧美精品在线观看播放| 国产毛片一区二区| 亚洲精品美女久久7777777| 宅男噜噜噜66一区二区66| 亚洲欧美第一页| 久久久亚洲人| 一本色道久久综合亚洲精品不| 亚洲欧美国产精品桃花| 玖玖玖国产精品| 国产精品任我爽爆在线播放 | 久久欧美肥婆一二区| 欧美黄色日本| 亚洲欧美日韩直播| 欧美高清影院| 国产一二精品视频| 一二三区精品福利视频| 久久先锋影音| 亚洲一区二区欧美日韩| 欧美a级理论片| 国产在线精品自拍| 亚洲一区在线免费观看| 欧美 日韩 国产精品免费观看| 一区二区免费在线视频| 免费不卡视频| 国产中文一区二区三区| 亚洲影院色在线观看免费| 亚洲电影视频在线| 欧美在线亚洲在线| 国产精品亚洲综合一区在线观看| 亚洲片在线观看| 美女图片一区二区| 欧美一区二区三区啪啪 | 一区二区亚洲精品| 欧美一级午夜免费电影| 99re亚洲国产精品| 欧美国产日韩精品| 亚洲国产合集| 亚洲视频axxx| 一本久久综合| 欧美日韩高清在线| 亚洲高清一区二| 免费日韩av片| 老司机成人网| 亚洲日本va午夜在线影院| 欧美高清不卡在线| 欧美+亚洲+精品+三区| 亚洲欧洲综合| 亚洲精品日韩欧美| 欧美日韩一区二区视频在线观看| 亚洲精品日韩激情在线电影| 亚洲国产欧美在线| 欧美激情导航| 日韩视频精品在线| 亚洲美女在线国产| 欧美午夜精品伦理| 羞羞答答国产精品www一本| 亚洲一区二区精品| 国产自产女人91一区在线观看| 久久久久九九视频| 久久久久国色av免费观看性色| 国内精品亚洲| 亚洲国产精品999| 欧美日韩精品一区| 欧美亚洲一区在线| 久久久久久97三级| 一本大道久久a久久精二百| 亚洲另类在线视频| 国产精品一区二区久久| 另类亚洲自拍| 欧美精品一区二| 欧美亚洲视频| 久久综合给合久久狠狠色| 日韩一级不卡| 亚洲欧美另类在线| 亚洲国产精品成人综合色在线婷婷 | 亚洲一区网站| 久久精品视频网| 亚洲三级毛片| 亚洲女同精品视频| 亚洲三级免费电影| 欧美日韩久久不卡| 亚洲美女在线一区| 欧美成人久久| 国产欧美91| 一区二区激情视频| 亚洲一区二区少妇| 久久九九电影| 久久婷婷国产综合尤物精品 | 久久久综合视频| 久久av一区二区三区| 欧美日韩精品在线| 久久久久在线观看| 欧美日韩999| 久久影音先锋| 欧美午夜视频一区二区| 久久久久久亚洲综合影院红桃| 欧美精品久久一区| 久久综合九色综合久99| 欧美日韩成人综合| 欧美福利网址| 亚洲国产精品黑人久久久| 亚洲欧美日韩一区二区在线 | 国产专区一区| 亚洲午夜精品在线| 亚洲美女黄网| 免费看成人av| 老色鬼久久亚洲一区二区 | 最新国产成人av网站网址麻豆| 欧美亚洲综合网| 亚洲愉拍自拍另类高清精品| 久热精品视频在线| 久久久噜噜噜| 国产日韩在线一区二区三区| 中文av一区特黄| 亚洲小说欧美另类婷婷| 欧美理论大片| 亚洲伦理一区| 亚洲一区日韩在线| 国产精品久在线观看| 日韩网站在线看片你懂的| 日韩亚洲欧美成人一区| 欧美日韩成人激情| 亚洲最新视频在线播放| 99成人精品| 欧美午夜寂寞影院| 亚洲香蕉网站| 久久国产精品网站| 黄色成人免费观看| 猛男gaygay欧美视频| 亚洲福利视频三区| 亚洲精品免费在线| 欧美日韩国产精品成人| 99视频一区| 久久精品女人天堂| 精品91免费| 欧美激情影音先锋| 中文无字幕一区二区三区| 欧美在线一区二区| 在线播放中文字幕一区| 免费观看久久久4p| 99re66热这里只有精品4| 午夜视频在线观看一区二区三区| 国产欧美一区二区三区国产幕精品| 香蕉久久夜色| 欧美韩日高清| 亚洲天堂黄色| 国产色综合网| 欧美成人精品高清在线播放| av不卡在线看| 久久中文字幕一区二区三区| 亚洲国产欧美不卡在线观看| 欧美影视一区| 午夜精品久久久久久久男人的天堂| 在线视频一区观看| 午夜久久资源| 久久久久久午夜| 亚洲人精品午夜| 欧美高清视频一区二区| 亚洲图片在区色| 亚洲婷婷综合久久一本伊一区| 久久麻豆一区二区| 亚洲国产成人av| 午夜免费在线观看精品视频| **欧美日韩vr在线| 欧美日韩在线不卡| 久久久久久久久久久久久女国产乱| 亚洲国产精品成人精品| 亚洲曰本av电影| 亚洲第一在线综合在线| 欧美日韩中文字幕在线视频| 久久精品在线| 亚洲午夜久久久久久尤物 | 欧美成人精品| 欧美一区二区高清在线观看| 亚洲精品欧美| 狠狠色综合网| 国产精品入口66mio| 欧美激情在线狂野欧美精品| 久久精品观看| 亚洲综合视频1区| 亚洲最新在线视频| 亚洲美女中文字幕|