WSAAsyncSelect模型分析

发布于 2021-11-18 10:50:46 字数 3968 浏览 755 评论 1

#include<winsock2.h>
#include<windows.h>
#include<stdio.h>
#pragma comment (lib,"ws2_32.lib")
#define PORT 8888
#define ADDR "127.0.0.1"
//char ADDR[15];
#define MSGSIZE 1024
#define WM_SOCKET WM_USER+1 
#define serecho "get it"

LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,PSTR szCmdLine,int iCmdShow)
{
	//printf("server IP is : ");
	//gets(ADDR);
	static TCHAR szAppName[]=L"TCPAsyn server f_ck";
	HWND hwnd;
	MSG msg;
	WNDCLASS wndclass;
	wndclass.style=CS_HREDRAW	|CS_VREDRAW;
	wndclass.lpfnWndProc=WndProc;
	wndclass.cbClsExtra=0;
	wndclass.cbWndExtra=0;
	wndclass.hInstance=hInstance;
	wndclass.hIcon=LoadIcon(NULL,IDI_APPLICATION);
	wndclass.hCursor=LoadCursor(NULL,IDC_ARROW);
	wndclass.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH);
	wndclass.lpszMenuName=NULL;
	wndclass.lpszClassName=szAppName;
	if(!RegisterClass(&wndclass))
	{
		MessageBox(NULL,TEXT("this program requires windows NT"),szAppName,MB_ICONERROR);
		return 0;
	}
	hwnd=CreateWindow(
		szAppName,
		TEXT("WHAT A F_CK TCPAsyn TITLE"),
		WS_OVERLAPPEDWINDOW,
		100,100,800,600,
		NULL,NULL,hInstance,NULL	
		);
	ShowWindow(hwnd,iCmdShow);
	UpdateWindow(hwnd);
	while(GetMessage(&msg,NULL,0,0))
	{
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}
	return msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hwnd,UINT message,WPARAM wparam,LPARAM lparam)
{
	WSADATA wsadata;
	SOCKET listensocket,acceptsocket;
	SOCKADDR_IN seraddr,cliaddr;
	int nret;
	int cliaddrsize=sizeof(cliaddr);
	char szmessage[MSGSIZE];
	switch(message)
	{
	case WM_CREATE:
		if(WSAStartup(MAKEWORD(2,2),&wsadata)!=0)
		{
			MessageBox(NULL,TEXT("WSAStartup() failed"),TEXT("wrong"),MB_OK);
			return 0;
		}
		if((listensocket=WSASocket(AF_INET,SOCK_STREAM,0,NULL,0,WSA_FLAG_OVERLAPPED))==INVALID_SOCKET)
	{
		MessageBox(NULL,TEXT("create socket failed "),TEXT("wrong"),MB_OK);
		WSACleanup();
		return 0;
	}
		seraddr.sin_family=AF_INET;
		seraddr.sin_addr.s_addr=inet_addr(ADDR);
		seraddr.sin_port=htons(PORT);
		if(bind(listensocket,(SOCKADDR*)&seraddr,sizeof(seraddr))==SOCKET_ERROR)
	{
		MessageBox(NULL,TEXT("bind failed"),TEXT("wrong"),MB_OK);
		closesocket(listensocket);
		WSACleanup();
		return 0;
	}
	if(listen(listensocket,5))//无错误返回0,有错返回SOCKET ERROR
	{
		MessageBox(NULL,TEXT("listen failed"),TEXT("wrong"),MB_OK);
		closesocket(listensocket);
		WSACleanup();
		return 0;
	}
	if(WSAAsyncSelect(listensocket,hwnd,WM_SOCKET,FD_ACCEPT|FD_READ|FD_WRITE)==SOCKET_ERROR)//WM_SOCKET it's here!!
	{
		MessageBox(NULL,TEXT("WSAAsyncSelect() failed"),TEXT("wrong"),MB_OK);
		closesocket(listensocket);
		WSACleanup();
		return 0;
	}
	return 0;
	case WM_DESTROY:
		//closesocket(listensocket);
		WSACleanup();
		PostQuitMessage(0);
		return 0;
	case WM_SOCKET:
		if(WSAGETSELECTERROR(lparam))
		{
			closesocket(wparam);
			break;
		}
	switch(WSAGETSELECTEVENT(lparam))
	{
		case FD_ACCEPT:
		if((acceptsocket=accept(wparam,(SOCKADDR*)&cliaddr,&cliaddrsize))==SOCKET_ERROR)
		{
			MessageBox(NULL,TEXT("accept failed"),TEXT("wrong"),MB_OK);
			 
			WSACleanup();
			return 0;
		}
		if(WSAAsyncSelect(acceptsocket,hwnd,WM_SOCKET,FD_READ|FD_CLOSE|FD_WRITE)==SOCKET_ERROR)
		{
		MessageBox(NULL,TEXT("WSAAsyncSelect() failed"),TEXT("wrong"),MB_OK);
		
		WSACleanup();
		return 0;
		}
		break;
	case FD_READ:
		if((nret=recv(wparam,szmessage,MSGSIZE,0))==SOCKET_ERROR)
		{
			closesocket(wparam);
		}
		else 
		{
			send(wparam,serecho,strlen(serecho),0);
			//szmessage[nret]='';
			//send(wparam,szmessage,strlen(szmessage),0);
		}
		break;
	case FD_CLOSE:
		closesocket(wparam);
		break;
	}
	return 0;
}
return DefWindowProc(hwnd,message,wparam,lparam);
}

这是我的TCP服务器端的程序,采用WSAAsyncSelect模型,但是我不明白select模型如何就实现非阻塞通信了?在代码上是怎么体现的?和一个普通的服务器端程序相比又有什么不同?

 

 

 

fdfd

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

如日中天 2021-11-19 12:16:05

      非阻塞 只是看用的 套接字对象 类型. 你用阻塞的socket就阻塞, 用设置非阻塞选项的socket 就非阻塞.
      select只是搭配非阻塞套接字的 模型而已, 他一次能等待多个套接字. 不等待的套接字模型是不存在, 想想就知道. 你肯定要等网络来数据 是吧. 呵呵. 
      epoll等待的效率就更高了. iocp则是系统级的线程池回调. 都是搭配非阻塞socket的好模型.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文