網(wǎng)絡(luò)WSAAsyncSelect網(wǎng)絡(luò)模型講解.ppt_第1頁(yè)
網(wǎng)絡(luò)WSAAsyncSelect網(wǎng)絡(luò)模型講解.ppt_第2頁(yè)
網(wǎng)絡(luò)WSAAsyncSelect網(wǎng)絡(luò)模型講解.ppt_第3頁(yè)
網(wǎng)絡(luò)WSAAsyncSelect網(wǎng)絡(luò)模型講解.ppt_第4頁(yè)
網(wǎng)絡(luò)WSAAsyncSelect網(wǎng)絡(luò)模型講解.ppt_第5頁(yè)
已閱讀5頁(yè),還剩59頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶(hù)提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

1、WSASsyncSelect模型,前面學(xué)習(xí)的Windows Sockets select模型。在應(yīng)用程序中調(diào)用select()函數(shù)時(shí),會(huì)發(fā)生阻塞現(xiàn)象。開(kāi)發(fā)人員可以通過(guò)select()函數(shù)的timeout參數(shù),設(shè)置函數(shù)調(diào)用的阻塞時(shí)間,在設(shè)定時(shí)間內(nèi),線(xiàn)程保持等待,直到其中的一個(gè)或者多個(gè)套接字滿(mǎn)足可讀或者可寫(xiě)的條件,該函數(shù)才返回。,WSAAsyncSelect模型是非阻塞的。如圖所示,Windows Sockets 應(yīng)用程序在調(diào)用recv()函數(shù)接收數(shù)據(jù)前,調(diào)用WSAAsyncselect()函數(shù)注冊(cè)網(wǎng)絡(luò)事件。WSAAsyncselect()函數(shù)立即返回,線(xiàn)程繼續(xù)運(yùn)行。當(dāng)系統(tǒng)中數(shù)據(jù)準(zhǔn)備好時(shí),向應(yīng)用程

2、序發(fā)送消息。應(yīng)用程序接收到這個(gè)消息后,調(diào)用recv()函數(shù)接收數(shù)據(jù)。,與select模型比較,WSAAsyncSelect模型與Select模型的相同點(diǎn): 都可以對(duì)Windows套接字應(yīng)用程序所使用的多個(gè)套接字進(jìn)行有效的管理。 WSAAsyncSeelect模型與Select模型相比存在以下不同: WSAAsyncSelet模型是異步的。在應(yīng)用程序中調(diào)用WSAAsyncSelect()函數(shù),通知系統(tǒng)感興趣的網(wǎng)絡(luò)事件,該函數(shù)立即返回,應(yīng)用程序繼續(xù)運(yùn)行。,發(fā)生網(wǎng)絡(luò)事件時(shí),應(yīng)用程序得到通知的方式不同。Select()函數(shù)返回時(shí),說(shuō)明某個(gè)或者某些套接字滿(mǎn)足可讀可寫(xiě)的條件,應(yīng)用程序需要使用FD_ISSE

3、T宏,判斷套接字是否存在于可讀可寫(xiě)集合中。而對(duì)于WSAAsyncSelect模型來(lái)說(shuō),當(dāng)網(wǎng)絡(luò)事件發(fā)生時(shí),系統(tǒng)向應(yīng)用程序發(fā)送消息。,WSAAsyncSelect模型應(yīng)用在基于消息的Windows環(huán)境下,使用該模型時(shí)必須創(chuàng)建窗口。而Slelect模型廣泛應(yīng)用在Unix系統(tǒng)和Windows系統(tǒng),使用模型不需要?jiǎng)?chuàng)建窗口。 應(yīng)用程序中調(diào)用WSAAsyncSelect()函數(shù)后,自動(dòng)將套接字設(shè)置為非阻塞模式。而應(yīng)用程序中調(diào)用select()函數(shù)后,并不能改變?cè)撎捉幼值墓ぷ鞣绞健?套接字WSAAsyncSelect模型實(shí)現(xiàn),WSAAsyncSelect模型核心是WSAAsyncSelect()函數(shù),該函數(shù)使

