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: 在此处添加消息处理程序代码
}




评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值