WSAAsyncSelect模型是winsock编程模型的一种,它提供了socket异步编程的方便,其实现是基于Windows消息机制的,最主要的就是下面这个函数:

 int PASCAL FAR WSAAsyncSelect (SOCKET s,HWND hWnd,unsigned int wMsg,long lEvent);

s 标识一个需要事件通知的套接口的描述符.
hWnd 标识一个在网络事件发生时需要接收消息的窗口句柄.
wMsg 在网络事件发生时要接收的消息.
lEvent位屏蔽码,用于指明应用程序感兴趣的网络事件集合.

1、服务器端

因此首先需要自定义一个消息

#define WM_SOCKET WM_USER + 1

并定义消息处理函数,以及做映射

 // 声明消息处理函数
afx_msg LRESULT OnSocket(WPARAM wParam, LPARAM lParam);
// 映射
ON_MESSAGE(WM_SOCKET,OnSocket)

初始化socket

 BOOL CSocketSeverDlg::InitNetwork()
{
WSADATA wsaData;
//初始化TCP协议
BOOL ret = WSAStartup(MAKEWORD(,), &wsaData);
if(ret != )
{
MessageBox("初始化网络协议失败!");
return FALSE;
}
//创建服务器端套接字
ServerSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if(ServerSock == INVALID_SOCKET)
{
MessageBox("创建套接字失败!");
closesocket(ServerSock);
WSACleanup();
return FALSE;
}
//绑定到本地一个端口上
sockaddr_in localaddr;
localaddr.sin_family = AF_INET;
localaddr.sin_port = htons(); file://端口号不要与其他应用程序冲突
localaddr.sin_addr.s_addr = ;
if(SOCKET_ERROR = = bind(ServerSock ,(struct sockaddr*)&localaddr,sizeof(sockaddr)))
{
MessageBox("绑定地址失败!");
closesocket(ServerSock);
WSACleanup();
return FALSE;
}
//将SeverSock设置为异步非阻塞模式,并为它注册各种网络异步事件,其 中 m_hWnd
//为应用程序的主对话框或主窗口的句柄
if(SOCKET_ERROR == WSAAsyncSelect(ServerSock, m_hWnd, WM_SOCKET,
FD_ACCEPT | FD_CLOSE | FD_READ | FD_WRITE))
{
MessageBox("注册网络异步事件失败!");
WSACleanup();
return FALSE;
}
//设置侦听模式
listen(ServerSock, );
return TRUE;
}

定义自定义消息处理函数

 LRESULT CSocketSeverDlg::OnSocket(WPARAM wParam, LPARAM lParam)
{
//调用Winsock API函数,得到网络事件类型
int iEvent = WSAGETSELECTEVENT(lParam);
//调用Winsock API函数,得到发生此事件的客户端套接字
SOCKET CurSock= (SOCKET)wParam;
switch(iEvent)
{
case FD_ACCEPT:
//客户端连接请求事件
OnAccept(CurSock);
break;
case FD_CLOSE:
//客户端断开事件:
OnClose(CurSock);
break;
case FD_READ:
//网络数据包到达事件
OnReceive(CurSock);
break;
case FD_WRITE:
//发送网络数据事件
OnSend(CurSock);
break;
default: break;
}
return ;
}

2、客户端

用同样的方法建立一个客户端应用程序,初始化网络部分,不需要将套接字设置为监听模式。注册网络事件时没有FD_ACCEPT,但增加了FD_CONNECT事件,因此没有OnAccept函数,但增加了OnConnect函数,向服务器发出连接请求时,使用connect函数,连接成功后,会相应到OnConnect函数中。下面是OnConnect函数的定义,传进来的参数是客户端Socket和服务器端发回来的连接是否成功的标识。

 void CSocketClientDlg::OnConnect(SOCKET CurSock, int error)
{
if( == error)
{
if(CurSock == ClientSock)
{
MessageBox("连接成功!");
}
}
}

定义OnReceive函数,处理网络数据到达事件

定义OnSend函数,处理发送网络数据事件

定义OnClose函数,处理服务器socket关闭事件

以上就是用基于windows消息机制的异步I/O模型实现服务器/客户端应用程序的基本方法。

3、我的疑问

我有一点不是很明白,那就是这个发送网络数据事件是什么意思?什么时候发生?是我们使用send函数发送数据时发生么,

未完待续。。。

最新文章

  1. jQuery动画
  2. 725C
  3. Linux下内存占用和CPU占用的计算
  4. 利用HTML5云存储实现模拟对比投票效果
  5. jQuery基础知识— 获得内容和属性
  6. Ubuntu14.04LST 安装Oracle SQL Developer 4.0.2
  7. solr4.5分组查询、统计功能介绍
  8. SICP 锻炼 (2.15)解决摘要:深入思考间隔误差
  9. 预览github项目的html文件新方法
  10. 【Vue】详解Vue生命周期
  11. jenkins构建一个maven项目[五]
  12. ADS协议变量配置界面
  13. layui之确认框
  14. 删除Apache服务的命令
  15. [转]Ubuntu16.04下ralink rt3290驱动安装
  16. mpVue小程序全栈开发
  17. JS中的函数节流throttle详解和优化
  18. Codeforces 833A The Meaningless Game - 数论 - 牛顿迭代法 - 二分法
  19. 水仙花在python3在pycharm的实现
  20. vue实现按需加载(懒加载)

热门文章

  1. logback.xml 文件
  2. 〖Android〗/system/etc/event-log-tags
  3. java 多态的好处
  4. linux 系统文件的特殊权限
  5. Eclipse调试cas server 3.5.2.1
  6. 线代: N阶行列式
  7. 打开Activity时,不自动显示(弹出)虚拟键盘
  8. hadoop编译map/reduce时的问题
  9. 学会快速装系统 图解硬盘分区软件Norton Ghost使用
  10. Android ——真机调试