《Windows网络与通信程序设计》读书笔记-----WSAAsyncSelect模型

WSAAsyncSelect模型

WSAAsyncSelect模型允许应用程序以Windows消息的接收网络事件通知。这个模型是为了适应Windows的消息驱动环境而设置的,现在许多对性能要求不高的网络应用程序都采用WSAAsyncSelect模型,MFC中的CSocket类也使用了它。

 

WSAAsyncSelect函数自动把套接字设为非阻塞模式,并且为套接字绑定一个窗口句柄和发送哪些通知码(FD_READ之类的)。当有网络事件发生时,便向这个窗口发送程序自定义的消息。


具体编程流程

1、         自定义一个与网络通知消息,用于通知WSAsyncSelect绑定中的窗口。

2、         创建一个窗口,用于WSAAsyncSelect绑定到指定的套接字。

3、         编写上述窗口的消息处理函数。在收到自定义网络通知消息后,提取出相应错误码和网络事(FD_ACCEPT、        FD_READ、FD_WRIET、FD_CLOSE),并作出相应的处理。


#define _WIN32_WINNT 0x0400   


#include<windows.h>
#include<cstdio>
#include"InitSocket.h"

//需要自定义一个消息
#define WM_SOCKET WM_USER+1

CInitSock initSock ; //进入main函数前已经进行了初始化

LONG CALLBACK WindowProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam) ;


int main(void)
{
	char szClassName[] = "MainWClass" ;
	WNDCLASSEX wndclass ;

	wndclass.cbSize = sizeof(wndclass) ;
	wndclass.style = CS_HREDRAW|CS_VREDRAW ;
	wndclass.lpfnWndProc = WindowProc ;
	wndclass.cbClsExtra = 0 ;
	wndclass.cbWndExtra = 0 ;
	wndclass.hInstance = NULL ;
	wndclass.hIcon = LoadIcon(NULL,IDI_APPLICATION) ;
	wndclass.hCursor = LoadCursor(NULL,IDC_ARROW) ;
	wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH) ;
	wndclass.lpszMenuName = NULL ;
	wndclass.lpszClassName = szClassName ;
	wndclass.hIconSm = NULL ;
	RegisterClassEx(&wndclass) ;

	//创建主窗口
	HWND hWnd = CreateWindowEx(
			0,
			szClassName,
			"",
			WS_OVERLAPPEDWINDOW,
			CW_USEDEFAULT,
			CW_USEDEFAULT,
			CW_USEDEFAULT,
			CW_USEDEFAULT,
			NULL,
			NULL,
			NULL,
			NULL 
			) ;

	if(NULL == hWnd)
	{
		MessageBox(NULL,"创建窗口出错!","error",MB_OK) ;
		return -1 ;
	} 

	USHORT nPort = 4567 ;
	SOCKET sListen = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP) ;

	sockaddr_in sin ;
	sin.sin_family = AF_INET ;
	sin.sin_port = htons(nPort) ;
	sin.sin_addr.s_addr = INADDR_ANY ;

	if(bind(sListen,(sockaddr*)&sin,sizeof(sin)) == SOCKET_ERROR)
	{
		printf("Failed bind()\n") ;
		return -1 ;
	}

	//将套接字设为窗口通知消息类型,自动将套接字设置为非阻塞模式
	WSAAsyncSelect(sListen,hWnd,WM_SOCKET,FD_ACCEPT|FD_CLOSE) ;
	listen(sListen,5) ;
	MSG msg ;

	while(GetMessage(&msg,NULL,0,0))
	{
		TranslateMessage(&msg) ;
		DispatchMessage(&msg) ;
	}

	return msg.wParam ;
}

LONG CALLBACK WindowProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam) 
{
	switch(uMsg)
	{
		case WM_SOCKET :
			{
				SOCKET s = wParam ;

				if(WSAGETSELECTERROR(lParam))
				{
					closesocket(s) ;
					return 0 ;
				}

				switch(WSAGETSELECTEVENT(lParam))
				{
					case FD_ACCEPT :
						{
							SOCKET client = accept(s,NULL,NULL) ;
							WSAAsyncSelect(client,hWnd,WM_SOCKET,FD_READ|FD_WRITE|FD_CLOSE) ;
							printf("接收一个连接\n") ;
						}
						break ;

					case FD_WRITE:
						break ;

					case FD_READ :
						{
							char szText[1024] =  {0} ;
							if(recv(s,szText,1024,0) == SOCKET_ERROR)
							{
								closesocket(s) ;
							}
							else
							{
								printf("接收数据:%s",szText) ;
							}
							break ;
						}

					case FD_CLOSE :
						{
							printf("关闭一个连接\n") ;
							closesocket(s);
						}
						break ;
				}
				return 0 ;
			}

		case WM_DESTROY :
			PostQuitMessage(0) ;
			return 0 ;
	}

	//将我们不处理的消息交给系统做默认处理
	return DefWindowProc(hWnd,uMsg,wParam,lParam) ;
}









  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值