首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > 编程 >

【网络编程】之8、异步选择WSAAsyncSelect

2012-09-11 
【网络编程】之八、异步选择WSAAsyncSelect大家用这个模型,可以让应用程序在一个套接字上接收以windows消息为

【网络编程】之八、异步选择WSAAsyncSelect

   大家用这个模型,可以让应用程序在一个套接字上接收以windows消息为基础的网络事件通知。我们想要用这个操作,具体的做法就是我们建立一个套接字,然后调用WSAAsyncSelect函数, 也就是说,这个模型的核心就是我们的这个函数;

来看一下函数原型:

WSAAsyncSeltct(s, hwnd, WM_SOCKET, FD_CONNECT | FD_READ | FD_WRITE | FD_CLOSE);
应用程序可以在套接字s上,接收到有关连接,发送,接收以及套接字关闭的一系列通知了。


要注意的是:通过上面的函数原型我们可以看出来,要想使用我们的这个模型,必须要先调用CreateWindow函数来创建一个窗口,然后再为窗口提供一个窗口例程函数(WinProc);


这里要说的注意是:

当你有多个事件的时候,你一定要在套接字上一次注册,一旦你在这个套接字上允许了事件通知,那么以后除非你明确的调用closesocket命令或者由应用程序针对的那个套接字调用了WSAAsyncSelect,那么你就更改了注册的网络事件的类型了,否则的话事件通知就会永远有效。  上面函数你最后一个参数设置为0,效果相当于你停止在套接字上进行的所有网络事件通知。


还有就是你的应用程序针对一个套接字调用了WSAAsyncSelect,那么套接字会从“锁定”模式变成“非锁定”模式。    这样以后,会导致错误。     为了防止错误的产生,应用程序依赖于由WSAAsyncSelect的第三个参数指定的用户自定义窗口消息,来判断网络事件类型何时在套接字上发生,不能盲目的调用。


当你的程序调用WSAAsyncSelect成功后,会在和hWnd窗口句柄对应的窗口以windows消息的形式接受网络事件的通知。

看窗口消息如何定义:

#include<Windows.h>#include<tchar.h>#define MSGSIZE 1024#define WM_SOCKET WM_USER+100#pragma comment(lib, "ws2_32.lib")LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);int WINAPI WinMain( __in HINSTANCE hInstance, __in_opt HINSTANCE hPrevInstance, __in LPSTR lpCmdLine, __in int nShowCmd ){    TCHAR classname[] = "AsyncSelect";WNDCLASS wndclass;   //窗口类wndclass.style = CS_HREDRAW | CS_VREDRAW;//窗口类型wndclass.lpfnWndProc = WindowProc;//窗口处理函数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 = classname;//窗口类名为“窗口”//注册窗口类if (!RegisterClass(&wndclass)){MessageBox(NULL, "register class error", classname, MB_ICONERROR);return 0;}//创建窗口(窗口类名,窗口标题,窗口风格,坐标缺省, 有没有父窗口,有没有子窗口, 创建这个窗口的应用程序当前句柄,不适用)HWND hwnd = CreateWindow(classname, "AsyncSelect Model", WS_OVERLAPPEDWINDOW,CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL);//显示和更新ShowWindow(hwnd, nShowCmd);UpdateWindow(hwnd);MSG msg;//消息循环while (GetMessage(&msg, NULL, 0, 0)){TranslateMessage(&msg);DispatchMessage(&msg);}return msg.wParam;}LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam){WSADATA wsd;static SOCKET slisten;SOCKET sClient;SOCKADDR_IN local, client;int ret, iAddrsize = sizeof(client);char szMessage[MSGSIZE] = {0};switch (uMsg){case WM_DESTROY:{//退出清理closesocket(slisten);WSACleanup();PostQuitMessage(0);return 0;}case WM_CREATE:{//初始化WORD sockVersion = MAKEWORD(2, 0);WSAStartup(sockVersion, &wsd);//创建socketslisten = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);local.sin_family = AF_INET;local.sin_port = htons(8888);local.sin_addr.S_un.S_addr = htonl(INADDR_ANY);//绑定socketif(bind(slisten, (sockaddr*)&local, sizeof(local)) == SOCKET_ERROR){WSACleanup();return 0;}//监听socketif(listen(slisten, 5) == SOCKET_ERROR){WSACleanup();return 0;}//注册监听socket FD_ACCEPT事件,当socket有连接时,会发送WM_SOCKET消息给窗口WSAAsyncSelect(slisten, hwnd, WM_SOCKET, FD_ACCEPT);return 0;}case WM_SOCKET:{if (WSAGETSELECTERROR(lParam)){closesocket(wParam);break;}switch(WSAGETSELECTEVENT(lParam)){case FD_ACCEPT:{//接受sClient = accept(wParam, (sockaddr*)&client, &iAddrsize);//注册客户socket FD_READ和FD_CLOSE事件WSAAsyncSelect(sClient, hwnd, WM_SOCKET, FD_READ|FD_CLOSE);break;}case FD_READ:{//接受ret = recv(wParam, szMessage, MSGSIZE, 0);if (ret == 0 || ret == SOCKET_ERROR && WSAGetLastError() == WSAECONNRESET){closesocket(wParam);}else{//发送szMessage[ret] = '\0';send(wParam, szMessage, strlen(szMessage), 0);}break;}case FD_CLOSE:{closesocket(wParam);break;}default:{closesocket(wParam);break;}}}return 0;}return DefWindowProc(hwnd, uMsg, wParam, lParam);}


2012/9/2

jofranks于南昌

热点排行