4、得Windows應(yīng)用程序能夠接收網(wǎng)絡(luò)事件消息。在應(yīng)用程序窗口例程中對(duì)接收到的網(wǎng)絡(luò)事件進(jìn)行處理。 由于WSAAsyncSelect模型應(yīng)用在基于消息的Windows應(yīng)用程序中,所以本節(jié)還將講解窗口例程和如何創(chuàng)建窗口等內(nèi)容。,WSAAsynSelect()函數(shù),int WSAAsyncSelect( SOCKET s, HWND hWnd, unsigned int wMsg, long lEvent ),s:需要事件通知的套接字。 hWnd: 當(dāng)網(wǎng)絡(luò)事件發(fā)生時(shí)接收消息的窗口句柄。 wWsg: 當(dāng)網(wǎng)絡(luò)事件發(fā)生時(shí)窗口收到的消息。 lEvent:應(yīng)用程序感興趣的網(wǎng)絡(luò)事件集合。 應(yīng)當(dāng)用程序中調(diào)用該函數(shù)后

5、,自動(dòng)將套接字設(shè)置為非阻塞模式。 通常,應(yīng)用程序聲明的消息要比Windows的WM_USER值大,以避免該消息與Windows預(yù)定消息發(fā)生混淆。,注冊(cè)哪種網(wǎng)絡(luò)事件,取決于實(shí)際的需要。如果應(yīng)用程序同時(shí)對(duì)多個(gè)網(wǎng)絡(luò)事件感興趣。需要對(duì)網(wǎng)絡(luò)事件類(lèi)型執(zhí)行按位OR(或)運(yùn)算。然后將它們分配給lEvent參數(shù)。 例如,應(yīng)用程序希望在套接字上接收有關(guān)連接完成、數(shù)據(jù)可讀和套接字關(guān)閉的網(wǎng)絡(luò)事件。那么在應(yīng)用程序中,調(diào)用WSAAsyncSelect()函數(shù)如下所示: WSAAsyncSelect(s, hWnd,WM_SOCKET, FD_CONNECT|FD_READ|FD_CLOSE);,當(dāng)該套接字連接完成、有數(shù)據(jù)

6、可讀或者套接字關(guān)閉的網(wǎng)絡(luò)事件事件發(fā)生時(shí),就會(huì)有WM_SOCKET消息發(fā)送給窗口句柄為hWnd窗口。,窗口例程,當(dāng)調(diào)用WSAAsyncselect()函數(shù)后,應(yīng)用程序會(huì)在hWnd窗口例程,以消息形式接收網(wǎng)絡(luò)事件通知。窗口例程是回調(diào)函數(shù),當(dāng)成功創(chuàng)建窗口后由系統(tǒng)調(diào)用。窗口例程聲明如下: LRESULT CALLBACK WindowProc( HWND hWnd,/窗口句柄 UINT uMsg,/消息 WPARAM wParam, /消息參數(shù) LPARAM lParam, /消息參數(shù) );,hWnd:窗口句柄。 uMsg消息。對(duì)Windows Sockets應(yīng)用程序來(lái)說(shuō)感興趣的是在 WSAAsync

7、Select()函數(shù)中,由應(yīng)用程序定義的消息。 wParam:消息參數(shù)。在 Windows Sockets應(yīng)用程序中,該參數(shù)指明發(fā)生網(wǎng)絡(luò)事件的套接字。 lParam: 消息參數(shù)。在 Windows sockets 應(yīng)用程序中,該參數(shù)低字節(jié)指明已經(jīng)發(fā)生的網(wǎng)絡(luò)事件。高字節(jié)包含可能出現(xiàn)的錯(cuò)誤代碼。,在Windows sockets 應(yīng)用程序中,當(dāng)WindowProc()函數(shù)接收到網(wǎng)絡(luò)事件消息時(shí),在該函數(shù)內(nèi)執(zhí)行下面步驟 : (1) 讀取lParam參數(shù)高字節(jié),判斷是否發(fā)生了一個(gè)網(wǎng)絡(luò)錯(cuò)誤事件??梢允褂?WSAGETSELECTERROR宏。 (2) 如果應(yīng)用程序發(fā)現(xiàn)套接字上沒(méi)有發(fā)生任何錯(cuò)誤,則讀取Ipa

