频道栏目
首页 > 程序开发 > 软件开发 > 其他 > 正文
WSAAsyncSelect应用
2012-06-06 10:54:10           
收藏   我要投稿

#ifndef Unit2H  
#define Unit2H  
//---------------------------------------------------------------------------  
#include <vcl.h>  
#include <winsock2.h>  
#include <cassert>  
#include <map>  
#include <list>  
#include "Datastruct.h"  
using namespace std; 
 
#pragma comment(lib,"ws2_32.lib")  
 
namespace Async 

  #ifndef __BORLANDC__  
  typedef void  (*receive_handler)(Data *pd); 
  typedef void  (*error_handler)(int errcode); 
  typedef void  (*close_handler)(SOCKET s); 
  typedef void  (*connect_handler)(SOCKET s); 
  #else  
  typedef void __fastcall (__closure* receive_handler)(Data *pd); 
  typedef void __fastcall (__closure *error_handler)(int errcode); 
  typedef void __fastcall (__closure *close_handler)(SOCKET s); 
  typedef void __fastcall (__closure *connect_handler)(SOCKET s); 
  #endif  
   
  class AsyncSocket 
  { 
     static const int  WM_SOCKET=WM_USER+109; 
     static map<SOCKET,list<Data*> > sMapOfComm; 
     static WNDPROC sOldProc; 
     static bool bWrite;//可写  
      
     static receive_handler sReceviceProc; 
     static error_handler sErrorProc; 
     static close_handler sCloseProc; 
     static connect_handler sConnectProc; 
 
     static int Send(SOCKET s) 
     { 
        map<SOCKET,list<Data*> >::iterator it=sMapOfComm.find(s); 
        if(it!=sMapOfComm.end()) 
        { 
           for(list<Data*>::iterator itlist=it->second.begin();itlist!=it->second.end(); 
              ) 
           { 
              auto_str str; 
              (*itlist)->getstr(str); 
              int ret=::send(s,str.cstr(),str.length(),0); 
              if(ret==SOCKET_ERROR)//  
              { 
                 if((ret=WSAGetLastError())!=WSAEWOULDBLOCK) 
                 return 0; 
                 else 
                 { 
                   bWrite=false; 
                   return WSAEWOULDBLOCK;//缓冲区满了或对方接收缓冲区满了  
                 } 
              } 
              else 
              { 
                delete (*itlist); 
                itlist=it->second.erase(itlist); 
              } 
           } 
           return 1; 
        } 
        return 0; 
     } 
     static LRESULT CALLBACK NewWndProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam) 
     { 
        if(msg==WM_SOCKET) 
        { 
           SOCKET s=(SOCKET)wParam; 
           if(WSAGETSELECTERROR(lParam)) 
           { 
             sErrorProc(WSAGetLastError()); 
             ::closesocket(s); 
             return 0; 
           } 
           switch(WSAGETSELECTEVENT(lParam)) 
           { 
             case FD_ACCEPT: 
             { 
                 SOCKET sClient=::accept(s,NULL,NULL); 
                 ::WSAAsyncSelect(sClient,hwnd,WM_SOCKET,FD_READ|FD_WRITE|FD_CLOSE); 
             } 
             break; 
             case FD_CONNECT: 
             { 
                sConnectProc(s); 
             } 
             break; 
             case FD_READ: 
             { 
                 DataHead dh; 
                 dh.s=s; 
                 int len=::recv(s,(char*)&dh,sizeof(DataHead),0); 
                 if(len==sizeof(DataHead)) 
                 { 
                     if(dh.datalen>0) 
                     { 
                         auto_str astr(dh.datalen); 
                         len=::recv(s,astr.str(),astr.length(),0); 
                         if(len==dh.datalen) 
                         { 
                            Data data(dh.cmd,astr.str(),astr.length(),s); 
                            sReceviceProc(&data); 
                         } 
                     } 
                     else if(!dh.datalen) 
                     { 
                         Data data(dh.cmd,NULL,0,s); 
                         sReceviceProc(&data); 
                     } 
                 } 
             } 
             break; 
             case FD_WRITE: 
             { 
                 bWrite=True; 
                 //Send(s);  
             } 
             break; 
             case FD_CLOSE: 
             { 
                sCloseProc(s); 
                ::closesocket(s); 
             } 
             break; 
           } 
           return 1; 
        } 
        else 
        { 
          return  ::CallWindowProc(sOldProc,hwnd,msg,wParam,lParam); 
        } 
     } 
     HWND s_hwnd; 
     SOCKET s_Sock; 
     bool bMode; 
  public: 
     AsyncSocket(HWND hwnd):s_hwnd(hwnd),s_Sock(INVALID_SOCKET),bMode(true) 
     { 
       sOldProc=(WNDPROC)SetWindowLong(s_hwnd,GWL_WNDPROC,(LONG)NewWndProc); 
       assert(sOldProc); 
     } 
     ~AsyncSocket() 
     { 
        Close(); 
     } 
 
     void reg_receive_handler(receive_handler handler) 
     { 
       sReceviceProc=handler; 
     } 
     void reg_error_handler(error_handler handler) 
     { 
       sErrorProc=handler; 
     } 
     void reg_close_handler(close_handler handler) 
     { 
       sCloseProc=handler; 
     } 
     void reg_connect_handler(connect_handler handler) 
     { 
       sConnectProc=handler; 
     } 
     void Close() 
     { 
       if(s_Sock!=INVALID_SOCKET) 
       { 
         ::closesocket(s_Sock); 
         s_Sock=INVALID_SOCKET; 
       } 
       for(map<SOCKET,list<Data*> >::iterator it=sMapOfComm.begin(); 
           it!=sMapOfComm.end();++it 
          ) 
       { 
          for(list<Data*>::iterator itlist=it->second.begin(); 
              itlist!=it->second.end(); 
              ++itlist 
             ) 
          { 
             delete (*itlist); 
          } 
          it->second.clear(); 
       } 
       sMapOfComm.clear(); 
     } 
     bool Listen(int Port) 
     { 
       Close(); 
       bMode=true; 
 
       s_Sock=::socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); 
       if(s_Sock==INVALID_SOCKET)return false; 
 
       sockaddr_in addr; 
       addr.sin_family=AF_INET; 
       addr.sin_addr.S_un.S_addr=INADDR_ANY; 
       addr.sin_port=::htons(Port); 
 
       if(::bind(s_Sock,(PSOCKADDR)&addr,sizeof(addr))==SOCKET_ERROR) 
       return false; 
 
       ::WSAAsyncSelect(s_Sock,s_hwnd,WM_SOCKET,FD_ACCEPT|FD_READ|FD_WRITE|FD_CLOSE); 
 
       ::listen(s_Sock,5); 
       return true; 
     } 
     bool Connect(const char* lpszIp, int Port) 
     { 
         Close(); 
         bMode=false; 
 
         s_Sock=::socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); 
         if(s_Sock==INVALID_SOCKET)return false; 
 
         sockaddr_in addr; 
         addr.sin_family=AF_INET; 
         addr.sin_addr.S_un.S_addr=::inet_addr(lpszIp); 
         addr.sin_port=::htons(Port); 
 
         if(addr.sin_addr.S_un.S_addr==0xffffffff) 
         return false; 
 
         ::WSAAsyncSelect(s_Sock,s_hwnd,WM_SOCKET,FD_CONNECT|FD_READ|FD_WRITE|FD_CLOSE); 
         int ret=::connect(s_Sock,(PSOCKADDR)&addr,sizeof(addr)); 
         if(ret!=SOCKET_ERROR) 
         return true; 
         else 
         { 
            return ::WSAGetLastError()==WSAEWOULDBLOCK; 
         } 
     } 
     int PostSend(const char *cmd,const char *data,int datalen,SOCKET s=INVALID_SOCKET) 
     { 
       DataHead dh={0}; 
       memcpy(dh.cmd,cmd,2); 
       dh.datalen=datalen; 
 
       if(!bMode)  //客户端模式  
       dh.s=s_Sock; 
       else 
       dh.s=s; 
 
       Data *pd(new Data(dh,data)); 
       assert(pd); 
       map<SOCKET,list<Data*> >::iterator it=sMapOfComm.find(pd->getdatahead().s); 
       if(it==sMapOfComm.end()) 
       sMapOfComm[pd->getdatahead().s].push_back(pd); 
       else 
       { 
         it->second.push_back(pd); 
       } 
       return Send(pd->getdatahead().s); 
     } 
     bool GetWriteStatus()const 
     { 
         return bWrite; 
     } 
  }; 
  map<SOCKET,list<Data*> >AsyncSocket::sMapOfComm; 
  WNDPROC AsyncSocket::sOldProc; 
  bool AsyncSocket::bWrite; 
   
  receive_handler AsyncSocket::sReceviceProc; 
  error_handler  AsyncSocket::sErrorProc; 
  close_handler AsyncSocket::sCloseProc; 
  connect_handler AsyncSocket::sConnectProc; 
 
  class InitSocket 
  { 
  public: 
    InitSocket() 
    { 
      WSAData wsaData={0}; 
      assert(::WSAStartup(MAKEWORD(2,2),&wsaData)==0); 
    } 
    ~InitSocket() 
    { 
       ::WSACleanup(); 
    } 
  }; 
  static InitSocket init; 

