WSAAsyncSelect基于Windows消息机制异步I/O模型,为特定网络事件指定系统通知信息.
函数定义
int WSAAsyncSelect(SOCKET s, HWND hWnd, unsigned int wMsg, long lEvent);
(1)参数4-1Event:设定用户关心得套接口上的网络事件.形式如:1Event=FD_READ/FD_CLOSE.
网络I/O事件 简表
事件值 含义 触发条件
FD_READ 套接口有可读消息通知 recv,recvfrom,WSARecv或WSARecvFrom
FD_WRITE 套接口有可发消息通知 send,sendto,WSASend或WSASendTo
FD_OOB 套件口有外带数据消息通知 recv,recvfrom,WSARecv或WSARecvFrom
FD_ACCEPT 套接口有链接请求消息通知 accept或WSAAccept(错误码不能WSATRY_AGAIN)
FD_CONNECT 希望得到connect或多点join操作完成信息通知 无
FD_CLOSE(面向连接) 套接口关闭消息通知 无
FD_QOS 套接口QOS状态发生变化消息通知 WSAIoctl(SIO_GET_QOS)
FD_GROUP_QOS 保留 Reserved
FD_ROUTING_INTERFACE_CHANGE
特定方向的路由接口发生改变消息通知。 WSAIoctl(SIO_ROUTING_INTERFACE_CHANGE)
FD_ADDRESS_LIST_CHANGE
得到本地地址列表上套接口协议族发生改变通知。 WSAIoctl(SIO_ADDRESS_LIST_CHANGE)
(2)参数3-wMsg:为套接口事件设定1Event通知消息通常形式(WM_USER + n)
如 #define WM_USER_SERVER WM_USER+1
(3)参数2-bWnd指定系统通知消息wMsg的窗口句柄.函数若调用成功,
WSAAsyncSelect返回0;否则返回SOCKET_ERROR,这时可用WSAGetLastError来获取错误码.
事实上,成功发送一次消息,通知机制会暂停工作直到有重新激活消息通知机制到来.才可重新激活事件.
水平触发:FD_READ,FD_OOB和FD_ACCEPT 即重新激活,需要引发消息发送的条件.
边缘触发:FD_QOS,FD_GROUP_QOS等.
同一接口多次调用WSAAsyncSelect函数,只有最后一次生效.
因此:
WSAAsyncSelect(s, m_hWnd, WM_USER_SERVER, FD_READ),加上
WSAAsyncSelect(s, m_hWnd, WM_USER_SERVER, FD_CLOSE) 并不等于
WSAAsyncSelect(s, m_hWnd, WM_USER_SERVER, FD_READ | FD_CLOSE)
取消套接口上的I/O事件消息通知:、
WSAAsyncSelect(s, hWnd, 0, 0) // 把监听的消息清零
在MFC编程环境中,使用该消息处理函数
BEGIN_MESSAGE_MAP(CXXXDlg, CDialog)
//{{AFX_MSG_MAP(CXXXDlg)
........
//}}AFX_MSG_MAP
ON_MESSAGE(WM_USER_SERVER, OnServerMsg)
........
END_MESSAGE_MAP()
处理消息函数声明为:
afx_msg void OnSERVERMsg(WPARAM wparam,LPARAM lParam);
它定义为:
void CXXXDlg::OnServerMsg(WPARAM wParam,LPARAM lParam)
{
SOCKET sock = (SOCKET) wParam;
if(WSAGETSELECTERROR(lParam)){
ErrorProcess();
return;
}
switch(WSAGETSELECTEVENT(lParam)){
case FD_READ:
ReadDate(sock); // 读数据并进行相应处理
break;
case FD_CLOSE:
Finsish(sock); //套接口关闭工作
break;
default;
break;
}
}
其中函数会接受到两个参数wParam 和 lParam。
其中 wParam参数 指明网络事件套接口,多个套接口指定同一个用户消息,那么就需要根据wParam判断到底是哪个套接口待处理。
lParam参数包含两信息:底字指定发生网络事件,高字包含可能出现错误带代码。
另外 OnServerMsg函数中出现两个宏定义
#define WSAGETSELECTERROR(lParam) HIWORD(lParam)
#define WSAGETSELECTEVENT(lparam) LOWORD(lParam)
一般来讲,当用户 收到第一个FD_WRITE用户消息时就可以向套接口写数据,直到碰到WSAEWOULBALOCK错误时才
等待下一次FD_WRITE通知消息。
总结:WSAAsynSelect在MFC中使用流程
(1)、使用#define语句定义套接口网络事件设置用户消息值,一般为WM_USER+N形式。
(2)、调用WSAAsynsSelect函数,为套接口设定"网络事件-用户消息-消息接收窗体"的对应关系。
(3)、在消息接收窗体的代码的消息映射模块中,加入ON_MESSAGE宏,设定用户消息的处理函数。
(4)、编写用户处理函数,该函数应该首先使用WSAGETSELECTERROR宏判断是否有错误发生:
然后根据wParam值了解是哪一个套接口上发生了网络事件从而引起用户消息被发送:最后使用
WSAGETSELECTEVENT宏来了解所发生的网络事件,从而进行相应处理。