WSAAsyncSelect模型

        WSAAsyncSelect模型允许应用程序以Windows消息的方式接收网络事件通知。许多对性能要求不高的网络应用程序都采用WSAAsyncSelect模型,MFC的CSocket类也使用了它。

        WSAAsyncSelect自动把套接字设为非阻塞模式,并且为套接字绑定一个窗口句柄,当有网络事件发生时,便向这个窗口发送消息。

        intWSAAsyncSelect(

        SOCKET s,                  //需要设置的套接字句柄

        HWND  hWnd,     //指定一个窗口句柄, 套接字的通知消息将被发到此窗口中

       u_int    wMsg,     //网络事件到来的ID,可以在WM_USER以上数值中任意指定一个值

       long    IEvent     //指定哪些通知码需要发送

                                 //FD_READ可以读套接字

                                 //FD_WRITE 可以写套接字

                                //FD_ACCEPT 监听套接字有连接接入

                               //FD_CONNET  如果套接字连接对方主机,连接完成后会收到这个通知码

                              //FD_CLOSE 检测到套接字对应的连接被关闭

)

       回传过来的消息类型与注册的wMsg相同,wParam等于套接字句柄,lParam通过WSAGETSELECTEVENT转义后就是FD_READ,FD_WRITE,FD_ACCEPT,FD_CONNET,FD_CLOSE

        代码如下:

        新建一个基于MFC对话框的工程,工程名为test,然后在testDlg.h中定义      

#include "winsock2.h"
#pragma comment(lib, "WS2_32")
#define WM_SOCKET (WM_USER+1) 
同时在该文件中加入一个自定义消息处理函数

afx_msg LRESULT OnSocketMsg(WPARAM wParam,LPARAM lParam);
在testDlg.cpp中定义

ON_MESSAGE(WM_SOCKET,OnSocketMsg)

在OnInitDialog中加入自己的初始化代码

// TODO: 在此添加额外的初始化代码

	WSADATA wsaData;
	WORD sockVersion = MAKEWORD(2, 2);
	if(WSAStartup(sockVersion, &wsaData) != 0)
	{
		return 0;
	}
	USHORT nPort=4567;
	SOCKET s=socket(AF_INET,SOCK_STREAM,0);
	sockaddr_in sin;
	sin.sin_family=AF_INET;
	sin.sin_port=ntohs(nPort);
	sin.sin_addr.S_un.S_addr=INADDR_ANY;
	if(bind(s,(sockaddr*)&sin,sizeof(sin))==SOCKET_ERROR)
	{
		DWORD error=GetLastError();
		return TRUE;
	}

	WSAAsyncSelect(s,m_hWnd,WM_SOCKET,FD_ACCEPT|FD_CLOSE);
	listen(s,5);

添加自定义消息函数的处理:

LRESULT CtestDlg::OnSocketMsg(WPARAM wParam,LPARAM lParam)
{
	SOCKET s=wParam;
	CString strContent;
	if(WSAGETSELECTERROR(lParam))
	{
		closesocket(s);
		return false;
	}
	switch(WSAGETSELECTEVENT(lParam))
	{
	case FD_ACCEPT://检测到有套接字连上来
		{
			SOCKET client=accept(s,NULL,NULL);
			WSAAsyncSelect(client,m_hWnd,WM_SOCKET,FD_READ|FD_WRITE|FD_CLOSE);
			CString strContent;
			GetDlgItemText(IDC_EDIT1,strContent);
			if(!strContent.IsEmpty())
			{
				strContent+="\r\n";
			}			
			strContent+="有客户端连上来了";
			SetDlgItemText(IDC_EDIT1,strContent);//将内容显示到Edit控件
		}
		break;
	case FD_WRITE:
		{
		}
		break;
	case FD_READ:
		{
			char szText[1024]={0};
			if(recv(s,szText,1024,0)==-1)
				closesocket(s);
			else
			{				
				GetDlgItemText(IDC_EDIT1,strContent);
				if(!strContent.IsEmpty())
				{
					strContent+="\r\n";
				}
				CString strTemp;
				strTemp.Format("%s",szText);
				strContent+=strTemp;
				SetDlgItemText(IDC_EDIT1,strContent);//将内容显示到Edit控件中
			}
		}
		break;
	case FD_CLOSE:
		{
			closesocket(s);
			GetDlgItemText(IDC_EDIT1,strContent);
			if(!strContent.IsEmpty())
			{
				strContent+="\r\n";
			}			
			strContent+="有客户端断开了";
			SetDlgItemText(IDC_EDIT1,strContent);//将内容显示到Edit控件中
		}
		break;
	}
	return true;
}

对WM_DESTROY消息处理,清理套接字库

void CtestDlg::OnDestroy()
{
	CDialog::OnDestroy();
	WSACleanup();
	// TODO: 在此处添加消息处理程序代码
}




  • 6
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
WSAAsyncSelect模型是一种Windows Socket编程模型,它采用异步通信方式,可以实现异步接收和发送数据。其工作原理如下: 1. 在使用WSAAsyncSelect模型之前,需要调用WSAStartup函数初始化Winsock库。 2. 调用socket函数创建一个套接字,并使用WSAAsyncSelect函数注册一个异步消息事件。该函数指定了套接字、窗口句柄、消息类型等参数。 3. 当套接字事件发生时,Winsock库会向指定的窗口发送一个异步消息,通知程序有数据可读或可写。 4. 在窗口过程中,根据接收到的消息类型,调用recv或send函数进行数据的异步接收或发送。 WSAAsyncSelect模型的优点是: 1. 异步通信方式,可以实现在数据传输过程中,程序不被阻塞,提高程序的执行效率。 2. 采用事件驱动方式,程序可以响应多个套接字事件,实现多路复用。 3. 可以通过窗口消息机制,实现程序间的通信。 WSAAsyncSelect模型的缺点是: 1. 编程复杂度较高,需要熟悉Windows消息机制。 2. 在多线程编程中,需要实现线程之间的消息传递,程序设计和调试难度较大。 3. 需要频繁地调用recv和send函数进行数据的异步接收和发送,程序运行效率较低。 总的来说,WSAAsyncSelect模型适用于需要同时处理多个套接字事件的程序,例如服务器程序,但是在编程复杂度和程序执行效率方面,都需要付出一定的代价。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值