📄 casyncsock.cpp
字号:
/*
CAsyncSock.cpp
Classe per interfaccia Winsock (modalita' asincrona).
Luca Piergentili, 06/07/98
lpiergentili@yahoo.com
http://www.geocities.com/lpiergentili/
*/
#include "env.h"
#include "pragma.h"
#include "strcpyn.h"
#include "window.h"
#include "CSock.h"
#include "CAsyncSockMessages.h"
#include "CAsyncSock.h"
BEGIN_MESSAGE_MAP(CSockWnd,CWnd)
ON_MESSAGE(WM_ASYNCSELECT,OnAsyncSelect)
ON_MESSAGE(WM_ASYNCGETHOSTBYNAME,OnAsyncGetHostByName)
ON_MESSAGE(WM_ASYNCGETHOSTBYADDR,OnAsyncGetHostByAddr)
ON_MESSAGE(WM_ASYNCGETSERVBYNAME,OnAsyncGetServByName)
ON_MESSAGE(WM_ASYNCGETSERVBYPORT,OnAsyncGetServByPort)
END_MESSAGE_MAP()
/*
CSockWnd()
Crea la finestra interna utilizzata per la gestione dei messaggi WSA.
In input il puntatore alla classe CAsyncSock (utilizzato per le callback) ed il puntatore
alla finestra dell'applicazione.
*/
CSockWnd::CSockWnd(CAsyncSock* pAsyncSock,CWnd* pParent)
{
// ptr per le callback di CAsyncSock
m_pAsyncSock = pAsyncSock;
// AsyncGetHostByName()
m_hAsyncGetHostByName = (HANDLE)0; // handle restituito da WSAAsyncGetXByY()
m_lpszAsyncGetHostByName = (LPSTR)NULL; // ptr al buffer interno di CAsyncSock
m_nAsyncGetHostByName = 0; // dim. del buffer
memset(m_szIPAddr,'\0',sizeof(m_szIPAddr)); // buffer interno
// AsyncGetHostByAddr()
m_hAsyncGetHostByAddr = (HANDLE)0; // handle restituito da WSAAsyncGetXByY()
m_lpszAsyncGetHostByAddr = (LPSTR)NULL; // ptr al buffer interno di CAsyncSock
m_nAsyncGetHostByAddr = 0; // dim. del buffer
memset(m_szHostName,'\0',sizeof(m_szHostName)); // buffer interno
// AsyncGetServByName()
m_hAsyncGetServByName = (HANDLE)0; // handle restituito da WSAAsyncGetXByY()
m_lpszAsyncGetServByName = (LPSTR)NULL; // ptr al buffer interno di CAsyncSock
m_nAsyncGetServByName = 0; // dim. del buffer
m_nPort = 0; // # porta interno
// AsyncGetServByPort()
m_hAsyncGetServByPort = (HANDLE)0; // handle restituito da WSAAsyncGetXByY()
m_lpszAsyncGetServByPort = (LPSTR)NULL; // ptr al buffer interno di CAsyncSock
m_nAsyncGetServByPort = 0; // dim. del buffer
memset(m_szService,'\0',sizeof(m_szService)); // buffer interno
// crea la finestra per i messaggi asincroni
CString strClassName = AfxRegisterWndClass(CS_BYTEALIGNCLIENT|CS_BYTEALIGNWINDOW,0,0,0);
CreateEx(0,strClassName,"CSockWnd",0,1,1,1,1,(pParent ? pParent->m_hWnd : NULL),NULL,NULL);
}
/*
~CSockWnd()
Cancella le eventuali richieste asincrone pendenti.
*/
CSockWnd::~CSockWnd(void)
{
if(m_hAsyncGetHostByName!=(HANDLE)0)
::WSACancelAsyncRequest(m_hAsyncGetHostByName);
if(m_hAsyncGetHostByAddr!=(HANDLE)0)
::WSACancelAsyncRequest(m_hAsyncGetHostByAddr);
if(m_hAsyncGetServByName!=(HANDLE)0)
::WSACancelAsyncRequest(m_hAsyncGetServByName);
if(m_hAsyncGetServByPort!=(HANDLE)0)
::WSACancelAsyncRequest(m_hAsyncGetServByPort);
}
/*
AsyncGetHostByName()
Ricava l'ip relativo all'host in modo asincrono, chiamando la WSAAsyncGetHostByName().
Imposta la OnAsyncGetHostByName() come callback per WSAAsyncGetHostByName() per poter
formattare i dati ricevuti.
input:
LPCSTR puntatore al buffer contenente il nome dell'host
LPSTR puntatore al buffer per WSAAsyncGetHostByName() (CAsyncSock)
UINT dimensione del buffer (CAsyncSock)
output:
int 0 o codice d'errore WSA
*/
int CSockWnd::AsyncGetHostByName(LPCSTR lpcszHost,LPSTR pBuffer,UINT nBufSize)
{
int nWSAError = WSA_FAILURE;
m_lpszAsyncGetHostByName = pBuffer;
m_nAsyncGetHostByName = nBufSize;
memset(m_lpszAsyncGetHostByName,'\0',m_nAsyncGetHostByName);
// controlla che sia stato passato un puntatore valido alla classe
if(m_pAsyncSock)
{
// effettua la richiesta asincrona passando l'handle della finestra interna ed il ptr al buffer di CAsyncSock
if((m_hAsyncGetHostByName=::WSAAsyncGetHostByName(this->m_hWnd,WM_ASYNCGETHOSTBYNAME,lpcszHost,m_lpszAsyncGetHostByName,m_nAsyncGetHostByName))==(HANDLE)0)
{
// in caso di errore deve inviare il messaggio autonomamente perche' la On...() non verra' chiamata
nWSAError = m_pAsyncSock->GetWSALastError(WSA_GETLASTERROR);
::PostMessage(this->m_hWnd,WM_ASYNCGETHOSTBYNAME,0,MAKELPARAM(0,nWSAError));
}
else
nWSAError = 0;
}
return(nWSAError);
}
/*
OnAsyncGetHostByName()
Callback per WSAAsyncGetHostByName().
Formatta i dati ricevuti e chiama la callback di CAsyncSock.
input:
UINT (wParam) codice d'errore WSA
LONG (lParam) puntatore al buffer riempito da WSAAsyncGetHostByName()
output:
LONG 0L (il codice d'errore viene passato alla callback di CAsyncSock come wParam)
*/
#pragma warning(disable:4305)
LONG CSockWnd::OnAsyncGetHostByName(UINT /*wParam*/,LONG lParam)
{
int nWSAError = WSAGETASYNCERROR(lParam);
m_hAsyncGetHostByName = (HANDLE)0;
memset(m_szIPAddr,'\0',sizeof(m_szIPAddr));
// errore Winsock
if(nWSAError!=0)
{
// azzera il buffer di CAsyncSock
memset(m_lpszAsyncGetHostByName,'\0',m_nAsyncGetHostByName);
}
else
{
// copia dal buffer di CAsyncSock a quello interno
struct in_addr st_addr = {0};
st_addr.s_addr = *((u_long FAR *)(((struct hostent FAR *)m_lpszAsyncGetHostByName)->h_addr));
strcpyn(m_szIPAddr,::inet_ntoa(st_addr),sizeof(m_szIPAddr));
}
// chiama la callback di CAsyncSock
if(m_pAsyncSock)
m_pAsyncSock->AsyncGetHostByNameCallBack(nWSAError,MAKELPARAM(LOWORD(m_szIPAddr),HIWORD(m_szIPAddr)));
return(0L);
}
#pragma warning(default:4305)
/*
AsyncGetHostByAddr()
Ricava il nome host relativo all'ip in modo asincrono, chiamando la WSAAsyncGetHostByAddr().
Imposta la OnAsyncGetHostByAddr() come callback per WSAAsyncGetHostByAddr() per poter
formattare i dati ricevuti.
input:
LPCSTR puntatore al buffer contenente l'indirizzo ip
LPSTR puntatore al buffer per WSAAsyncGetHostByAddr() (CAsyncSock)
UINT dimensione del buffer (CAsyncSock)
output:
int 0 o codice d'errore WSA
*/
int CSockWnd::AsyncGetHostByAddr(LPCSTR lpcszIPAddr,LPSTR pBuffer,UINT nBufSize)
{
int nWSAError = WSA_FAILURE;
m_lpszAsyncGetHostByAddr = pBuffer;
m_nAsyncGetHostByAddr = nBufSize;
memset(m_lpszAsyncGetHostByAddr,'\0',m_nAsyncGetHostByAddr);
// controlla che sia stato passato un puntatore valido alla classe
if(m_pAsyncSock)
{
// controlla se si tratta dell'host locale
if(lstrcmp(lpcszIPAddr,m_pAsyncSock->GetLocalHostAddr())==0)
{
HOSTENT stHostEnt = {0};
stHostEnt.h_name = (char FAR *)m_pAsyncSock->GetLocalHostName();
memcpy(m_lpszAsyncGetHostByAddr,&stHostEnt,sizeof(HOSTENT));
::PostMessage(this->m_hWnd,WM_ASYNCGETHOSTBYADDR,0,0);
nWSAError = 0;
goto done;
}
// converte da "n.n.n.n" in n.n.n.n
static struct in_addr st_addr;
memset(&st_addr,'\0',sizeof(struct in_addr));
st_addr.s_addr = ::inet_addr(lpcszIPAddr);
if(st_addr.s_addr!=INADDR_NONE)
{
// effettua la richiesta asincrona passando l'handle della finestra interna ed il ptr al buffer di CSock
if((m_hAsyncGetHostByAddr=::WSAAsyncGetHostByAddr(this->m_hWnd,WM_ASYNCGETHOSTBYADDR,(const char FAR*)&st_addr,sizeof(struct in_addr),PF_INET,m_lpszAsyncGetHostByAddr,m_nAsyncGetHostByAddr))==(HANDLE)0)
{
// in caso di errore deve inviare il messaggio autonomamente perche' la On...() non verra' chiamata
nWSAError = m_pAsyncSock->GetWSALastError(WSA_GETLASTERROR);
::PostMessage(this->m_hWnd,WM_ASYNCGETHOSTBYADDR,0,MAKELPARAM(0,nWSAError));
}
else
nWSAError = 0;
}
else
nWSAError = WSAEDESTADDRREQ;
}
done:
return(nWSAError);
}
/*
OnAsyncGetHostByAddr()
Callback per WSAAsyncGetHostByAddr().
Formatta i dati ricevuti e chiama la callback di CAsyncSock.
input:
UINT (wParam) codice d'errore WSA
LONG (lParam) puntatore al buffer utilizzato da WSAAsyncGetHostByAddr()
output:
LONG 0L (il codice d'errore viene passato alla callback di CAsyncSock in wParam)
*/
#pragma warning(disable:4305)
LONG CSockWnd::OnAsyncGetHostByAddr(UINT /*wParam*/,LONG lParam)
{
int nWSAError = WSAGETASYNCERROR(lParam);
m_hAsyncGetHostByAddr = (HANDLE)0;
memset(m_szHostName,'\0',sizeof(m_szHostName));
if(nWSAError!=0)
{
// azzera il buffer di CAsyncSock
memset(m_lpszAsyncGetHostByAddr,'\0',m_nAsyncGetHostByAddr);
}
else
{
// copia dal buffer di CAsyncSock a quello interno
strcpyn(m_szHostName,((LPHOSTENT)m_lpszAsyncGetHostByAddr)->h_name,sizeof(m_szHostName));
}
// chiama la callback di CAsyncSock
if(m_pAsyncSock)
m_pAsyncSock->AsyncGetHostByAddrCallBack(nWSAError,MAKELPARAM(LOWORD(m_szHostName),HIWORD(m_szHostName)));
return(0L);
}
#pragma warning(default:4305)
/*
AsyncGetServByName()
Ricava il # della porta relativa al servizio in modo asincrono, chiamando la WSAAsyncGetServByName().
Imposta la OnAsyncGetServByName() come callback per WSAAsyncGetServByName() per poter formattare i
dati ricevuti.
input:
LPCSTR puntatore al buffer con il nome del servizio
LPCSTR puntatore al buffer con il protocollo (default tcp)
LPSTR puntatore al buffer per WSAAsyncGetServByName() (CAsyncSock)
UINT dimensione del buffer (CAsyncSock)
output:
int 0 o codice d'errore WSA
*/
int CSockWnd::AsyncGetServByName(LPCSTR lpcszService,LPCSTR lpcszProto,LPSTR pBuffer,UINT nBufSize)
{
int nWSAError = WSA_FAILURE;
m_lpszAsyncGetServByName = pBuffer;
m_nAsyncGetServByName = nBufSize;
memset(m_lpszAsyncGetServByName,'\0',m_nAsyncGetServByName);
// controlla che sia stato passato un puntatore valido alla classe
if(m_pAsyncSock)
{
m_nPort = 0;
// prima di chiamare winsock controlla nell'array dei servizi di CSock
ITERATOR iter;
SERVICES* s;
if((iter = m_pAsyncSock->m_pServicesList.First())!=(ITERATOR)NULL)
while(iter!=(ITERATOR)NULL)
{
s = (SERVICES*)iter->data;
if(stricmp(lpcszService,s->service)==0)
if(lstrcmpi(lpcszProto,s->proto)==0)
{
m_nPort = s->port;
break;
}
iter = m_pAsyncSock->m_pServicesList.Next(iter);
}
if(m_nPort==0)
{
// effettua la richiesta asincrona passando l'handle della finestra interna ed il ptr al buffer di CAsyncSock
if((m_hAsyncGetServByName=::WSAAsyncGetServByName(this->m_hWnd,WM_ASYNCGETSERVBYNAME,lpcszService,lpcszProto,m_lpszAsyncGetServByName,m_nAsyncGetServByName))==(HANDLE)0)
{
// in caso di errore deve inviare il messaggio autonomamente perche' la On...() non verra' chiamata
nWSAError = m_pAsyncSock->GetWSALastError(WSA_GETLASTERROR);
::PostMessage(this->m_hWnd,WM_ASYNCGETSERVBYNAME,0,MAKELPARAM(0,nWSAError));
}
else
nWSAError = 0;
}
else
{
struct servent se = {0};
se.s_port = (short)m_nPort;
memset(m_lpszAsyncGetServByName,'\0',m_nAsyncGetServByName);
memcpy(m_lpszAsyncGetServByName,&se,sizeof(struct servent));
// ha incontrato il servizio nell'array, invia il messaggio alla On...()
nWSAError = 0;
::PostMessage(this->m_hWnd,WM_ASYNCGETSERVBYNAME,0,MAKELPARAM(0,nWSAError));
}
}
return(nWSAError);
}
/*
OnAsyncGetServByName()
Callback per WSAAsyncGetServByName().
Formatta i dati ricevuti e chiama la callback di CAsyncSock.
input:
UINT (wParam) codice d'errore WSA
LONG (lParam) puntatore al buffer utilizzato da WSAAsyncGetServByName()
output:
LONG 0L (il codice d'errore viene passato alla callback di CAsyncSock in wParam)
*/
LONG CSockWnd::OnAsyncGetServByName(UINT /*wParam*/,LONG lParam)
{
int nWSAError = WSAGETASYNCERROR(lParam);
m_hAsyncGetServByName = (HANDLE)0;
m_nPort = 0;
// errore Winsock
if(nWSAError!=0)
{
// azzera il buffer di CAsyncSock
memset(m_lpszAsyncGetServByName,'\0',m_nAsyncGetServByName);
}
else
{
// copia dal buffer di CAsyncSock a quello interno
m_nPort = (int)((struct servent FAR *)m_lpszAsyncGetServByName)->s_port;
}
// chiama la callback di CAsyncSock
if(m_pAsyncSock)
m_pAsyncSock->AsyncGetServByNameCallBack(nWSAError,MAKELPARAM(LOWORD(m_nPort),HIWORD(m_nPort)));
return(0L);
}
/*
AsyncGetServByPort()
Ricava il nome del servizio relativo al # porta in modo asincrono, chiamando la WSAAsyncGetServByPort().
Imposta la OnAsyncGetServByPort() come callback per WSAAsyncGetServByPort() per poter formattare i
dati ricevuti.
input:
LPCSTR # porta
LPCSTR puntatore al buffer con il protocollo (default tcp)
LPSTR puntatore al buffer per WSAAsyncGetServByPort() (CAsyncSock)
UINT dimensione del buffer (CAsyncSock)
output:
int 0 o codice d'errore WSA
*/
int CSockWnd::AsyncGetServByPort(UINT m_nPort,LPCSTR lpcszProto,LPSTR pBuffer,UINT nBufSize)
{
static LPSTR lpName;
static char szName[32];
int nWSAError = WSA_FAILURE;
m_lpszAsyncGetServByPort = pBuffer;
m_nAsyncGetServByPort = nBufSize;
memset(m_lpszAsyncGetServByPort,'\0',m_nAsyncGetServByPort);
// controlla che sia stato passato un puntatore valido alla classe
if(m_pAsyncSock)
{
lpName = NULL;
memset(szName,'\0',sizeof(szName));
// prima di chiamare winsock controlla nell'array dei servizi di CSock
ITERATOR iter;
SERVICES* s;
if((iter = m_pAsyncSock->m_pServicesList.First())!=(ITERATOR)NULL)
while(iter!=(ITERATOR)NULL)
{
s = (SERVICES*)iter->data;
if(stricmp(lpcszProto,s->proto)==0)
{
strcpyn(szName,s->service,sizeof(szName));
lpName = szName;
break;
}
iter = m_pAsyncSock->m_pServicesList.Next(iter);
}
if(!lpName)
{
// effettua la richiesta asincrona passando l'handle della finestra interna ed il ptr al buffer di CAsyncSock
if((m_hAsyncGetServByPort=::WSAAsyncGetServByPort(this->m_hWnd,WM_ASYNCGETSERVBYPORT,m_nPort,lpcszProto,m_lpszAsyncGetServByPort,m_nAsyncGetServByPort))==(HANDLE)0)
{
// in caso di errore deve inviare il messaggio autonomamente perche' la On...() non verra' chiamata
nWSAError = m_pAsyncSock->GetWSALastError(WSA_GETLASTERROR);
::PostMessage(this->m_hWnd,WM_ASYNCGETSERVBYPORT,0,MAKELPARAM(0,nWSAError));
}
else
nWSAError = 0;
}
else
{
struct servent se = {0};
se.s_name = (char FAR *)szName;
memset(m_lpszAsyncGetServByPort,'\0',m_nAsyncGetServByPort);
memcpy(m_lpszAsyncGetServByPort,&se,sizeof(struct servent));
// ha incontrato il servizio nell'array, invia il messaggio alla On...()
nWSAError = 0;
::PostMessage(this->m_hWnd,WM_ASYNCGETSERVBYPORT,0,MAKELPARAM(0,nWSAError));
}
}
return(nWSAError);
}
/*
OnAsyncGetServByPort()
Callback per WSAAsyncGetServByPort().
Formatta i dati ricevuti e chiama la callback di CAsyncSock.
input:
UINT (wParam) codice d'errore WSA
LONG (lParam) puntatore al buffer utilizzato da WSAAsyncGetServByPort()
output:
LONG 0L (il codice d'errore viene passato alla callback di CAsyncSock in wParam)
*/
#pragma warning(disable:4305)
LONG CSockWnd::OnAsyncGetServByPort(UINT /*wParam*/,LONG lParam)
{
int nWSAError = WSAGETASYNCERROR(lParam);
m_hAsyncGetServByPort = (HANDLE)0;
memset(m_szService,'\0',sizeof(m_szService));
// errore Winsock
if(nWSAError!=0)
{
// azzera il buffer di CAsyncSock
memset(m_lpszAsyncGetServByPort,'\0',m_nAsyncGetServByPort);
}
else
{
// copia dal buffer di CAsyncSock a quello interno
strcpyn(m_szService,(char FAR *)((struct servent FAR *)m_lpszAsyncGetServByPort)->s_name,sizeof(m_szService));
}
// chiama la callback di CAsyncSock
if(m_pAsyncSock)
m_pAsyncSock->AsyncGetServByPortCallBack(nWSAError,MAKELPARAM(LOWORD(m_szService),HIWORD(m_szService)));
return(0L);
}
#pragma warning(default:4305)
/*
OnAsyncSelect()
Callback per WSAAsyncSelect().
Chiama la callback di CAsyncSock relativa all'evento segnalato.
La chiamata a WSAAsyncSelect() per registrare gli eventi da segnalare viene effettuata
durante la creazione del socket in CAsyncSock::Create(), passando come handle di
finestra quello di CSockWnd.
*/
LONG CSockWnd::OnAsyncSelect(UINT /*wParam*/,LONG lParam)
{
WORD wWSAEvent = WSAGETSELECTEVENT(lParam); // evento (FD_READ|FD_WRITE|FD_OOB|FD_ACCEPT|FD_CONNECT|FD_CLOSE)
WORD wWSAError = WSAGETSELECTERROR(lParam); // errore winsock
if(wWSAError!=0)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -