WSAAsyncSelect详细使用说明
### WSAAsyncSelect 的详细使用说明 #### 一、概述 `WSAAsyncSelect` 是一个基于 Windows 消息机制的异步 I/O 模型函数,它允许开发者为特定的网络事件指定系统通知信息。这使得应用程序能够在接收到网络事件(如连接建立或数据可读)时通过窗口消息来接收通知,而无需频繁地轮询网络套接字的状态。这对于提高程序效率和响应性非常有用。 #### 二、函数原型与参数说明 ```c int WSAAsyncSelect( SOCKET s, // 套接字句柄 HWND hWnd, // 窗口句柄 unsigned int wMsg, // 消息标识 long lEvent // 事件掩码 ); ``` - **参数解析:** - `SOCKET s`: 指定用于注册事件的通知的套接字。 - `HWND hWnd`: 接收通知消息的窗口句柄。当有网络事件发生时,系统会向该窗口发送指定的消息。 - `unsigned int wMsg`: 当指定的网络事件发生时,系统发送到 `hWnd` 的消息值。通常,这个值是在 `WM_USER` 基础上自定义的。 - `long lEvent`: 事件掩码,指定希望接收哪些类型的网络事件的通知。它是由多个事件标志组合而成的。 #### 三、事件掩码详解 `lEvent` 参数指定了希望接收哪些类型的网络事件的通知,常见的事件类型包括: 1. **FD_READ**: 表示数据可读事件,即可以调用 `recv`, `recvfrom`, `WSARecv`, `WSARecvFrom` 函数进行读取操作。 2. **FD_CLOSE**: 表示套接字关闭事件,即套接字已关闭或被另一端关闭。 3. **FD_WRITE**: 表示数据可写事件,即可以调用 `send`, `sendto`, `WSASend`, `WSASendTo` 函数进行发送操作。 4. **FD_OOB**: 表示带外数据到达事件,即可以调用 `recv`, `recvfrom`, `WSARecv`, `WSARecvFrom` 函数处理带外数据。 5. **FD_ACCEPT**: 表示连接请求到达事件,即可以调用 `accept` 或 `WSAAccept` 函数接受新的连接。 6. **FD_CONNECT**: 表示连接建立完成事件,即调用 `connect` 后连接成功建立。 7. **FD_QOS**: 表示 QoS (Quality of Service) 状态改变事件,可以通过 `WSAIoctl(SIO_GET_QOS)` 获取 QoS 信息。 8. **FD_GROUP_QOS**: 预留,未定义。 9. **FD_ROUTING_INTERFACE_CHANGE**: 表示路由接口变化事件,可以通过 `WSAIoctl(SIO_ROUTING_INTERFACE_CHANGE)` 获取路由信息的变化。 10. **FD_ADDRESS_LIST_CHANGE**: 表示地址列表变化事件,可以通过 `WSAIoctl(SIO_ADDRESS_LIST_CHANGE)` 获取地址列表的变化。 #### 四、示例代码分析 在实际应用中,我们可以通过以下方式实现对网络事件的监听: 1. **注册事件:** ```c SOCKET s; HWND hWnd; // 注册 FD_READ 和 FD_CLOSE 两个事件 if (WSAAsyncSelect(s, hWnd, WM_USER + 1, FD_READ | FD_CLOSE) == SOCKET_ERROR) { DWORD error = WSAGetLastError(); // 处理错误 } ``` 2. **处理消息:** ```c BEGIN_MESSAGE_MAP(CXXXDlg, CDialog) //{{AFX_MSG_MAP(CXXXDlg) ON_MESSAGE(WM_USER + 1, OnServerMsg) //}}AFX_MSG_MAP END_MESSAGE_MAP() void CXXXDlg::OnServerMsg(WPARAM wParam, LPARAM lParam) { SOCKET sock = (SOCKET)wParam; if (WSAGETSELECTERROR(lParam)) { ErrorProcess(); return; } switch (WSAGETSELECTEVENT(lParam)) { case FD_READ: ReadData(sock); // 处理读事件 break; case FD_CLOSE: Finish(sock); // 处理关闭事件 break; default: // 其他事件处理 break; } } ``` - **wParam**: 指示触发事件的套接字。 - **lParam**: 包含事件的详细信息,其中 `WSAGETSELECTERROR` 可以用来检查是否有错误发生,`WSAGETSELECTEVENT` 用来获取具体的事件类型。 #### 五、注意事项 - 在同一个套接字上多次调用 `WSAAsyncSelect` 时,只有最后一次的设置是有效的。 - 若要取消对某个套接字的事件监听,可以调用 `WSAAsyncSelect` 并将 `wMsg` 和 `lEvent` 设置为 0。 - 使用 MFC 时,可以通过消息映射机制来处理接收到的消息。 - 在处理 FD_WRITE 事件时,如果尝试写入的数据量大于套接字缓冲区所能容纳的最大值,可能不会立即收到写入完成的通知。此时需要通过 `WSAGETSELECTERROR` 来判断是否有错误发生。 通过以上介绍,我们可以了解到 `WSAAsyncSelect` 提供了一种高效且灵活的方式来处理网络套接字的事件通知,有助于开发出更具有响应性的网络应用程序。
函数定义
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
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)
剩余5页未读,继续阅读
- 粉丝: 0
- 资源: 7
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助