8、ram低字節(jié),檢查到底是發(fā)生了什么網(wǎng)絡(luò)事件??梢允褂肳SAGETSELECTEVENT宏。,WSAGETSELECTERROR和WSAGETSELECTEVENT宏聲明如下: #define WSAGETSELECTEVENT(lParam) LOWORD(lParam) #define WSAGETSELECTERROR(lParam) HIWORD(lParam),WSAAsyncSelect模型示例程序,下面講解一個(gè)服務(wù)器程序。該程序是Win32 Application。在該程序中使用WSAAsyncSelect模型管理接受的客戶(hù)端套接字。該程序是示例程序,忽略主許多細(xì)節(jié)。程序設(shè)計(jì)如圖所

9、示,按照下面步驟編碼。,1. 聲明自定義消息。在程序中聲明自定義消息WM_SOCKET。 2. 聲明窗口例程。 3. 調(diào)用MyRegisterClass()函數(shù)注冊(cè)窗口類(lèi)。 4. 調(diào)用InitInstance()函數(shù)創(chuàng)建并顯示窗口。因?yàn)閃SAAsyncSelect()函數(shù)的第一個(gè)參數(shù)是窗口句柄,所以要在調(diào)用該函數(shù)之前創(chuàng)建窗口。 5. 初始化套接字動(dòng)態(tài)庫(kù),創(chuàng)建套接字。 6. 調(diào)用WSAAsyncSelect()函數(shù)注冊(cè)感興趣網(wǎng)絡(luò)事件。該示例程序中,服務(wù)器監(jiān)聽(tīng)套接字,感興趣的網(wǎng)絡(luò)事件有FD_ACCEPT和FD_CLOSE. 7. 綁定套接字,開(kāi)始監(jiān)聽(tīng)。 8. 消息循環(huán)。 9. 釋放套接字和申請(qǐng)的其

10、他資源。,1.聲明自定義消息,在應(yīng)用程序中,通常要聲明一個(gè)比WM_USER值要大的自定義消息,以免與Windows定義的消息沖突。除了聲明自定義消息外,在示例程序中還要聲明最大字符串長(zhǎng)度、服務(wù)器端口、數(shù)據(jù)緩沖區(qū)長(zhǎng)度。 #define MAX_LOADSTRING100 /最大字符串長(zhǎng)度 #define WM_SOCKETWM_USER+1 /套接字消息 #define PORT5150/服務(wù)器端口 #define MAX_SIZE_BUF 1024 /數(shù)據(jù)緩沖區(qū)長(zhǎng)度,2.聲明窗口例程,窗口例程是由Windows系統(tǒng)調(diào)用的函數(shù),通常將該函數(shù)的定義放在主函數(shù)之后,將聲明放在主函數(shù)之前。在示例程序中

11、為了使主程序結(jié)構(gòu)清晰,將注冊(cè)窗口類(lèi)、創(chuàng)建和顯示窗口的過(guò)程都設(shè)計(jì)為函數(shù),并提前聲明。聲明HandleSocketMsg()函數(shù)用于對(duì)Windows網(wǎng)絡(luò)事件消息進(jìn)行處理。 ATOM MyRegisterClass(HINSTANCE hInstance); /注冊(cè)窗口 BOOL InitInstance(HINSTANCE,int); /初始化實(shí)例 /窗口例程 LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM); /處理WM_SOCKET消息 void HandleSocketMsg(WPARM wParam,LPARAM lParam);,3.注冊(cè)

