⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 casyncsock.cpp

📁 VC网络程序设计实例导航配套代码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/*
	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 + -