博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
WSAAsyncSelect模型
阅读量:4993 次
发布时间:2019-06-12

本文共 4833 字,大约阅读时间需要 16 分钟。

WSAAsyncSelect模型是Windows Socket的一个异步I/O模型。
利用该模型可以接收以Windows消息为基础的socket网络事件。
Windows sockets应用程序在创建套接字后,调用WSAAsyncSelect函数注册感兴趣的网络事件,当该事件发生时Windows窗口收到消息,应用程序就可以对接收到的网络事件进行处理。
 
WSAAsyncSelect是select模型的异步版本。在应用程序使用select函数时会发生阻塞现象。可以通过select的timeout参数设置阻塞的时间。在设置的时间内,select函数等待,直到一个或多个Socket满足可读或可写的条件。
 

而WSAAsyncSelect是非阻塞的。Windows sockets程序在调用recv之前,调用WSAAsyncSelect注册网络事件。WSAAsyncSelect函数立即返回。当系统中数据准备好时,会向应用程序发送消息。此此消息的处理函数中可以调用recv接收数据。

 WSAAsyncSelect模型与select模型的相同点是它们都可以对多个套接字进行管理。但它们也有不小的区别。

首先WSAAsyncSelect模型是异步的,且通知方式不同。

更重要的一点是:WSAAsyncSelect模型应用在基于消息的Windows环境下,使用该模型时必须创建窗口,而select模型可以广泛应用在Unix系统,使用该模型不需要创建窗口。

最后一点区别:应用程序在调用WSAAsyncSelect函数后,套接字就被设置为非阻塞状态。而使用select函数不改变套接字的工作方式。

#define _WINSOCK_DEPRECATED_NO_WARNINGS#include 
#include
#include
#include
#include
#pragma comment(lib, "ws2_32.lib")#define WM_SOCKET (WM_USER + 1)#define MAXDATASIZE 1024LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);//回调函数int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow){ static TCHAR szAppName[] = TEXT("WSAAsyncSelect"); 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; } //直接发送WM_CREATE消息 hwnd = CreateWindow(szAppName, // window class name TEXT("WSAAsyncSelect"), // window caption WS_OVERLAPPEDWINDOW, // window style CW_USEDEFAULT, // initial x position CW_USEDEFAULT, // initial y position CW_USEDEFAULT, // initial x size CW_USEDEFAULT, // initial y size NULL, // parent window handle NULL, // window menu handle hInstance, // program instance handle NULL); // creation parameters //到此,窗口在内存已经存在 ShowWindow(hwnd, iCmdShow); UpdateWindow(hwnd); //-----------Socket------------ WSADATA wsaData; SOCKET sServer; if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) { return -1; } sServer = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (sServer == INVALID_SOCKET) { return -1; } SOCKADDR_IN addrServ; addrServ.sin_family = AF_INET; addrServ.sin_port = htons(9999); addrServ.sin_addr.S_un.S_addr = htonl(INADDR_ANY); if (bind(sServer, (const struct sockaddr*)&addrServ, sizeof(SOCKADDR_IN)) == SOCKET_ERROR) { return -1; } if (listen(sServer, 5) == SOCKET_ERROR) { return -1; } WSAAsyncSelect(sServer, hwnd, WM_SOCKET, FD_ACCEPT | FD_CLOSE); while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg);//键盘消息转换 DispatchMessage(&msg);//把消息返回操作系统,系统callback } closesocket(sServer); WSACleanup(); return msg.wParam;}LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) //回调函数,操作系统调用{ HDC hdc; PAINTSTRUCT ps; static char buf[MAXDATASIZE], temp[MAXDATASIZE]; static char szDateTime[50]; SOCKET sClient; SYSTEMTIME st; static SOCKADDR_IN addrClient; switch (message) { case WM_CREATE://可以进行动态链接库dll的载入 return 0; case WM_PAINT: hdc = BeginPaint(hwnd, &ps); TextOutA(hdc, 0, 0, buf, strlen(buf)); EndPaint(hwnd, &ps); return 0; case WM_SOCKET: { if (WSAGETSELECTERROR(lParam)) { closesocket(wParam); return -1; } switch (WSAGETSELECTEVENT(lParam)) { case FD_ACCEPT: if ((sClient = accept(wParam, (struct sockaddr *)&addrClient, NULL)) == INVALID_SOCKET) { closesocket(sClient); break; } //MessageBoxA(NULL, inet_ntoa(addrClient.sin_addr), "IP", 0); WSAAsyncSelect(sClient, hwnd, WM_SOCKET, FD_READ | FD_WRITE | FD_CLOSE); break; case FD_READ: GetLocalTime(&st); memset(szDateTime, 0, sizeof(szDateTime)); sprintf(szDateTime, "%4d-%02d-%02d %02d:%02d:%02d", st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond); memset(temp, 0, sizeof(temp)); if (recv(wParam, temp, MAXDATASIZE, 0) == SOCKET_ERROR) { return -1; } //sprintf(buf, "%s, Recv From Client [%s:%d] :%s\n", szDateTime, inet_ntoa(addrClient.sin_addr), addrClient.sin_port, temp); sprintf(buf, "%s, Recv From Client:%s\n", szDateTime, temp); if (send(wParam, temp, strlen(temp), 0) == SOCKET_ERROR) { return -1; } InvalidateRect(hwnd, NULL, TRUE); UpdateWindow(hwnd); break; case FD_CLOSE: closesocket(wParam); break; } return 0; } case WM_DESTROY: PostQuitMessage(0); return 0; } return DefWindowProc(hwnd, message, wParam, lParam);//默认系统消息处理}

转载于:https://www.cnblogs.com/lgh1992314/p/6616385.html

你可能感兴趣的文章
python网络编程基础
查看>>
selenium+maven+testng+IDEA+git自动化测试环境搭建(二)
查看>>
Mini2440 UART原理及使用
查看>>
Linux学习第六篇之文件处理命令ln(链接命令)
查看>>
thinkphp5 tp5 七牛云 上传图片
查看>>
VM下Linux网卡丢失(pcnet32 device eth0 does not seem to be ...)解决方案
查看>>
第一阶段意见汇总以及改进
查看>>
再说virtual
查看>>
随笔:技术流可以这样写博客
查看>>
[优化]JavaScript 格式化带有占位符字符串
查看>>
打JAR包
查看>>
大图轮播
查看>>
UNIX环境高级编程读书笔记
查看>>
java awt 乱码问题
查看>>
矩阵中的路径
查看>>
unity回调函数范例
查看>>
linux下给php安装curl、gd(ubuntu)
查看>>
Java自带的Logger使用-代码摘要
查看>>
Java设计模式系列 — 构造器模式
查看>>
MySQL执行计划explain的key_len解析
查看>>