12、窗口類(lèi),調(diào)用MyRegisterClass()函數(shù)注冊(cè)窗口類(lèi)。,4.創(chuàng)建和顯示窗口,調(diào)用InitInstance()函數(shù)創(chuàng)建、顯示窗口。此時(shí),窗口例程開(kāi)始接收Windows消息。,5.創(chuàng)建套接字,調(diào)用WSAStartup()函數(shù)初始化套接字動(dòng)態(tài)庫(kù),調(diào)用socket()函數(shù)創(chuàng)建套接字。,6.注冊(cè)感興趣的網(wǎng)絡(luò)事件,以窗口名柄hWnd和WM_SOCKET為第2、第3個(gè)參數(shù)調(diào)用WSAAsyncSelect()函數(shù)。同時(shí)注冊(cè)FD_ACCRPT和FD_CLOSE網(wǎng)絡(luò)事件。請(qǐng)求系統(tǒng)當(dāng)FD_ACCEPT和FD_CLOSE網(wǎng)絡(luò)事件發(fā)生時(shí),給hWnd窗口發(fā)送WM_SOCKET消息。,WSAAsyncSelect(

13、sListen, hWnd,WM_SOCKET, FD_READ|FD_CLOSE);,7.綁定套接字,調(diào)用bind()函數(shù)綁定套接字。,8.開(kāi)始監(jiān)聽(tīng),調(diào)用listen()函數(shù)套接字開(kāi)始監(jiān)聽(tīng)。,9.消息循環(huán),在while循環(huán)語(yǔ)句中,GetMessage()函數(shù)不斷從線(xiàn)程消息隊(duì)列中取出消息。當(dāng)FD_ACCEPT或者FD_CLOSE網(wǎng)絡(luò)事件發(fā)生時(shí),WM_SOCKET消息被投遞到線(xiàn)程消息隊(duì)列中,GetMessage()函數(shù)負(fù)責(zé)將該消息從線(xiàn)程消息隊(duì)列中取出,DispatchMessage()函數(shù)再將消息發(fā)送到窗口例程。,10.程序退出,當(dāng)GetMessage() 函數(shù)接收到WM_QUIT消息時(shí),whi

14、le循環(huán)結(jié)束,釋放資源,程序退出。,11.窗口例程,當(dāng)創(chuàng)建窗口成功后WndProc()窗口例程便開(kāi)始接收Windows消息。在該函數(shù)中需要處理許多消息。 例如,當(dāng)關(guān)閉窗口時(shí)發(fā)送WM_DESTROY消息,在窗口例程中調(diào)用PostQuitMessage()函數(shù)向線(xiàn)程消息隊(duì)列投遞WM_QUITI消息,GetMessage()函數(shù)接收到該消息后,程序退出。,應(yīng)用程序不感興趣的消息交給DefWindowProc()函數(shù)處理。 當(dāng)FD_ACCEPT或者FD_CLOSE網(wǎng)絡(luò)事件發(fā)生時(shí),窗口例程接收到WM_SOCKET消息。在窗口例程中調(diào)用HandleSocketMsg()函數(shù)對(duì)觸發(fā)WM_SOCKET消息的網(wǎng)

15、絡(luò)事件進(jìn)行處理。,/窗口例程 LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg,WPARAM wParam, LPARAM lParam) switch(message) case WM_SOCKET:/網(wǎng)絡(luò)事件發(fā)生時(shí)發(fā)送給該窗口的消息 HandleSocketMsg(wParam,lParam); /處理該消息 break; case WM_PAINT:/畫(huà)客戶(hù)區(qū) / break; case WM_DESTROY: PostQuitMessage(0); break; /消息處理 default: return DefWindowProc(hWnd,

16、message,wParam,lParam); return 0; ,12.CClient類(lèi),在程序中聲明Cclient類(lèi)管理服務(wù)器接受客戶(hù)端的新建套接字。該類(lèi)構(gòu)造函數(shù)的參數(shù)為服務(wù)器接受客戶(hù)端的新建套接字。在析構(gòu)函數(shù)中將套接字關(guān)閉。 在該類(lèi)中聲明RecvData()函數(shù)接收數(shù)據(jù),SendData()函數(shù)發(fā)送數(shù)據(jù),GetSocket()函數(shù)返回套接字。,#define MAX_SIZE_BUF1024/數(shù)據(jù)緩沖區(qū)長(zhǎng)度 class CClient public: CClient(SOCKET s); /構(gòu)造函數(shù) virtual CClient( ); /析構(gòu)函數(shù) public: void Recv

