日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

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

编程问答

重叠IO模型-异步IO

發布時間:2025/3/20 编程问答 15 豆豆
生活随笔 收集整理的這篇文章主要介紹了 重叠IO模型-异步IO 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

重疊IO模型-異步IO???

http://laiba.tianya.cn/laiba/CommMsgs?cmm=959&tid=2701316824681802728

說到重疊模型首先還是提一下異步IO比較好,因為從本質上講,重疊模型也是一種異步IO模型。

我們知道,相對于計算機執行的其他操作而言,設備IO(文件、管道、套接字等)是比較慢的。于是在多線程結構中就考慮到采用異步的方式進行設備讀寫操作,即我們告訴系統對設備的讀寫數據,而同時應用程序的其他代碼繼續執行,直到獲取設備操作完畢的系統通知。

在進行異步IO時,我們先向系統發出IO請求,操作系統隊列化各種IO請求,并在內部完成操作,當系統在處理IO請求時,我們的線程可以返回繼續執行,當操作系統處理完IO請求之后,通知我們數據操作(發送、接收、出錯)完畢。

Windows提供了四種異步IO技術,機制幾乎時相同的,區別在于通知結果的方式不同:

1、使一個設備內核對象變為有信號

Windows將設備句柄看作可同步的對象,即它可以處于有信號或處于無信號狀態,當創建設備句柄、以異步的方式發送IO請求時,該句柄處于無信號狀態,當異步IO完成之后,該句柄受信,通過WaitForSingleobject或WatiForMultipleObjects函數可以判斷設備操作合適完成。該技術只能用于一個設備只發送一個IO請求,否則,若一個設備對應多個操作,當句柄受信時無法判斷是該設備的那個操作完成。

2、使一個事件內核對象變為有信號

針對每個I/O操作綁定一個內核事件對象,并將等待事件等待函數等待該事件的受信,當I/O操作完成后系統使得與該操作綁定的事件受信,從而判斷那個操作完成。該技術解決了使一個設備內核對象變為有信號技術中一個設備只能對應一個操作的不足。

3、警告I/O

在該技術中,當發出設備IO請求時,同時要求我們傳遞一個被稱為完成例程的回調函數,當IO請求完成時調用該回調函數完成我們需要處理的工作。該技術允許單個設備同時進行多個I/O請求。

4、完成端口

完成端口技術多用于處理大規模的請求,通過內在的進程池技術可以達到很高的性能,此時暫不做深入討論,若預知后事如何,請自己看,或等下回完成端口部分分解。

好,至此,刀磨的差不多了,估計也飄了~~~~,干正事了。

重疊IO模型-網絡編程中的重疊IO模型理論 ??

在編程中可以有兩種方法管理I/O請求:

1、事件對象通知(eventobjectnotification)—對應上面的2

2、完成例程(completionroutines)——對應上面的3

這里只討論第一種情況,具體思路就是正對每個套接字的每個操作綁定一個事件,然后將所有的事件組成事件數據,運用事件等待函數等待事件的發生,并根據事件與操作的對應關系對與之對應的操作進行處理。

下面說一下實際編程中所用到的數據結構及函數。

1、WSAOVERLAPPED結構

這個結構自然是重疊模型里的核心,用于綁定套接字、操作以及操作對應的事件。

typedefstruct_WSAOVERLAPPED{

DWORDInternal;

DWORDInternalHigh;

DWORDOffset;//文件操作中想要開始的低偏移量,網絡中不用

DWORDOffsetHigh;//文件操作中想要開始的高偏移量,網絡中不用

WSAEVENThEvent;//網絡編程中唯一需要關注的參數,用來關聯WSAEvent對象

}WSAOVERLAPPED,*LPWSAOVERLAPPED;

2.WSARecv系列函數

在重疊模型中,發送接收等函數均由WSASend、WSARecv、WSASendTo、WSARecvFrom等函數代替,通過該函數將I/O操作與WSAOVERLAPPED結構綁定起來,也既是與一個特定的事件綁定在一起,當系統完成操作之后與該操作綁定的事件受信。

intWSARecv(

SOCKETs,//當然是投遞這個操作的套接字

LPWSABUFlpBuffers,//接收緩沖區,是WSABUF結構構成的數組

DWORDdwBufferCount,//數組中WSABUF結構的數量

LPDWORDlpNumberOfBytesRecvd,//如果接收操作立即完成,返回函數調用所接收到的字節數

LPDWORDlpFlags,//說來話長了,我們這里設置為0即可

LPWSAOVERLAPPEDlpOverlapped,//“綁定”的重疊結構

LPWSAOVERLAPPED_COMPLETION_ROUTINElpCompletionRoutine);//完成例程中將會用到的參數,我們這里設置為NULL

返回值:

WSA_IO_PENDING:最常見的返回值,這是說明我們的WSARecv操作成功了,但是I/O操作還沒有完成,所以我們就需要綁定一個事件來通知我們操作何時完成

3、WSAWaitForMultipleEvents函數

該函數類似于線程中常用的WaitForMultipleObjects函數,都是在等待事件的觸發。我們將WSARecv等操作上綁定的LPWSAOVERLAPPED數據結構中的事件組稱事件數據,在該函數上等待。

DWORDWSAWaitForMultipleEvents(

DWORDcEvents,//等候事件的總數量

constWSAEVENT*lphEvents,//事件數組的指針

BOOLfWaitAll,//當設置為TRUE,事件數組中所有事件被傳信的時候函數才會返回

//FALSE則任何一個事件被傳信函數都要返回,此時設為FALSE

DWORDdwTimeout,//超時時間,如果超時,函數會返回WSA_WAIT_TIMEOUT

//如果設置為0,函數會立即返回

BOOLfAlertable);//在完成例程中會用到這個參數,這里我們先設置為FALSE

返回值:

WSA_WAIT_TIMEOUT:最常見的返回值,等待超時,我們需要做的就是繼續Wait

WSA_WAIT_FAILED:出現了錯誤,請檢查cEvents和lphEvents兩個參數是否有效

如果事件數組中有某一個事件受信了,函數會返回這個事件的索引值,但是這個索引值需要減去預定義值WSA_WAIT_EVENT_0才是這個事件在事件數組中的位置。

注:WSAWaitForMultipleEvents函數只能支持由WSA_MAXIMUM_WAIT_EVENTS對象定義的一個最大值64,就是說WSAWaitForMultipleEvents只能等待64個事件,如果想同時等待多于64個事件,就要創建額外的工作者線程,就需要通過線程池管理了。

4、WSAGetOverlappedResult函數

我們利用該函數來查詢重疊操作的結果,定義如下:

BOOLWSAGetOverlappedResult(

SOCKETs,//SOCKET,需要操作的套接字

LPWSAOVERLAPPEDlpOverlapped,//我們想要查詢結果的那個重疊結構的指針

LPDWORDlpcbTransfer,//本次重疊操作的實際接收(或發送)的字節數

BOOLfWait,//設置為TRUE,除非重疊操作完成,否則函數不會返回

//設置FALSE,而且操作仍處于掛起狀態,那么函數就會返回FALSE

//此處采用的是設備內核對象受信方式,等待套接字受信。

LPDWORDlpdwFlags);//指向DWORD的指針,負責接收結果標志

注:如果WSAGetOverlappedResult完成以后,第三個參數返回是0,則說明通信對方已經關閉連接,我們這邊的SOCKET,Event之類的也就可以關閉了。

重疊IO模型-編程步驟 ??

1、創建一個套接字,開始在指定的端口上監聽連接請求。

2、接收一個入站的連接請求。

3、為接受的套接字創建新的WSAOVERLAPPED結構,并分配事件對象句柄。

4、以WSAOVERLAPPED結構為參數,在套接字上投遞WSARecv調用。

5、將所有接受套接字的事件組建事件數組,并調用WSAWaitForMultipleEvents函數,等待與重疊調用關聯在一起的事件受信。

6、使用WSAGetOverlappedResult函數,判斷重疊調用的返回狀態。

7、重新組建事件數組。

8、在套接字上重投遞WSARecv請求。

9、重復5~8。

例子:初步封裝了OverLapped類

/*SockObject*/

#include

classSockObject

{

public:

SOCKETm_sock;

intm_operatNum;

public:

SockObject(void);

SockObject(SOCKETmySock);

SockObject(SockObject&mySockObject);

~SockObject(void);

};

SockObject::SockObject(SOCKETmySock)

{

m_sock=mySock;

m_operatNum=0;

}

SockObject::SockObject(SockObject&mySockObject)

{

m_sock=mySockObject.m_sock;

m_operatNum=mySockObject.m_operatNum;

}

/******************************************************************************

*數據結構名稱:OverObject

*功能:記錄一個套接字的一個操作、一個事件和一個重疊I/O的關聯

*****************************************************************************/

classOverObject

{

public:

SOCKETm_sock;/*綁定的套接字*/

OVERLAPPEDm_overlapped;/*綁定的重疊I/O*/

char*m_buf;/*用于存放數據的緩沖區*/

intm_len;/*緩沖區的長度*/

intm_operation;/*套接字針對的操作*/

public:

booloperator==(constOverObject&myOverObject)const;

public:

OverObject(void);

OverObject(constOverObject&myOverObject);

OverObject(SOCKETmySock,intmyLen);

~OverObject(void);

};

/*定義指向重疊對象的指針類型*/

typedefOverObject*PtrOverObject;

OverObject::~OverObject(void)

{

deletem_buf;

}