#endif 
//---------------------------------------------------------------------------

#ifndef Unit2H
#define Unit2H
//---------------------------------------------------------------------------
#include <vcl.h>
#include <winsock2.h>
#include <cassert>
#include <map>
#include <list>
#include "Datastruct.h"
using namespace std;

#pragma comment(lib,"ws2_32.lib")

namespace Async
{
  #ifndef __BORLANDC__
  typedef void  (*receive_handler)(Data *pd);
  typedef void  (*error_handler)(int errcode);
  typedef void  (*close_handler)(SOCKET s);
  typedef void  (*connect_handler)(SOCKET s);
  #else
  typedef void __fastcall (__closure* receive_handler)(Data *pd);
  typedef void __fastcall (__closure *error_handler)(int errcode);
  typedef void __fastcall (__closure *close_handler)(SOCKET s);
  typedef void __fastcall (__closure *connect_handler)(SOCKET s);
  #endif
 
  class AsyncSocket
  {
     static const int  WM_SOCKET=WM_USER+109;
     static map<SOCKET,list<Data*> > sMapOfComm;
     static WNDPROC sOldProc;
     static bool bWrite;//可写
    
     static receive_handler sReceviceProc;
     static error_handler sErrorProc;
     static close_handler sCloseProc;
     static connect_handler sConnectProc;

     static int Send(SOCKET s)
     {
        map<SOCKET,list<Data*> >::iterator it=sMapOfComm.find(s);
        if(it!=sMapOfComm.end())
        {
           for(list<Data*>::iterator itlist=it->second.begin();itlist!=it->second.end();
              )
           {
              auto_str str;
              (*itlist)->getstr(str);
              int ret=::send(s,str.cstr(),str.length(),0);
              if(ret==SOCKET_ERROR)//
              {
                 if((ret=WSAGetLastError())!=WSAEWOULDBLOCK)
                 return 0;
                 else
                 {
                   bWrite=false;
                   return WSAEWOULDBLOCK;//缓冲区满了或对方接收缓冲区满了
                 }
              }
              else
              {
                delete (*itlist);
                itlist=it->second.erase(itlist);
              }
           }
           return 1;
        }
        return 0;
     }
     static LRESULT CALLBACK NewWndProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)
     {
        if(msg==WM_SOCKET)
        {
           SOCKET s=(SOCKET)wParam;
           if(WSAGETSELECTERROR(lParam))
           {
             sErrorProc(WSAGetLastError());
             ::closesocket(s);
             return 0;
           }
           switch(WSAGETSELECTEVENT(lParam))
           {
             case FD_ACCEPT:
             {
                 SOCKET sClient=::accept(s,NULL,NULL);
                 ::WSAAsyncSelect(sClient,hwnd,WM_SOCKET,FD_READ|FD_WRITE|FD_CLOSE);
             }
             break;
             case FD_CONNECT:
             {
                sConnectProc(s);
             }
             break;
             case FD_READ:
             {
                 DataHead dh;
                 dh.s=s;
                 int len=::recv(s,(char*)&dh,sizeof(DataHead),0);
                 if(len==sizeof(DataHead))
                 {
                     if(dh.datalen>0)
                     {
                         auto_str astr(dh.datalen);
                         len=::recv(s,astr.str(),astr.length(),0);
                         if(len==dh.datalen)
                         {
                            Data data(dh.cmd,astr.str(),astr.length(),s);
                            sReceviceProc(&data);
                         }
                     }
                     else if(!dh.datalen)
                     {
                         Data data(dh.cmd,NULL,0,s);
                         sReceviceProc(&data);
                     }
                 }
             }
             break;
             case FD_WRITE:
             {
                 bWrite=True;
                 //Send(s);
             }
             break;
             case FD_CLOSE:
             {
                sCloseProc(s);
                ::closesocket(s);
             }
             break;
           }
           return 1;
        }
        else
        {
          return  ::CallWindowProc(sOldProc,hwnd,msg,wParam,lParam);
        }
     }
     HWND s_hwnd;
     SOCKET s_Sock;
     bool bMode;
  public:
     AsyncSocket(HWND hwnd):s_hwnd(hwnd),s_Sock(INVALID_SOCKET),bMode(true)
     {
       sOldProc=(WNDPROC)SetWindowLong(s_hwnd,GWL_WNDPROC,(LONG)NewWndProc);
       assert(sOldProc);
     }
     ~AsyncSocket()
     {
        Close();
     }

     void reg_receive_handler(receive_handler handler)
     {
       sReceviceProc=handler;
     }
     void reg_error_handler(error_handler handler)
     {
       sErrorProc=handler;
     }
     void reg_close_handler(close_handler handler)
     {
       sCloseProc=handler;
     }
     void reg_connect_handler(connect_handler handler)
     {
       sConnectProc=handler;
     }
     void Close()
     {
       if(s_Sock!=INVALID_SOCKET)
       {
         ::closesocket(s_Sock);
         s_Sock=INVALID_SOCKET;
       }
       for(map<SOCKET,list<Data*> >::iterator it=sMapOfComm.begin();
           it!=sMapOfComm.end();++it
          )
       {
          for(list<Data*>::iterator itlist=it->second.begin();
              itlist!=it->second.end();
              ++itlist
             )
          {
             delete (*itlist);
          }
          it->second.clear();
       }
       sMapOfComm.clear();
     }
     bool Listen(int Port)
     {
       Close();
       bMode=true;

       s_Sock=::socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
       if(s_Sock==INVALID_SOCKET)return false;

       sockaddr_in addr;
       addr.sin_family=AF_INET;
       addr.sin_addr.S_un.S_addr=INADDR_ANY;
       addr.sin_port=::htons(Port);

       if(::bind(s_Sock,(PSOCKADDR)&addr,sizeof(addr))==SOCKET_ERROR)
       return false;

       ::WSAAsyncSelect(s_Sock,s_hwnd,WM_SOCKET,FD_ACCEPT|FD_READ|FD_WRITE|FD_CLOSE);

       ::listen(s_Sock,5);
       return true;
     }
     bool Connect(const char* lpszIp, int Port)
     {
         Close();
         bMode=false;

         s_Sock=::socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
         if(s_Sock==INVALID_SOCKET)return false;

         sockaddr_in addr;
         addr.sin_family=AF_INET;
         addr.sin_addr.S_un.S_addr=::inet_addr(lpszIp);
         addr.sin_port=::htons(Port);

         if(addr.sin_addr.S_un.S_addr==0xffffffff)
         return false;

         ::WSAAsyncSelect(s_Sock,s_hwnd,WM_SOCKET,FD_CONNECT|FD_READ|FD_WRITE|FD_CLOSE);
         int ret=::connect(s_Sock,(PSOCKADDR)&addr,sizeof(addr));
         if(ret!=SOCKET_ERROR)
         return true;
         else
         {
            return ::WSAGetLastError()==WSAEWOULDBLOCK;
         }
     }
     int PostSend(const char *cmd,const char *data,int datalen,SOCKET s=INVALID_SOCKET)
     {
       DataHead dh={0};
       memcpy(dh.cmd,cmd,2);
       dh.datalen=datalen;

       if(!bMode)  //客户端模式
       dh.s=s_Sock;
       else
       dh.s=s;

       Data *pd(new Data(dh,data));
       assert(pd);
       map<SOCKET,list<Data*> >::iterator it=sMapOfComm.find(pd->getdatahead().s);
       if(it==sMapOfComm.end())
       sMapOfComm[pd->getdatahead().s].push_back(pd);
       else
       {
         it->second.push_back(pd);
       }
       return Send(pd->getdatahead().s);
     }
     bool GetWriteStatus()const
     {
         return bWrite;
     }
  };
  map<SOCKET,list<Data*> >AsyncSocket::sMapOfComm;
  WNDPROC AsyncSocket::sOldProc;
  bool AsyncSocket::bWrite;
 
  receive_handler AsyncSocket::sReceviceProc;
  error_handler  AsyncSocket::sErrorProc;
  close_handler AsyncSocket::sCloseProc;
  connect_handler AsyncSocket::sConnectProc;

  class InitSocket
  {
  public:
    InitSocket()
    {
      WSAData wsaData={0};
      assert(::WSAStartup(MAKEWORD(2,2),&wsaData)==0);
    }
    ~InitSocket()
    {
       ::WSACleanup();
    }
  };
  static InitSocket init;
}
#endif
[cpp]
 
#ifndef DatastructH  
#define DatastructH  
#include <windows.h>  
#include <cassert.h>  
//---------------------------------------------------------------------------  
  class auto_str 
  { 
     char* s_buf; 
     int s_buflen; 
 
     friend class Data; 
 
     void* operator new(size_t); 
     void* operator new[](size_t); 
 
     void set(const char *buf,const int len) 
     { 
       s_buf=const_cast<char*>(buf); 
       s_buflen=len; 
     } 
   public: 
     auto_str():s_buf(NULL),s_buflen(0) 
     {} 
     auto_str(size_t size):s_buf(NULL),s_buflen(size) 
     { 
       if(size>0) 
       { 
         s_buf=new char[size]; 
         assert(s_buf); 
         memset(s_buf,0,size); 
       } 
     } 
     ~auto_str() 
     { 
       if(s_buf) 
       { 
         delete [] s_buf; 
       } 
     } 
     inline char* str()const 
     { 
       return s_buf; 
     } 
     inline const char* cstr()const 
     { 
       return s_buf; 
     } 
     inline const int length()const 
     { 
       return s_buflen; 
     } 
  }; 
  struct DataHead 
  { 
    char cmd[3]; 
    int datalen; 
    SOCKET s; 
  }; 
  class Data 
  { 
       //struct data  
       DataHead s_dh; 
       char *s_data; 
 
       Data& operator=(const Data&); 
       Data(const Data&); 
    public: 
       Data(const DataHead &dh,const char *data=NULL):s_data(NULL) 
       { 
         memcpy(&s_dh,&dh,sizeof(DataHead)); 
         if(data) 
         { 
           if(dh.datalen>0) 
           { 
              s_data=new char[dh.datalen]; 
              assert(s_data); 
              memcpy(s_data,data,dh.datalen); 
           } 
         } 
       } 
       Data(const char* cmd,const char* data,int datalen,SOCKET s=INVALID_SOCKET):s_data(NULL) 
       { 
         memset(&s_dh,0,sizeof(s_dh)); 
         s_dh.s=s; 
         memcpy(s_dh.cmd,cmd,2); 
         s_dh.datalen=datalen; 
         if(datalen>0) 
         { 
           s_data=new char[datalen]; 
           assert(s_data); 
           memcpy(s_data,data,datalen); 
         } 
       } 
       ~Data() 
       { 
         if(s_data) 
         { 
           delete [] s_data; 
         } 
       } 
       inline const char* getdata()const 
       { 
          return s_data; 
       } 
       inline const int getdatalen()const 
       { 
          return s_dh.datalen; 
       } 
       inline const DataHead& getdatahead()const 
       { 
          return s_dh; 
       } 
       void getstr(auto_str& str)const 
       { 
          char *pBuf=new char[s_dh.datalen+sizeof(DataHead)]; 
          assert(pBuf); 
          memcpy(pBuf,&s_dh,sizeof(DataHead)); 
          memcpy(pBuf+sizeof(DataHead),s_data,s_dh.datalen); 
          str.set(pBuf,s_dh.datalen+sizeof(DataHead)); 
       } 
  }; 
   
#endif 

 

 

摘自 天道酬勤

点击复制链接 与好友分享!回本站首页
相关TAG标签 WSAAsyncSelect应用
上一篇:保护电脑系统时间不被修改
下一篇:用ASIO编写UDP通信程序
相关文章
图文推荐
点击排行

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训 | 举报中心

版权所有: 红黑联盟--致力于做实用的IT技术学习网站