您的位置:首页 > 其它

WSAAsyncSelect 异步I/O模型

2008-11-12 11:43 567 查看
WSAAsyncSelect(s, hwnd, WM_SOCKET, FD_CONNECT | FD_READ | FD_WRITE | FD_CLOSE);
这样一来,我们的应用程序以后便可在套接字 s上,接收到有关连接、发送、接收以及套接字关闭这一系列网络事件的通知。特别要注意的是,多个事件务必在套接字上一次注册!另外还要注意的是,一旦在某个套接字上允许了事件通知,那么以后除非明确调用c l o s e s o c k e t命令,或者由应用程序针对那个套接字调用了 W S A A s y n c S e l e c t,从而更改了注册的网络事件类型,否则的话,事件通知会永远有效!若将 l E v e n t参数设为0,效果相当于停止在套接字上进行的所有网络事件通知。
若应用程序针对一个套接字调用了W S A A s y n c S e l e c t,那么套接字的模式会从“锁定”自动变成“非锁定”,我们在前面已提到过这一点。这样一来,假如调用了像W S A R e c v这样的Wi n s o c kI / O函数,但当时却并没有数据可用,那么必然会造成调用的失败,并返回W S A E W O U L D B L O C K错误。为防止这一点,应用程序应依赖于由W S A A s y n c S e l e c t的u M s g参数指定的用户自定义窗口消息,来判断网络事件类型何时在套接字上发生;而不应盲目地进行调用。

表8-3 用于W S A A s y n c S e l e c t函数的网络事件类型
事件类型 含 义
F D _ R E A D 应用程序想要接收有关是否可读的通知,以便读入数据
F D _ W R I T E 应用程序想要接收有关是否可写的通知,以便写入数据
F D _ O O B 应用程序想接收是否有带外(O O B)数据抵达的通知
F D _ A C C E P T 应用程序想接收与进入连接有关的通知
F D _ C O N N E C T 应用程序想接收与一次连接或者多点j o i n操作完成的通知
F D _ C L O S E 应用程序想接收与套接字关闭有关的通知
F D _ Q O S 应用程序想接收套接字“服务质量”(Q o S)发生更改的通知
F D _ G R O U P _ Q O S 应用程序想接收套接字组“服务质量”发生更改的通知(现在没
什么用处,为未来套接字组的使用保留)
F D _ R O U T I N G _ I N T E R FA C E _ C H A N G E 应用程序想接收在指定的方向上,与路由接口发生变化的通知
F D _ A D D R E S S _ L I S T _ C H A N G E 应用程序想接收针对套接字的协议家族,本地地址列表发生变化的通知

w P a r a m参数指定在其上面发生了一个网络事件的套接字。假若同时为这个窗口例程分配了多个套接字,这个参数的重要性便显示出来了。在 l P a r a m参数中,包含了两方面重要的信息。其中, l P a r a m的低字(低位字)指定了已经发生的网络事件,而 l P a r a m的高字(高位字)包含了可能出现的任何错误代码。

WSAAsyncSelect 服务器示范代码

#define WM_SOCKET WM_USER+1

#include < windows.h >

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,

LPSTR lpCmdLine, int nCmdShow)

{

SOCKET Listen;

HWND Window;

//Create a window and assign the ServerWinProc below to it

Window = CreateWindow(...);

//Start Winsock and create a socket

WSAStartup(...);

Listen = Socket();

//Bind the socket to port 5150 and begin listening for connections

InternetAddr.sin_family = AF_INET;

InternetAddr.sin_addr.s_addr = htonl(INADDR_ANY);

InternetAddr.sin_port = htons(5150);

bind(Listen, (PSOCKADDR) &InternetAddr, sizeof(InternetAddr));

//Set up window message notification on the new socket

//using the WM_SOCKEt define above

WSAAsyncSelect(Listen, Window, WM_SOCKET, FD_ACCEPT | FD_CLOSE);

listen(Listen, 5);

// Translate and dispatch window messages until the application terminates

}

BOOL CALLBACK ServerWinProc(HWND hDlg, WORD wMsg, WORD wParam, DWORD lParam)

{

SOCKET Accept;

switch(wMsg)

{

case WM_PAINT:

// Process window paint messages

break;

case WM_SOCKET:

// Determine whether an error occurred on the

// socket by using the WSAGETSELECTERROR() macro

if(WSAGETSELECTERROR(lParam))

{

//Display the error and close the socket

closesocket(wParam);

break;

}

// Determine what event occurred on the socket

swith(WSAGETSELECTEVENT(lParam))

{

case FD_ACCEPT:

// Accept an incoming connection

Accept = accept(wParam, NULL, NULL);

// Prepare accepted socket for read, write, and close notification

WSAAsyncSelect(Accept, hwnd, WM_SOCKET, FD_READ | FD_WRITE | FD_CLOSE);

break;

case FD_READ:

// Receive data from the socket in wParam

break;

case FD_WRITE:

// The socket in wParam is ready for sending data

break;

case FD_CLOSE:

// The connection is now closed

closesocket(wParam);

break;

}

break;

}

return TRUE;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: