非同步選擇模型

2022-05-03 01:33:09 字數 4786 閱讀 3175

非同步選擇(wsaasyncselect)模型是乙個有用的非同步 i/o 模型。利用這個模型,應用程式可在乙個套接字上,接收以 windows 訊息為基礎的網路事件通知。具體

的做法是在建好乙個套接字後,呼叫wsaasyncselect函式。該模型的核心即是wsaasyncselect函式。

wsaasyncselect函式定義如下:

int wsaasyncselect(

__in socket s,              //指定的是我們感興趣的那個套接字。

__in hwnd hwnd,          //指定乙個視窗控制代碼,它對應於網路事件發生之後,想要收到通知訊息的那個視窗。

__in unsigned int wmsg,  //指定在發生網路事件時,打算接收的訊息。該訊息會投遞到由hwnd視窗控制代碼指定的那個視窗。

__in long levent              //指定乙個位掩碼,對應於一系列網路事件的組合

);注意:

1、wmsg引數指定的訊息通常是我們自定義的訊息,應用程式需要將這個訊息設為比windows的wm_user大的乙個值,避免網路視窗訊息與系統預定義的標準窗

口訊息發生混淆與衝突。

2、levent引數指定的網路型別為:fd_read、fd_write、fd_accept、fd_connect、fd_close等。當然,到底使用fd_accept,還是使用

fd_connect型別,要取決於應用程式的身份是客戶端,還是伺服器。如應用程式同時對多個網路事件有興趣,只需對各種型別執行一次簡單的按位or(或)運算就ok。

fd_read              應用程式想要接收有關是否可讀的通知,以便讀入資料

fd_write            應用程式想要接收有關是否可寫的通知,以便寫入資料

fd_accept           應用程式想接收與進入連線有關的通知

fd_connect        應用程式想接收與一次連線完成的通知

fd_close            應用程式想接收與套接字關閉的通知

3、多個事件務必在套接字上一次註冊!另外還要注意的是,一旦在某個套接字上允許了事件通知,那麼以後除非明確呼叫closesocket命令,或者由應用程式針對那

個套接字呼叫了wsaasyncselect,從而更改了註冊的網路事件型別,否則的話,事件通知會永遠有效!若將levent引數設為0,效果相當於停止在套接字上進行的所有

網路事件通知。

4、若應用程式針對乙個套接字呼叫了wsaasyncselect,那麼套接字的模式會從「鎖定」變成「非鎖定」。這樣一來,如果呼叫了像wsarecv這樣的winsock函式,

但當時卻並沒有資料可用,那麼必然會造成呼叫的失敗,並返回wsaewouldblock錯誤。為防止這一點,應用程式應依賴於由wsaasyncselect的umsg引數指定的

使用者自定義視窗訊息,來判斷網路事件型別何時在套接字上發生;而不應盲目地進行呼叫。

應用程式在乙個套接字上成功呼叫了wsaasyncselect之後,會在與hwnd視窗控制代碼對應的視窗例程中,以windows訊息的形式,接收網路事件通知。視窗例程通常

定義如下:

