消息机制-WSAAsyncSelect

来源:互联网 发布:主流的数据分析工具 编辑:程序博客网 时间:2024/06/06 16:31

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宏来了解所发生的网络事件,从而进行相应处理。

原创粉丝点击