/********************************************************************************

*函數介紹:本函數是OverObject類的復制構造函數。

*********************************************************************************/

OverObject::OverObject(constOverObject&myOverObject)

{

m_sock=myOverObject.m_sock;

m_overlapped=myOverObject.m_overlapped;

m_buf=newchar[myOverObject.m_len];

strcpy(m_buf,myOverObject.m_buf);

m_len=myOverObject.m_len;

m_operation=myOverObject.m_operation;

}

/********************************************************************************

*函數介紹:本函數是OverObject類帶參數的構造函數。

*********************************************************************************/

OverObject::OverObject(SOCKETmySock,intmyLen)

{

m_sock=mySock;

m_buf=newchar[myLen];

m_len=myLen;

m_overlapped.hEvent=::WSACreateEvent();

}

/********************************************************************************

*函數介紹:本函數是OverObject類的==運算符重載函數

*********************************************************************************/

boolOverObject::operator==(constOverObject&myOverObject)const

{

if(this->m_sock==myOverObject.m_sock&&this->m_operation==myOverObject.m_operation&&this->m_len==myOverObject.m_len&&!strcmp(this->m_buf,myOverObject.m_buf))

{

coutoverObjects;/*需要維護的所有重疊I/O*/

vectoreventArray;/*所有重疊I/O所對應的事件組成的數組,作為等待函數的參數*/

vectorsockArray;/*需要維護的所有套接字,當操作為零時關閉套接字*/

public:

list::iteratorGetOverObject(SOCKETmySock,intmyLen);

voidFreeOverObject(list::iteratormyPtrOverObject);

list::iteratorOverlapped::FindOverObject(HANDLEmyEvent);

voidRebuildEventArray();

voidCreateAcceptEvent();

voidSetAcceptEvent();

voidResetAcceptEvent();

boolIsAcceptEvent(intindex);

boolPostRecv(list::iteratormyPtrOverObject);

boolPostSend(list::iteratormyPtrOverObject);

boolPostAccept(list::iteratormyPtrOverObject);

Overlapped(void);

~Overlapped(void);

voidInitSocket();

};

/********************************************************************************

*函數介紹:創建重疊對象的類對象,并插入重疊對象鏈表中。

*********************************************************************************/

list::iteratorOverlapped::GetOverObject(SOCKETmySock,intmyLen)

{

OverObjectlocalOverObject(mySock,myLen);

overObjects.push_back(localOverObject);

eventArray.push_back(localOverObject.m_overlapped.hEvent);

list::iteratorret=overObjects.end();

ret--;

returnret;

}

/********************************************************************************

*函數介紹:釋放重疊對象鏈表中指定的重疊對象。

*********************************************************************************/

voidOverlapped::FreeOverObject(list::iteratormyPtrOverObject)

{

overObjects.erase(myPtrOverObject);

}

/********************************************************************************

*函數介紹:從重疊對象列表中查找指定事件所對應的重疊對象。

*********************************************************************************/

list::iteratorOverlapped::FindOverObject(HANDLEmyEvent)

{

list::iteratorlocalIerator;

for(localIerator=overObjects.begin();localIerator!=overObjects.end();localIerator++)

{

if(localIerator->m_overlapped.hEvent==myEvent)

{

break;

}

}

returnlocalIerator;

}

/********************************************************************************

*函數介紹:遍歷重疊對象列表,重建重疊對象列表所對應的事件數組。

*********************************************************************************/

voidOverlapped::RebuildEventArray()

{

eventArray.clear();

list::iteratoroverObjIterator;

overObjIterator=overObjects.begin();

for(overObjIterator;overObjIterator!=overObjects.end();++overObjIterator)

{

eventArray.push_back(overObjIterator->m_overlapped.hEvent);

}

}

/********************************************************************************

*函數介紹:投放接受操作,即將指定套接字的Recv操作與重疊I/O對象關聯起來。

*********************************************************************************/

boolOverlapped::PostRecv(list::iteratormyPtrOverObject)

{

myPtrOverObject->m_operation=OP_READ;

DWORDdwBytes;

DWORDdwFlags=0;

WSABUFbuf;

buf.buf=myPtrOverObject->m_buf;

buf.len=myPtrOverObject->m_len;

memset(buf.buf,0,buf.len);

if(::WSARecv(myPtrOverObject->m_sock,&buf,1,&dwBytes,&dwFlags,&myPtrOverObject->m_overlapped,NULL)!=NO_ERROR)

{

if(::WSAGetLastError()!=WSA_IO_PENDING)

{

returnfalse;

}

}

returntrue;

}

/********************************************************************************

*函數介紹:投放發送操作,即將指定套接字的Send操作與重疊I/O對象關聯起來。

*********************************************************************************/

boolOverlapped::PostSend(list::iteratormyPtrOverObject)

{

myPtrOverObject->m_operation=OP_WRITE;

DWORDdwBytes;

DWORDdwFlags=0;

WSABUFbuf;

buf.buf=myPtrOverObject->m_buf;

buf.len=myPtrOverObject->m_len;

if(::WSASend(myPtrOverObject->m_sock,&buf,1,&dwBytes,dwFlags,&myPtrOverObject->m_overlapped,NULL)!=NO_ERROR)

{

if(::WSAGetLastError()!=WSA_IO_PENDING)

{

returnfalse;

}

}

returntrue;

}

/********************************************************************************

*函數介紹:創建accept函數完成事件,用于處理accepe后等待函數的等待事件句柄數組發

生變化,若此時無事件觸發,等待事件句柄數組仍以原來的事件句柄數組為依

據等待。

*********************************************************************************/

voidOverlapped::CreateAcceptEvent()

{

//標志套接字,用于觸發accept完成事件。

SOCKETmyClient=::WSASocket(AF_INET,SOCK_STREAM,IPPROTO_TCP,NULL,0,WSA_FLAG_OVERLAPPED);

list::iteratoracceptIterator=GetOverObject(myClient,512);

RebuildEventArray();

}

/********************************************************************************

*函數介紹:當accept函數完成時,重置accept所對應的事件,從而使得等待函數能夠在改

變后的事件句柄數組上等待。

*********************************************************************************/

voidOverlapped::SetAcceptEvent()

{

::SetEvent(eventArray.front());

}

voidOverlapped::ResetAcceptEvent()

{

::ResetEvent(eventArray.front());

}

boolOverlapped::IsAcceptEvent(intindex)

{

if(index==0)

{

returntrue;

}

else

{

returnfalse;

}

}

/*主程序*/

#include"Overlapped.h"

#include

#include

boolOperateFunction(PtrOverObjectmyPtrOverObject);

UINTWINAPIServerThread(PVOIDpvParam);

OverlappedmyOverlapped;

intmain()

{

WSADATAwsaData;

if(WSAStartup(MAKEWORD(2,2),&wsaData)!=0)

{

cout::iteratorlocalIterator=myOverlapped.GetOverObject(myClient,512);

myOverlapped.PostRecv(localIterator);

myOverlapped.RebuildEventArray();

myOverlapped.SetAcceptEvent();

}

charch;

cin>>ch;

return0;

}

/********************************************************************************

*函數介紹:數據處理函數,按照不同操作類型,處理數據的發送或接受。

*********************************************************************************/

boolOperateFunction(list::iteratormyOverObjectIterator)

{

DWORDdwTrans;

DWORDdwFlags;

BOOLret=::WSAGetOverlappedResult(myOverObjectIterator->m_sock,&(myOverObjectIterator->m_overlapped),&dwTrans,false,&dwFlags);

if(!ret)

{

if(myOverObjectIterator->m_sock!=INVALID_SOCKET)

{

closesocket(myOverObjectIterator->m_sock);

}

coutm_operation)

{

caseOP_READ:/*接收數據完成*/

if(dwTrans>0)

{

coutm_buf::iteratorlocalIterator=myOverlapped.GetOverObject(myOverObjectIterator->m_sock,512);

localIterator->m_len=myOverObjectIterator->m_len;

strcpy(localIterator->m_buf,myOverObjectIterator->m_buf);

myOverlapped.PostSend(localIterator);

myOverlapped.RebuildEventArray();

returntrue;

}

else

{

closesocket(myOverObjectIterator->m_sock);

myOverlapped.FreeOverObject(myOverObjectIterator);

myOverlapped.RebuildEventArray();

cout0)

{

returntrue;

}

else

{

closesocket(myOverObjectIterator->m_sock);

myOverlapped.FreeOverObject(myOverObjectIterator);

myOverlapped.RebuildEventArray();

returnfalse;

}

break;

}

}

/********************************************************************************

*函數介紹:服務線程函數,平常處于等待狀態,完成數據處理。

*********************************************************************************/

UINTWINAPIServerThread(PVOIDpvParam)

{

while(true)

{

intindex;

DWORDeventNum=(DWORD)(myOverlapped.eventArray.size());

index=::WSAWaitForMultipleEvents(eventNum,&(myOverlapped.eventArray[0]),false,WSA_INFINITE,false);

if(index==WSA_WAIT_FAILED)

{

cout::iteratornowIterator=(myOverlapped.FindOverObject(myOverlapped.eventArray[index]));

if(nowIterator!=NULL)

{

boolret=OperateFunction(nowIterator);

if(ret)

{

::WSAResetEvent(myOverlapped.eventArray[index]);

myOverlapped.PostRecv(nowIterator);

}

}

}

}

return0;

}

?

總結

以上是生活随笔為你收集整理的重叠IO模型-异步IO的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。