lresult callback windowproc(

hwnd hwnd,           //指定乙個視窗的控制代碼,對視窗例程的呼叫正是由那個視窗發出的。

uint umsg,             //指定需要對哪些訊息進行處理。這裡我們感興趣的是wsaasyncselect呼叫中定義的訊息。

wparam wparam,   //指定在其上面發生了乙個網路事件的套接字。(假若同時為這個視窗例程分配了多個套接字,這個引數的重要性便顯示出來了。)

lparam lparam       //包含了兩方面重要的資訊。其中, lparam的低字(低位字)指定了已經發生的網路事件,而lparam的高字(高位字)包含了可能出現的任何

//錯誤**。

流程:網路事件訊息抵達乙個視窗例程後,應用程式首先應檢查lparam的高字位,以判斷是否在網路錯誤。這裡有乙個特殊的巨集: wsagetselecterror,可用

它返回高字位包含的錯誤資訊。若應用程式發現套接字上沒有產生任何錯誤,接著便應調查到底是哪個網路事件型別,具體的做法便是讀取lparam低字位的內容。此時可

使用另乙個特殊的巨集:wsagetselectevent,用它返回lparam的低字部分。

fd_write 事件通知:只有在三種條件下,才會發出 fd_write 通知:

1、使用 connect 或 wsaconnect,乙個套接字首次建立了連線。

2、使用 accept 或 wsaaccept,套接字被接受以後。

3、若 send、wsasend、sendto 或 wsasendto 操作失敗,返回了 wsaewouldblock 錯誤,而且緩衝區的空間變得可用。

下面,我們來看看具體的演示,客戶端是用select模型實現的,伺服器端是用wsaasyncselect實現的,兩者介面都相當的簡潔

伺服器介面如下:    

客戶端介面如下:    

其中,多個客戶端可以同時與伺服器端實現了,由於使用wsaasyncselect模型及我只起乙個工作執行緒的緣故,故最多只能接受64個客戶端。    

理論知識與演示完之後,我們來看看伺服器端具體的**實現

1、當然是初始化socket了,沒什麼好說的

wsadata data;

interror;

error = wsastartup(makeword(2, 2), &data);

if (0 !=error)

if(hibyte(data.wversion) != 2 &&lobyte(data.wversion))

return true;

2、定義乙個自定義訊息,前面理論知識已講過就不再重複了    

#define wm_socket wm_user + 0x01
3、開啟乙個工作執行緒,初始化socket,開始監聽。其實,這個執行緒可以封裝成乙個函式,具體看**就知道了,封裝成執行緒只是個人習慣哈。  

uint threadproc(lpvoid lpparameter)

char ipbuf[1024] = ;

wcstombs(ipbuf, pdlg->getipaddress(), pdlg->getipaddress().getlength());

const

char *p =ipbuf;

sockaddr_in serveraddress;

serveraddress.sin_addr.s_un.s_addr =inet_addr(p);

serveraddress.sin_family =af_inet;

serveraddress.sin_port = htons(pdlg->m_iport);

if (socket_error == bind(pdlg->m_listensocket, (sockaddr*)&serveraddress, sizeof

(sockaddr_in)))

wsaasyncselect(pdlg->m_listensocket, pdlg->getsafehwnd(), wm_socket, fd_accept |fd_close);

listen(pdlg->m_listensocket, somaxconn);

pdlg->showtext(_t("

系統訊息:伺服器開始監聽。。。

"));

return

true;

}

4、wsaasyncselect模型的核心就是這個視窗過程,但是格式也是一樣一樣的。。。

lresult cwsaasyncselectdlg::windowproc(uint message, wparam wparam, lparam lparam)

; cstring cstrmsg;

cstring cstrip;

szclientitem clientitem;

sockaddr_in clientaddr = ;

int ilength = sizeof

(sockaddr_in);

switch

(message)}}

switch

(wsagetselectevent(lparam))

}break

;

case

fd_write:

break

;

case

fd_close:

break;

}

default:break

; }

return

cdialogex::windowproc(message, wparam, lparam);

}

具體核心**我想應該就是這些了,這個模型相當簡單,操作無非是這幾步:

1、定義乙個自定義訊息

2、wsaasyncselect函式關聯自定義訊息並選擇感興趣的網路事件

3、定義乙個視窗過程,wsaasyncselect函式繫結到這個視窗過程

4、在視窗過程捕獲感興趣的網路事件並做相應的處理。

是不是很簡單。。。。

非同步選擇模型

非同步選擇 wsaasyncselect 模型是乙個有用的非同步 i o 模型。利用這個模型,應用程式可在乙個套接字上,接收以 windows 訊息為基礎的網路事件通知。具體 的做法是在建好乙個套接字後,呼叫wsaasyncselect函式。該模型的核心即是wsaasyncselect函式。wsaa...

二 非同步選擇模型(WSAAsyncSelect)

非同步選擇 wsaasyncselect 模型是乙個有用的非同步 i o 模型。利用這個模型,應用程式可在乙個套接字上,接收以 windows 訊息為基礎的網路事件通知。具體的做法是在建好乙個套接字後,呼叫wsaasyncselect函式。該模型的核心即是wsaasyncselect函式。要想使用 ...

socket模型 非同步事件選擇模型的正常退出

今天要用到非同步事件選擇模型,發現demo原型不能正常退出.除錯了一下,用wsasetevent waitforsingleobject 全域性標記搞定.如果以後要用到非同步事件選擇模型,在這個demo上直接加業務邏輯.srcasynceventselect.zip include stdafx.h...