//---------------------------------------------------------------------------
#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 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