17、Data(void); /接收數(shù)據(jù) void SendData(void); /發(fā)送數(shù)據(jù) SOCKET GetSocket(void); /獲取套接字 private: SOCKET m_s; /套接字 char m_recvBufMAX_SIZE_BUF; /接收數(shù)據(jù)緩沖區(qū) char m_sendBufMAX_SIZE_BUF; /發(fā)送數(shù)據(jù)緩沖區(qū) ;,13.管理客戶(hù)端套接字的鏈表,聲明_socktnode結(jié)構(gòu)體。該結(jié)構(gòu)體pClient字段為CClient類(lèi)指針。pNext變量為指向下一個(gè)節(jié)點(diǎn)指針。 typedef struct _socktnode CClient *pClient; /CC

18、lient類(lèi)指針 _socktnode *pNext; /指向下一個(gè)節(jié)點(diǎn) SOCKETNODE,*PSOCKETNODE;,當(dāng)服務(wù)器接受一個(gè)客戶(hù)端連接請(qǐng)求后,創(chuàng)建一個(gè)CClient實(shí)例,新建一個(gè)SOCKETNODE節(jié)點(diǎn)。將實(shí)例指針賦值給SOCKETNODE結(jié)構(gòu)體的pClient變量。 為了對(duì)鏈表進(jìn)行操作,聲明如下函數(shù)。 AddNode()函數(shù),添加節(jié)點(diǎn)。 DeleteNode()函數(shù):刪除節(jié)點(diǎn)。 GetClient()函數(shù):獲得Cclient類(lèi)指針。 DeleteAllNode()刪除所有節(jié)點(diǎn)。,14.網(wǎng)絡(luò)事件消息處理函數(shù),在HandleSocketMsg()函數(shù)中調(diào)用 WSAGETSELEC

19、TERROR宏檢查是否有網(wǎng)絡(luò)錯(cuò)誤事件發(fā)生。 如果有網(wǎng)絡(luò)錯(cuò)誤事件發(fā)生則調(diào)用 DeleteNode()函數(shù)將該套接字從鏈表中刪除。在前面的講解中,已經(jīng)知道 wParam 參數(shù)為發(fā)生網(wǎng)絡(luò)事件的套接字。所以,以wParam為參數(shù)調(diào)用 DeleteNode函數(shù)。 如果沒(méi)有網(wǎng)絡(luò)錯(cuò)誤事件發(fā)生,則調(diào)用WSAGETSELECTEVENT宏,檢查發(fā)生了什么網(wǎng)絡(luò)事件。,如果網(wǎng)絡(luò)事件為FD_ACCEPT,那么說(shuō)明此時(shí)客戶(hù)端等待服務(wù)器接受連接請(qǐng)求。發(fā)生這個(gè)網(wǎng)絡(luò)事件的套接字一定是服務(wù)器監(jiān)聽(tīng)套接字。 調(diào)用accept()函數(shù)接受客戶(hù)端連接請(qǐng)求,將該套接字加入鏈表中,然后以該新建套接字作為參數(shù)調(diào)用WSAAsyncSelect

20、()函數(shù),為該套接字請(qǐng)求FD_READ、FD_WRITE和FD_CLOSE網(wǎng)絡(luò)事件。,當(dāng)HandleSocketMsg()函數(shù)接收到FD_READ網(wǎng)絡(luò)事件時(shí),說(shuō)明此時(shí)在服務(wù)器接受的客戶(hù)端套接字中,某個(gè)套接字上存在可讀的數(shù)據(jù)。這個(gè)套接字就是wParam參數(shù)值。調(diào)用GetClient()函數(shù)得到保存該套接字的CClient類(lèi)指針。調(diào)用該類(lèi)的ecvData()函數(shù)接收客戶(hù)端數(shù)據(jù)。 HandleSocketMsg()函數(shù)接收到FD_WRITE網(wǎng)絡(luò)事件時(shí)的處理方法,同收到FD_READ網(wǎng)絡(luò)事件時(shí)的處理方法相似。 當(dāng)該函數(shù)接收到FD_CLOSE網(wǎng)絡(luò)事件時(shí),說(shuō)明此時(shí)客戶(hù)端關(guān)閉了套接字,可以調(diào)用DeleteN

