GetMssage()和WSAAsyncSelect()捕获网络事件消息

1、GetMessage()函数说明 编程

要从消息队列中取出消息,咱们须要调用GetMessage()函数,该函数的原型声明以下: 网络

BOOL GetMessage( socket

          LPMSG lpMsg,              // address of structure with message 函数

          HWND hWnd,                 // handle of window ui

          UINT wMsgFilterMin,       // first message spa

          UINT wMsgFilterMax        // last message 线程

); 指针

参数lpMsg指向一个消息(MSG)结构体,GetMessage从线程的消息队列中取出的消息信息将保存在该结构体对象中。 对象

参数hWnd指定接收属于哪个窗口的消息。一般咱们将其设置为NULL,用于接收属于调用线程的全部窗口的窗口消息。 接口

参数wMsgFilterMin指定要获取的消息的最小值,一般设置为0

参数wMsgFilterMax指定要获取的消息的最大值。若是wMsgFilterMinwMsgFilter Max都设置为0,则接收全部消息。

GetMessage函数接收到除WM_QUIT外的消息均返回非零值。对于WM_QUIT消息,该函数返回零。若是出现了错误,该函数返回-1,例如,当参数hWnd是无效的窗口句柄或lpMsg是无效的指针时。

 

2、WSAAsyncSelect()函数

 Windows消息机制编写socket客户端程序的方法。使用Windows消息机制编写socket程序主要有如下的好处:一是咱们能够将大部分的recv操做以及close操做放到消息处理函数里面,以利于代码的维护;二是当有数据可读的时候,本地程序会接到相应的消息,咱们能够在这时候读取数据。

WSAAsyncSelect(?)是Winsock提供的一个适合于Windows编程使用的函数,它容许在一个套接口上当发生特定的网络事件时,给Windows网络应用程序(窗口或对话框)发送一个消息(事件通知)。


这是一种winsock下的网络模型
例如: int iErrorCode=WSAAsyncSelect(mySocket.m_clientSocket,m_hWnd,WM_CLIENT_READ,FD_READ | FD_CLOSE);
这样一句代码,它告诉系统,如今我这个mySocket.m_clientSocket,只关注FD_READ | FD_CLOSE两个网络事件,一旦有这两个事件,我就会投递一个WM_CLIENT_READ的消息,这是一个自定义的消息
而后再到消息循环中对这个消息进行响应就行了

3、使用方法

使用方法1:

#pragma once 
#include <winsock.h>
#include <tchar.h>
#define PORT 5150
#define MSGSIZE 1024
#define WM_SOCKET WM_USER+0
#pragma comment(lib, "ws2_32.lib")
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
{
 static TCHAR szAppName[] = _T("AsyncSelect Model");
 HWND hwnd ;
 MSG msg ;
 WNDCLASS wndclass ;
 wndclass.style = CS_HREDRAW | CS_VREDRAW ;  //能够0
 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, // window class name

  TEXT ("AsyncSelect Model"), // 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);
 while (GetMessage(&msg, NULL, 0, 0) != 0)
 {
  TranslateMessage(&msg) ;
  DispatchMessage(&msg) ;
 }
 return msg.wParam;
}
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
 WSADATA wsd;
 static SOCKET sListen;
 SOCKET sClient;
 SOCKADDR_IN local, client;
 int ret, iAddrSize = sizeof(client);
 char szMessage[MSGSIZE];
 switch (message)
 {
 case WM_CREATE:
  // Initialize Windows Socket library

  WSAStartup(0x0202, &wsd);
  // Create listening socket

  sListen = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
  // Bind

  local.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
  local.sin_family = AF_INET;
  local.sin_port = htons(PORT);
  bind(sListen, (struct sockaddr *)&local, sizeof(local));
  // Listen

  listen(sListen, 3);
  // Associate listening socket with FD_ACCEPT event

  WSAAsyncSelect(sListen, hwnd, WM_SOCKET, FD_ACCEPT);
  return 0;
 case WM_DESTROY:
  closesocket(sListen);
  WSACleanup();
  PostQuitMessage(0);
  return 0;
 case WM_SOCKET:
  if (WSAGETSELECTERROR(lParam))
  {
   closesocket(wParam);
   break;
  }
  switch (WSAGETSELECTEVENT(lParam))
  {
  case FD_ACCEPT:
   // Accept a connection from client

   sClient = accept(wParam, (struct sockaddr *)&client, &iAddrSize);
   // Associate client socket with FD_READ and FD_CLOSE event

   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;
  }
  return 0;
 }
 return DefWindowProc(hwnd, message, wParam, lParam);
}

使用方法2:

        WNDCLASSEX theWndClass;
        theWndClass.cbSize = sizeof(theWndClass);
        theWndClass.style = 0;
        theWndClass.lpfnWndProc = &select_wndproc;
        theWndClass.cbClsExtra = 0;
        theWndClass.cbWndExtra = 0;
        theWndClass.hInstance = NULL;
        theWndClass.hIcon = NULL;
        theWndClass.hCursor = NULL;
        theWndClass.hbrBackground = NULL;
        theWndClass.lpszMenuName = NULL;
        theWndClass.lpszClassName = "ServerWindow";
        theWndClass.hIconSm = NULL;
       
        ATOM theWndAtom = ::RegisterClassEx(&theWndClass);  //注册一个窗口类
        Assert(theWndAtom != NULL);
        if (theWndAtom == NULL)
            ::exit(-1);
                
        sMsgWindow = ::CreateWindow(    "ServerWindow",  // Window class name
                                        "ServerWindow",  
                                        WS_POPUP, 
                                        0,          // x pos
                                        0,          // y pos
                                        CW_USEDEFAULT,  
                                        CW_USEDEFAULT,  
                                        NULL,     
                                        NULL,        
                                        NULL,           
                                        NULL);         
        Assert(sMsgWindow != NULL);
        if (sMsgWindow == NULL)
            ::exit(-1);
    }

    MSG theMessage; 

    //函数GetMessage 是 从调用线程的消息队列里取得一个消息并将其放于指定的结构
    UInt32 theErr = ::GetMessage(&theMessage, sMsgWindow, 0, 0);  //阻塞 一直等待消息到来才返回


    if (theErr > 0)
    {
        UInt32 theSelectErr = WSAGETSELECTERROR(theMessage.lParam);
        UInt32 theEvent = WSAGETSELECTEVENT(theMessage.lParam);
       
        req->er_handle = theMessage.wParam; 
        req->er_eventbits = EV_RE;          
        req->er_data = (void*)(theMessage.message);

        (void)::WSAAsyncSelect(req->er_handle, sMsgWindow, 0, 0); 

  return 0;                       }     else     {         //;     } }

相关文章
相关标签/搜索