Windows平台下WSAAsyncSelect 模型 服务器

#include   "stdafx.h"
#include   <winsock2.h>
#include   <iostream>
#include   "winuser.h"
#pragma   comment (   lib ,   "ws2_32.lib"   )

using   namespace   std ;


const   int   MAXDATASIZE     = 128;
const   int   BACKLOG         = 10;        //   指定等待连接队列的最大长度
const   int   WM_SOCKET       = (   WM_USER   + 1);
const   int   BUF_SIZE        = 256;

struct   _SOCKET_INFOMATION
{
        char       Buffer   [ MAXDATASIZE ];       //   发送和接收数据缓冲区
        WSABUF     DataBuf   ;                   //   定义发送和接收数据缓冲区,保护缓冲区在内的长度和内容
        SOCKET     Socket   ;                    //   与客户端进行通信的   socket
        _SOCKET_INFOMATION *   Next   ;          //   指向下一个 Socket   信息
};

typedef   _SOCKET_INFOMATION      SOCKET_INFOMATION ;
typedef   _SOCKET_INFOMATION   LPSOCKET_INFOMATION ;

SOCKET   Accept ;                         //   监听的 SOCKET
LPSOCKET_INFOMATION       SocketInfoList ;   //   所有 socket   的信息列表
char        buf [   MAXDATASIZE ];


BOOL                       CreateSocketInformation   (   SOCKET   s   );
LPSOCKET_INFOMATION        GetSocketInfomation (   SOCKET   s   );
HWND                       MakeWorkerWindow ();
LRESULT   CALLBACK         WindowProc (   HWND   hwdn ,   UINT   uMsg   ,   WPARAM   wParam ,   LPARAM   lParam   );

enum
{
        MAIN_RETURN_ERROR            =  -1,
        MAIN_RETURN_NORMAL           =   0,
};

//   创建   SOCKET
BOOL   CreateSocketInformation (   SOCKET   s   )
{
        LPSOCKET_INFOMATION   SI   ;
        //   SI   分配空间
        if ( (   SI   = ( LPSOCKET_INFOMATION )   GlobalAlloc (   GPTR   ,   sizeof   (   SOCKET_INFOMATION   ) ) ) ==   NULL   )
     {
             cout << "GlobalAlloc Failed with Error " <<   GetLastError ();
             return   FALSE   ;
     }

        //   向前插入法
        SI -> Socket          =   s ;
        SI -> Next            =   SocketInfoList ;
        SocketInfoList    =   SI   ;

        return   TRUE   ;
}

//   调用   GetSocketInfomation   来获取   Socket   的消息
LPSOCKET_INFOMATION        GetSocketInfomation (   SOCKET   s   )
{
        LPSOCKET_INFOMATION   si   =   SocketInfoList ;

        while (   si   )
     {
             if (   si   -> Socket   ==   s   )
                 return   si   ;

             si   =   si   -> Next ;
     }

        return   NULL   ;
}

HWND   MakeWorkerWindow ( )
{
        //   定义 registerClass   的注册窗口
        WNDCLASSEX   wndclass   ;
        char *     ProviderClass   =   "AsyncSelect" ;
        HWND     Window   ;

        wndclass . style   =   CS_HREDRAW   |   CS_VREDRAW ;
        wndclass . cbClsExtra   =   wndclass .   cbWndExtra   = 0;
        wndclass . hInstance   =   NULL ;
        wndclass . hIcon        =   LoadIcon (   NULL   ,   IDI_WARNING   );
        wndclass . hCursor      =   LoadCursor (   NULL ,   IDC_ARROW   );
        wndclass . hbrBackground   = ( HBRUSH   ) GetStockObject (   WHITE_BRUSH );
        wndclass . lpszMenuName     =   NULL ;
        wndclass . lpszClassName   =   ProviderClass ;
        wndclass . lpfnWndProc   = ( WNDPROC )   WindowProc ;

        if (   RegisterClassEx   ( & wndclass ) == 0 )
     {
             cout << "RegisterClass failed with error " <<   GetLastError ()<< endl   ;
             return   NULL   ;
     }

        if ( (   Window   =   CreateWindow (   ProviderClass ,   ""   ,   WS_OVERLAPPEDWINDOW   ,
                                   CW_USEDEFAULT ,   CW_USEDEFAULT   ,   CW_USEDEFAULT ,   CW_USEDEFAULT ,
                                       NULL ,   NULL   ,   NULL ,   NULL   ) ) ==   NULL   )
     {
             cout << "CreateWindow failed with error " <<   GetLastError ()<< endl   ;
             return   NULL   ;
     }

        return   Window   ;
}

LRESULT   CALLBACK   WindowProc (   HWND   hwdn ,   UINT   uMsg   ,   WPARAM   wParam   ,   LPARAM   lParam   )
{
        LPSOCKET_INFOMATION   SocketInfo   ;
        if (   uMsg   ==   WM_SOCKET   )
     {
             if (   WSAGETSELECTERROR   (   lParam   ) )
                 cout << "Socket failed with error with " <<   WSAGETSELECTERROR (   lParam   )<< endl ;
             else
          {
                 switch (   WSAGETSELECTEVENT   (   lParam ) )
              {
                 case   FD_ACCEPT   :
                   {
                           if (   Accept   =   accept (   wParam ,   NULL ,   NULL   ) ==   INVALID_SOCKET   )
                                cout << ""   << endl ;
                           else
                        {
                                CreateSocketInformation   (   Accept   );
                                WSAAsyncSelect (   Accept   ,   hwdn ,   WM_SOCKET   ,   FD_READ |   FD_WRITE | FD_CLOSE   );
                        }
                   }
                      break ;
                 case   FD_READ   :
                   {
                           SocketInfo   =   GetSocketInfomation   (   wParam   );
                           int   Recv      =   recv (   SocketInfo   -> Socket ,   buf ,   MAXDATASIZE   , 0 );
                           buf [ Recv   ]  =   '\0' ;
                           if (   Recv   > 0 )
                                cout << "Received:     %s " <<   endl ;
                   }
                      break ;
              }
          }

             return   0;
     }

        return   DefWindowProc   (   hwdn ,   uMsg ,   wParam   ,   lParam   );
}


int   main (   int   argc   ,   char *   argv [] )
{
        MSG       msg   ;
        DWORD     Ret   ;
        SOCKET   socketfd   ;
        HWND      Window   ;
     
        if ( (   Window   =   MakeWorkerWindow () ) ==   NULL   )
             return   0;

        WSADATA   wsaData   ;
        if (   WSAStartup   (   MAKEWORD ( 2, 2 ), &   wsaData   ) != 0 )
     {
             cout << "WSAStartup   无法初始化   !"   << endl   ;
             return   MAIN_RETURN_ERROR   ;
     }

        socketfd =   socket   (   AF_INET ,   SOCK_STREAM , 0 );
        WSAAsyncSelect (   socketfd   ,   Window ,   WM_SOCKET ,   FD_ACCEPT   );

        struct   sockaddr_in   my_addr ;
        my_addr . sin_family     =   AF_INET ;
        my_addr . sin_port       =   htons ( 9990 );     //   服务器端口号
        my_addr . sin_addr   . S_un .   S_addr   =   htonl   (   INADDR_ANY   );

        //   绑定
        int       retVal   ;
        retVal   =   bind   (   socketfd , (   const   struct   sockaddr   *)& my_addr   ,   sizeof (   struct   sockaddr_in   ) );
        if (   SOCKET_ERROR   ==   retVal   )
     {
             cout << "bind failed !"   << "   Reson: " <<   WSAGetLastError ()<< endl   ;
             closesocket (   socketfd   );
             WSACleanup ();
             return   -1;
     }

        //   监听
        retVal   =   listen   (   socketfd ,   BACKLOG   );
        if (   SOCKET_ERROR   ==   retVal   )
     {
             cout << "listen failed !"   << " Reson:" <<   WSAGetLastError ()<< endl   ;
             closesocket (   socketfd   );
             WSACleanup ();
             return   -1;
     }

        while (   Ret   =   GetMessage ( &   msg ,   NULL   , 0, 0 ) )
     {
             if (   Ret   == -1 )
          {
                 cout << "GetMessage failed with error at " <<   GetLastError ()<< endl   ;
                 return   0;
          }

             TranslateMessage ( & msg   );
             DispatchMessage ( & msg   );
     }

        system ( "pause"   );
        return   0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值