• WSAAsyncSelect模型


    WSAAsyncSelect模型允许程序以windows消息的形式接受网络事件通知

    WSAAsyncSelect函数自动把套接字设为非阻塞模式,并且为套接字绑定一个窗口句柄,当有网络事件发生时,便向这个窗口发送消息

    int WSAAsyncSelect(
        SOCKET s, //套接字句柄
        HWND hWnd,//指定一个窗口句柄
        u_int wMsg,//网络事件到来的消息ID
        long lEvent//指定那些需要发送
    );

    FD_READ:接收对方发送的数据包

    FD_WRITE:继续发送数据

    FD_ACCEPT:有连接进入

    FD_CONNECT:连接对方主机

    FD_CLOSE:连接被关闭

    调用WSAAsyncSelect函数监听套接字

    ::WSAAsyncSelect(sListen,hWnd,WM_SOCKET,FD_ACCEPT|FD_CLOSE);

    成功调用后,应用程序开始以windows消息形式在窗口函数接受网络事件通知

    LRESULT CALLBACK WindowProc(HWND hWnd,
                                UINT uMsg,
                                WPARAM wParam,//发送网络事件的套接字句柄
                                LPARAM lParam//指定了发生的网络事件
    );

    下面是简单的TCP服务器程序,接受客户端的连接请求,打印出接收的数据。

    // WSATCPSERVER.cpp : 定义控制台应用程序的入口点。
    //
    
    #include "stdafx.h"
    #include <winsock2.h>
    #include <stdio.h> 
    #pragma comment(lib,"WS2_32")
    class CInitSock
     {
     public:
         CInitSock(BYTE minorVer=2,BYTE majorVer=2)
         {
             WSADATA wsaData;
             WORD sockVersion = MAKEWORD(minorVer,majorVer);
             if(::WSAStartup(sockVersion,&wsaData)!=0)
             {
                 exit(0);
             }
         }
         ~CInitSock()
         {
             ::WSACleanup();
         }
    }; 
    CInitSock initSock;
    LRESULT CALLBACK WindowProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam);
    int _tmain(int argc, _TCHAR* argv[])
    {
        char szClassName[] = "MainWClass";
        WNDCLASSEX wndclass;
        //用描述主窗口的参数填充WNDCLASSEX结构
        wndclass.cbSize = sizeof(wndclass);
        wndclass.style = CS_HREDRAW|CS_VREDRAW;
        wndclass.lpfnWndProc = WindowProc;
        wndclass.cbWndExtra = 0;
        wndclass.cbClsExtra = 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(hWnd == NULL)
        {
            ::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_un.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;//当GETMESSAGE返回0时结束
    }
    LRESULT 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);
                    }
                    break;
                case FD_WRITE:
                    {
    
                    }
                    break;
                case FD_READ:
                    {
                        char szText[1024]={0};
                        if(::recv(s,szText,1024,0) == -1)
                            ::closesocket(s);
                        else
                            printf("接收数据:%s",szText);
                    }
                    break;
                case FD_CLOSE:
                    {
                        ::closesocket(s);
                    }
                    break;
                }
            }
        case WM_DESTROY:
            ::PostQuitMessage(0);
            return 0;
        }
        //不处理的消息交给系统默认处理
        return ::DefWindowProc(hWnd,uMsg,wParam,lParam);
    }

    好多错误啊...首先 char 不能转成LPSZ  其次,WM_SOCKET不认,为什么......哎

  • 相关阅读:
    leetcode 2 Add Two Numbers
    log4j2 springboot 特点与使用方法
    数据类型和运算符
    初识Java
    《梦断代码》阅读笔记02
    《梦断代码》阅读笔记01
    场景调研
    【站立会议】第九天
    【站立会议】第八天
    【站立会议】第七天
  • 原文地址:https://www.cnblogs.com/xing901022/p/2720633.html
Copyright © 2020-2023  润新知