21、ode()函數(shù)刪除該客戶(hù)端節(jié)點(diǎn)。,/WM_SOCKET消息處理 void HandleSocketMsg(WPARAM wParam,LPARAM lParam) if (WASGETSELECTERROR(lParam) /檢查網(wǎng)絡(luò)錯(cuò)誤 DeleteNode(wParam); /刪除節(jié)點(diǎn),關(guān)閉套接字 else /檢查網(wǎng)絡(luò)事件 switch(WASGETSELECTEVENT(lParam) case FD_ACCEPT: /接受客戶(hù)端連接請(qǐng)求, SOCKET sAccept; if(sAccept=accept(wParam,NULL,NULL) =INVALID_SOCKET) break

22、; AddNode(sAccept); /將套接字加入鏈表中 /FD_READ、FD_WRITE、FD_CLOSE事件發(fā)生 /時(shí),發(fā)送WM_SOCKET消息 WSAAsyncSelect(sAccept,hWnd,WM_SOCKET, FD_READ|FD_WRITE|FD_CLOSE); break; ,case FD_READ: /接收數(shù)據(jù) CClient* pClient=GetClient(wParam);/根據(jù)套接字, /獲取客戶(hù)端節(jié)點(diǎn) pClient-RecvData(); /接收數(shù)據(jù) break; case FD_WRITE: CClient* pClient=GetClient

23、(wParam);/根據(jù)套接字, /獲取客戶(hù)端節(jié)點(diǎn) pClient-SendData(); /發(fā)送數(shù)據(jù) break; ,case FD_CLOSE: /對(duì)方關(guān)閉了套接字連接 DeleteNode(wParam); /刪除節(jié)點(diǎn),break; return; ,調(diào)用WSAAsyncSelect()函數(shù)注意問(wèn)題,接收不到網(wǎng)絡(luò)事件 第一種情況是由于在同一個(gè)套接字同一個(gè)自定義消息上,多次調(diào)用WSAAsyncSelect()函數(shù)注冊(cè)不同的網(wǎng)絡(luò)事件,最后一次函數(shù)調(diào)用取消了前面注冊(cè)的網(wǎng)絡(luò)事件。 例如,在應(yīng)用程序中,第一次調(diào)用WSAAsyncSelect()函數(shù)注冊(cè)FD_READ網(wǎng)絡(luò)事件,然后又調(diào)用該函數(shù)注冊(cè)F

24、_WRITE網(wǎng)絡(luò)事件,那么此時(shí)應(yīng)用程序,就只能接收到FD_WRITE網(wǎng)絡(luò)事件。,如果要取消所有請(qǐng)求的網(wǎng)絡(luò)事件通知,告知indows Sockets實(shí)現(xiàn)不再為該套接字發(fā)送任何網(wǎng)絡(luò)事件相關(guān)的消息,要以參數(shù)IEvent值為0調(diào)用WSAAsyncSelect()函數(shù)。 WSAAsyncSelect(s,hWnd,0,0); 需要注意盡管應(yīng)用程序調(diào)用上述函數(shù)取消了網(wǎng)絡(luò)事件通知,但是在應(yīng)用程序消息隊(duì)列中,可能還有網(wǎng)絡(luò)消息在排隊(duì)。所以在調(diào)用WSAAsyncSelect()函數(shù)取消網(wǎng)絡(luò)事件消息后,應(yīng)用程序還應(yīng)該繼續(xù)準(zhǔn)備接收網(wǎng)絡(luò)事件。,第二種情況是在同一個(gè)套接字上,多次調(diào)用WSAAsyncSelect()函數(shù),

25、為不同的網(wǎng)絡(luò)事件定義了不同的消息,最后一次該函數(shù)調(diào)用將取消前面注冊(cè)的網(wǎng)絡(luò)事件。 下面的代碼中,第二次函數(shù)調(diào)用將會(huì)取消第一次函數(shù)調(diào)用的作用。只有FD_WRITE網(wǎng)絡(luò)事件能過(guò)wMsg2消息通知到窗口。 WSAAsyncSelect(s,hWnd,wMsg1,FD_READ); WSAAsyncSelect(s,hWnd,wMsg2,FD_WRITE);,關(guān)于accept()函數(shù),因?yàn)檎{(diào)用accept()函數(shù)接受的套接字和監(jiān)聽(tīng)套接字具有同樣的屬性。所以,任何為監(jiān)聽(tīng)套接字設(shè)置的網(wǎng)絡(luò)事件對(duì)接受的套接字同樣起作用。 如果一個(gè)監(jiān)聽(tīng)套接字請(qǐng)求FD_ACCEPT、FD_READ和FD_WRITE網(wǎng)絡(luò)事件,則在該

26、監(jiān)聽(tīng)套接字上接受的任何套接字也會(huì)請(qǐng)求FD_ACCEPT、FD_READ和FD_WRITE網(wǎng)絡(luò)事件,以及發(fā)送同樣的消息。,若需要不同的消息和網(wǎng)絡(luò)事件,應(yīng)用程序應(yīng)該調(diào)用WSAAsyncSelect()函數(shù),為該套接字請(qǐng)求不同的網(wǎng)絡(luò)事件和消息。,關(guān)于FD_READ網(wǎng)絡(luò)事件,為一個(gè)FD_READ網(wǎng)絡(luò)事件不要多次調(diào)用recv()函數(shù)。如果應(yīng)用程序?yàn)橐粋€(gè)FD_READ網(wǎng)絡(luò)事件,調(diào)用了多個(gè)recv()函數(shù),會(huì)使得該應(yīng)用程序接收到多個(gè)_READ網(wǎng)絡(luò)事件。 如果在一次接收FD_READ網(wǎng)絡(luò)事件時(shí)需要調(diào)用多次recv()函數(shù),應(yīng)用程序應(yīng)該在調(diào)用recv()函數(shù)之前關(guān)閉FD_READ 消息。 應(yīng)用程序不必在收到FD

27、_READ消息時(shí),讀進(jìn)所有可讀的數(shù)據(jù)。每接收到一次FD_READ網(wǎng)絡(luò)事件,應(yīng)用程序調(diào)用一次recv()函數(shù)是恰當(dāng)?shù)摹?如何判斷套接字已經(jīng)關(guān)閉,要使用FD_CLOSE網(wǎng)絡(luò)事件來(lái)判斷套接字是否已經(jīng)關(guān)閉。 接收FD_CLOSE網(wǎng)絡(luò)事件時(shí),錯(cuò)誤代碼指示出套接字是從容關(guān)閉還是硬關(guān)閉。如果錯(cuò)誤代碼0,則為從容關(guān)閉;若錯(cuò)誤代碼為WSAECONNRESET,則套接字是硬關(guān)閉。 如果套接字從容關(guān)閉,數(shù)據(jù)已經(jīng)都全部接收,應(yīng)用程序只會(huì)收到FD_CLOSE消息來(lái)指出虛電路關(guān)閉,它不會(huì)收到FD_READ消息來(lái)表明這種狀況。 調(diào)用closesocket()函數(shù)后不會(huì)投遞FD_CLOSE網(wǎng)絡(luò)事件。,發(fā)送數(shù)據(jù)失敗,一個(gè)應(yīng)用程

