版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(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),線程保持等待,直到其中的一個(gè)或者多個(gè)套接字滿足可讀或者可寫(xiě)的條件,該函數(shù)才返回。 1WSAAsyncSelect模型是非阻塞的。如圖所示,Windows Sockets 應(yīng)用程序在調(diào)用recv()函數(shù)接收數(shù)據(jù)前,調(diào)用WSAAsyncselect()函數(shù)注冊(cè)網(wǎng)絡(luò)事件。WSAAsyncselect()函數(shù)立即返回,線程繼續(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ù)。 23與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)行。4發(fā)生網(wǎng)絡(luò)事件時(shí),應(yīng)用程序得到通知的方式不同。Select()函數(shù)返回時(shí),說(shuō)明某個(gè)或者某些套接字滿足可讀可寫(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ā)送消息。5WSAAsyncSelect模型應(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)容。 7WSAAsynSelect()函數(shù) int WSAAsyncSelect( SOCKET s, HWND hWnd, unsigned int wMsg, long lEvent )8s:需要事件通知的套接字。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ù)后,自動(dòng)將
5、套接字設(shè)置為非阻塞模式。 通常,應(yīng)用程序聲明的消息要比Windows的WM_USER值大,以避免該消息與Windows預(yù)定消息發(fā)生混淆。910注冊(cè)哪種網(wǎng)絡(luò)事件,取決于實(shí)際的需要。如果應(yīng)用程序同時(shí)對(duì)多個(gè)網(wǎng)絡(luò)事件感興趣。需要對(duì)網(wǎng)絡(luò)事件類型執(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); 11當(dāng)該套接字連接完成、有數(shù)據(jù)可讀或
6、者套接字關(guān)閉的網(wǎng)絡(luò)事件事件發(fā)生時(shí),就會(huì)有WM_SOCKET消息發(fā)送給窗口句柄為hWnd窗口。 12窗口例程 當(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ù) );13hWnd:窗口句柄。uMsg消息。對(duì)Windows Sockets應(yīng)用程序來(lái)說(shuō)感興趣的是在 WSAAsyncSele
7、ct()函數(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ò)誤代碼。14在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ò)誤,則讀取Iparam低字節(jié),
8、檢查到底是發(fā)生了什么網(wǎng)絡(luò)事件??梢允褂肳SAGETSELECTEVENT宏。 15WSAGETSELECTERROR和WSAGETSELECTEVENT宏聲明如下:#define WSAGETSELECTEVENT(lParam) LOWORD(lParam)#define WSAGETSELECTERROR(lParam) HIWORD(lParam)16WSAAsyncSelect模型示例程序 下面講解一個(gè)服務(wù)器程序。該程序是Win32 Application。在該程序中使用WSAAsyncSelect模型管理接受的客戶端套接字。該程序是示例程序,忽略主許多細(xì)節(jié)。程序設(shè)計(jì)如圖所示,按照下面
9、步驟編碼。 17 1. 聲明自定義消息。在程序中聲明自定義消息WM_SOCKET。 2. 聲明窗口例程。 3. 調(diào)用MyRegisterClass()函數(shù)注冊(cè)窗口類。 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、。18191.聲明自定義消息在應(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)度202.聲明窗口例程 窗口例程是由Windows系統(tǒng)調(diào)用的函數(shù),通常將該函數(shù)的定義放在主函數(shù)之后,將聲明放在主函數(shù)之前。在示例程序中為了使主
11、程序結(jié)構(gòu)清晰,將注冊(cè)窗口類、創(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);213.注冊(cè)窗口類 調(diào)用MyR
12、egisterClass()函數(shù)注冊(cè)窗口類。 4.創(chuàng)建和顯示窗口 調(diào)用InitInstance()函數(shù)創(chuàng)建、顯示窗口。此時(shí),窗口例程開(kāi)始接收Windows消息。 225.創(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消息。23WSAAsyncSelect(sListe
13、n, 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)。 249.消息循環(huán) 在while循環(huán)語(yǔ)句中,GetMessage()函數(shù)不斷從線程消息隊(duì)列中取出消息。當(dāng)FD_ACCEPT或者FD_CLOSE網(wǎng)絡(luò)事件發(fā)生時(shí),WM_SOCKET消息被投遞到線程消息隊(duì)列中,GetMessage()函數(shù)負(fù)責(zé)將該消息從線程消息隊(duì)列中取出,DispatchMessage()函數(shù)再將消息發(fā)送到窗口例程。 2510.程序退出 當(dāng)GetMessage() 函數(shù)接收到WM_QUIT消息時(shí),while循環(huán)
14、結(jié)束,釋放資源,程序退出。2611.窗口例程 當(dāng)創(chuàng)建窗口成功后WndProc()窗口例程便開(kāi)始接收Windows消息。在該函數(shù)中需要處理許多消息。例如,當(dāng)關(guān)閉窗口時(shí)發(fā)送WM_DESTROY消息,在窗口例程中調(diào)用PostQuitMessage()函數(shù)向線程消息隊(duì)列投遞WM_QUITI消息,GetMessage()函數(shù)接收到該消息后,程序退出。27應(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)絡(luò)事件進(jìn)
15、行處理。28/窗口例程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à)客戶區(qū)/break; case WM_DESTROY:PostQuitMessage(0);break;/消息處理default:return DefWindowProc(hWnd,message,wPar
16、am,lParam);return 0;2912.CClient類在程序中聲明Cclient類管理服務(wù)器接受客戶端的新建套接字。該類構(gòu)造函數(shù)的參數(shù)為服務(wù)器接受客戶端的新建套接字。在析構(gòu)函數(shù)中將套接字關(guān)閉。在該類中聲明RecvData()函數(shù)接收數(shù)據(jù),SendData()函數(shù)發(fā)送數(shù)據(jù),GetSocket()函數(shù)返回套接字。 30#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 RecvData(void); /接
17、收數(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ū) ;3113.管理客戶端套接字的鏈表 聲明_socktnode結(jié)構(gòu)體。該結(jié)構(gòu)體pClient字段為CClient類指針。pNext變量為指向下一個(gè)節(jié)點(diǎn)指針。 typedef struct _socktnodeCClient *pClient; /CClient類指針_socktn
18、ode *pNext; /指向下一個(gè)節(jié)點(diǎn)SOCKETNODE,*PSOCKETNODE;32當(dāng)服務(wù)器接受一個(gè)客戶端連接請(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類指針。DeleteAllNode()刪除所有節(jié)點(diǎn)。3314.網(wǎng)絡(luò)事件消息處理函數(shù) 在HandleSocketMsg()函數(shù)中調(diào)用 WSAGETSELECTERROR宏檢查是否有網(wǎng)絡(luò)錯(cuò)誤事件發(fā)生
19、。如果有網(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ò)事件。 34如果網(wǎng)絡(luò)事件為FD_ACCEPT,那么說(shuō)明此時(shí)客戶端等待服務(wù)器接受連接請(qǐng)求。發(fā)生這個(gè)網(wǎng)絡(luò)事件的套接字一定是服務(wù)器監(jiān)聽(tīng)套接字。調(diào)用accept()函數(shù)接受客戶端連接請(qǐng)求,將該套接字加入鏈表中,然后以該新建套接字作為參數(shù)調(diào)用WSAAsyncSelect()函數(shù),為該套接字請(qǐng)求FD_READ、F
20、D_WRITE和FD_CLOSE網(wǎng)絡(luò)事件。 35當(dāng)HandleSocketMsg()函數(shù)接收到FD_READ網(wǎng)絡(luò)事件時(shí),說(shuō)明此時(shí)在服務(wù)器接受的客戶端套接字中,某個(gè)套接字上存在可讀的數(shù)據(jù)。這個(gè)套接字就是wParam參數(shù)值。調(diào)用GetClient()函數(shù)得到保存該套接字的CClient類指針。調(diào)用該類的ecvData()函數(shù)接收客戶端數(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í)客戶端關(guān)閉了套接字,可以調(diào)用DeleteNode()函數(shù)刪除該客戶端節(jié)點(diǎn)。36/WM
21、_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: /接受客戶端連接請(qǐng)求37 SOCKET sAccept;if(sAccept=accept(wParam,NULL,NULL)=INVALID_SOCKET)break;AddNode(sAccept); /將套接字加
22、入鏈表中 /FD_READ、FD_WRITE、FD_CLOSE事件發(fā)生 /時(shí),發(fā)送WM_SOCKET消息 WSAAsyncSelect(sAccept,hWnd,WM_SOCKET, FD_READ|FD_WRITE|FD_CLOSE); break; 38 case FD_READ: /接收數(shù)據(jù) CClient* pClient=GetClient(wParam);/根據(jù)套接字, /獲取客戶端節(jié)點(diǎn)pClient-RecvData(); /接收數(shù)據(jù)break; case FD_WRITE: CClient* pClient=GetClient(wParam);/根據(jù)套接字, /獲取客戶端節(jié)點(diǎn)p
23、Client-SendData(); /發(fā)送數(shù)據(jù)break; 39case FD_CLOSE: /對(duì)方關(guān)閉了套接字連接 DeleteNode(wParam); /刪除節(jié)點(diǎn),break; return;40調(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_WRITE網(wǎng)絡(luò)事件,那么此時(shí)應(yīng)用程序,就只能接收到FD
24、_WRITE網(wǎng)絡(luò)事件。 41如果要取消所有請(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ò)事件。42第二種情況是在同一個(gè)套接字上,多次調(diào)用WSAAsyncSelect()函數(shù),為不同的網(wǎng)絡(luò)事件定義了不同的消息,最后一次該函數(shù)調(diào)用將
25、取消前面注冊(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);43關(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ò)事件,則在該監(jiān)聽(tīng)套接字上接受的任何套接字也會(huì)請(qǐng)求FD_ACCEPT、FD
26、_READ和FD_WRITE網(wǎng)絡(luò)事件,以及發(fā)送同樣的消息。 44若需要不同的消息和網(wǎng)絡(luò)事件,應(yīng)用程序應(yīng)該調(diào)用WSAAsyncSelect()函數(shù),為該套接字請(qǐng)求不同的網(wǎng)絡(luò)事件和消息。 45關(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_READ消息時(shí),讀進(jìn)所有可讀的數(shù)據(jù)。每接收到一次FD
27、_READ網(wǎng)絡(luò)事件,應(yīng)用程序調(diào)用一次recv()函數(shù)是恰當(dāng)?shù)摹?46如何判斷套接字已經(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ò)事件。 47發(fā)送數(shù)據(jù)失敗 一個(gè)應(yīng)用程序當(dāng)接收到第一個(gè)FD_WRITE網(wǎng)絡(luò)事件后,便認(rèn)為在
28、該套接字上可以發(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ā)送出去。 48發(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é)。49 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_READ網(wǎng)絡(luò)事件時(shí)。調(diào)用recv()或者recvfr
29、om()函數(shù)后,如果仍然有可讀數(shù)據(jù)時(shí)。50 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í)。 51FD_ACCEPT事件 在下面情況下,發(fā)生FD_ACCEPT網(wǎng)絡(luò)事件。當(dāng)調(diào)用WSAAsyncSelect()函數(shù)時(shí),如果當(dāng)前有連接請(qǐng)求需要接受時(shí)。當(dāng)連接請(qǐng)求到達(dá),還沒(méi)有發(fā)送FD_ACCEPT網(wǎng)絡(luò)事件時(shí)。調(diào)用
30、accept()函數(shù)后,如果還有另外連接請(qǐng)求需要接受時(shí)。52FD_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ò)誤代碼,確定連接是否成功。53FD_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í)。54 WSAAsyncSelect模型優(yōu)勢(shì)和不足 1.優(yōu)勢(shì)該模型的使用方便了基于消息的Windo
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 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ì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 2021年超市促銷(xiāo)方案5篇范文模板
- 石河子大學(xué)《食品物性學(xué)》2022-2023學(xué)年第一學(xué)期期末試卷
- 石河子大學(xué)《結(jié)構(gòu)力學(xué)二》2023-2024學(xué)年第一學(xué)期期末試卷
- 石河子大學(xué)《簡(jiǎn)明新疆地方史教程》2022-2023學(xué)年第一學(xué)期期末試卷
- 石河子大學(xué)《風(fēng)景畫(huà)表現(xiàn)》2021-2022學(xué)年第一學(xué)期期末試卷
- 沈陽(yáng)理工大學(xué)《自動(dòng)武器原理與構(gòu)造》2023-2024學(xué)年第一學(xué)期期末試卷
- 沈陽(yáng)理工大學(xué)《交互設(shè)計(jì)》2023-2024學(xué)年第一學(xué)期期末試卷
- 2018年四川內(nèi)江中考滿分作文《我心中的英雄》12
- 沈陽(yáng)理工大學(xué)《電力電子技術(shù)》2023-2024學(xué)年期末試卷
- 廣州 存量房交易合同 范例
- 信息安全保密控制措施資料
- 《現(xiàn)代漢語(yǔ)修辭》PPT課件(完整版)
- 行政倫理學(xué)-試題及答案
- TTJCA 0007-2022 住宅室內(nèi)裝飾裝修工程施工驗(yàn)收規(guī)范
- 鄉(xiāng)村振興戰(zhàn)略項(xiàng)目經(jīng)費(fèi)績(jī)效評(píng)價(jià)指標(biāo)體系及分值表
- 構(gòu)造柱工程施工技術(shù)交底
- 醫(yī)院科室質(zhì)量與安全管理小組工作記錄本目錄
- 300字方格紙模板
- 草訣百韻歌原文及解釋
- 鋼網(wǎng)架防火涂料施工方案
評(píng)論
0/150
提交評(píng)論