28、序當(dāng)接收到第一個(gè)FD_WRITE網(wǎng)絡(luò)事件后,便認(rèn)為在該套接字上可以發(fā)送數(shù)據(jù)。當(dāng)調(diào)用輸出函數(shù)發(fā)送數(shù)據(jù)時(shí),會(huì)收到WSAEWOULDBLOCKE錯(cuò)誤。經(jīng)過(guò)這樣的失敗后,要在下一次接收到FD_WRITE網(wǎng)絡(luò)事件后,再次發(fā)送數(shù)據(jù),才能夠?qū)?shù)據(jù)發(fā)送出去。,發(fā)生網(wǎng)絡(luò)事件的條件,調(diào)用WSAAsyncSelect()函數(shù)只是請(qǐng)求系統(tǒng)在網(wǎng)絡(luò)事件發(fā)生時(shí),給窗口發(fā)送消息.開(kāi)發(fā)人員需要了解在什么情況下會(huì)發(fā)生網(wǎng)絡(luò)事件下。下面對(duì)發(fā)生網(wǎng)絡(luò)事件條件進(jìn)行小結(jié)。,FD_READ網(wǎng)絡(luò)事件,在下面情況下,發(fā)生FD_READ網(wǎng)絡(luò)事件。 當(dāng)調(diào)用WSAAsyncSelect()函數(shù)時(shí),如果當(dāng)前有可讀數(shù)據(jù)時(shí)。 當(dāng)數(shù)據(jù)到達(dá)并且沒(méi)有發(fā)送FD_RE

29、AD網(wǎng)絡(luò)事件時(shí)。 調(diào)用recv()或者recvfrom()函數(shù)后,如果仍然有可讀數(shù)據(jù)時(shí)。,FD_WRITE事件,在下面情況下,發(fā)生FD_WRITE網(wǎng)絡(luò)事件。 當(dāng)調(diào)用WSAAsyncSelect()函數(shù)時(shí),如果調(diào)用能夠發(fā)送數(shù)據(jù)時(shí)。 調(diào)用connect()或者accept()函數(shù)后,當(dāng)連接已經(jīng)建立時(shí)。 調(diào)用send()或者sendto()函數(shù),返回WSAEWOULDBLOCKE錯(cuò)誤后,再次調(diào)用send()或者sendto()函數(shù)可能成功時(shí)。,FD_ACCEPT事件,在下面情況下,發(fā)生FD_ACCEPT網(wǎng)絡(luò)事件。 當(dāng)調(diào)用WSAAsyncSelect()函數(shù)時(shí),如果當(dāng)前有連接請(qǐng)求需要接受時(shí)。 當(dāng)連接請(qǐng)

30、求到達(dá),還沒(méi)有發(fā)送FD_ACCEPT網(wǎng)絡(luò)事件時(shí)。 調(diào)用accept()函數(shù)后,如果還有另外連接請(qǐng)求需要接受時(shí)。,FD_CONNECT事件,在下面情況下,發(fā)生FD_CONNECT網(wǎng)絡(luò)事件。 當(dāng)調(diào)用WSAAsyncSelect()函數(shù),如果當(dāng)前一個(gè)連接已經(jīng)建立時(shí)。 當(dāng)調(diào)用connect()函數(shù)后,建立連接完成時(shí)。 當(dāng)調(diào)用WSAJoinLeaf()函數(shù)后,加入操作完成時(shí)。 在面向連接的非阻塞套接字上,調(diào)用connect()、WSAConnect()或者WSAJoinLeaf()函數(shù)后,嘗試連接完成時(shí)。此時(shí)應(yīng)用程序應(yīng)該檢查錯(cuò)誤代碼,確定連接是否成功。,FD_CLOSE事件,FD_CLOSE事件僅對(duì)面向連接套接字有效,在下面情況下發(fā)送FD_CLOSE事件。 當(dāng)調(diào)用WSAAsyncSelect()函數(shù)時(shí),套接字連接關(guān)閉時(shí)。 對(duì)方執(zhí)行了從容關(guān)閉后,沒(méi)有數(shù)據(jù)可讀時(shí)。如果數(shù)據(jù)已經(jīng)到達(dá)并等待讀取,F(xiàn)D_CLOSE事件不會(huì)被發(fā)送,直到所有的數(shù)據(jù)都被接收。 調(diào)用shutdown()函數(shù)執(zhí)行從容關(guān)閉,對(duì)方應(yīng)答FIN后,此時(shí)如果沒(méi)有數(shù)據(jù)可讀時(shí)。 當(dāng)對(duì)方結(jié)束了連接,并且IParam包含WSAECONNRESET錯(cuò)誤時(shí)。,WSAAsyncSelect模型優(yōu)勢(shì)和不足,1.優(yōu)勢(shì) 該模型的使用方便了基于消息的Windows環(huán)境下開(kāi)發(fā)套

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶(hù)所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶(hù)上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶(hù)上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶(hù)因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論