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

📄 csock.cpp

📁 <Visual C++ 网络程序设计实例详解>配套源码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
		nWsaError = GetWSALastError();

	// legge gli eventuali dati rimanenti
	while(remain!=0 && remain!=SOCKET_ERROR)
	{
		// se non viene passato nessun buffer, scarta i dati pendenti
		if(lpszDiscard)
		{
			remain = CWinsock::recv(m_Socket.socket,&lpszDiscard[offset],nSize,0);
			if(remain!=0 && remain!=SOCKET_ERROR)
			{
				nSize -= remain;
				offset += remain;
			}
		}
		else
		{
			remain = SOCKET_ERROR;
		}
	}

	// resetta il codice d'errore
	SetWSALastError(0);

	// chiude il socket
	if(CWinsock::closesocket(m_Socket.socket)==SOCKET_ERROR)
		nWsaError = GetWSALastError();

	return(nWsaError);
}

/*
	GetIPAddress()

	Ricava l'ip relativo al socket.
*/
LPCSTR CSock::GetIPAddress(SOCKET socket/*=INVALID_SOCKET*/)
{
	unsigned char* ip;
	static char ip_addr[IP_ADDRESS_SIZE+1];
	SOCKADDR_IN sockaddr_in;
	int sockaddr_size = sizeof(SOCKADDR_IN);

	strcpyn(ip_addr,NULL_HOST,sizeof(ip_addr));

	// controlla che il costruttore abbia terminato correttamente
	if(IsValid())
	{
		// ricava l'ip del socket
		if(socket==INVALID_SOCKET)
			socket = m_Socket.socket;

		if(CWinsock::getsockname(socket,(SOCKADDR*)&sockaddr_in,&sockaddr_size)==0)
		{
			ip = (unsigned char*)&(sockaddr_in.sin_addr);
			_snprintf(ip_addr,sizeof(ip_addr)-1,"%i.%i.%i.%i",ip[0],ip[1],ip[2],ip[3]);
		}
		else
			GetWSALastError();
	}
	else
		SetWSALastError(WSANOTINITIALISED);

	return(ip_addr);
}

/*
	CreateListenSocket()

	Crea il socket da mettere in ascolto per le connessioni.
	Notare che la funzione crea un socket di tipo PF_INET(arpa)/SOCK_STREAM(tcp)/protocollo di default.
*/
#if defined(_WINDOWS)
SOCKET CSock::CreateListenSocket(HWND hWnd,UINT uMsg,UINT nPort)
{
	int nWsaError = WSANOTINITIALISED;
	SOCKADDR_IN sockaddr_in;
	int sockaddr_size = sizeof(SOCKADDR_IN);

	// controlla che il costruttore abbia terminato correttamente
	if(IsValid())
	{
		// controlla che il socket non sia gia' aperto
		if(m_Socket.socket==INVALID_SOCKET && m_Socket.status==UNDEFINED)
		{
			if(Create()!=INVALID_SOCKET)
			{
				// arpa/tcp/protocollo di default
				m_Socket.format = PF_INET;
				m_Socket.type   = SOCK_STREAM;
				m_Socket.proto  = 0;
				m_Socket.status = OPEN;

				// famiglia=ARPA, porta=[input], indirizzo=qualunque (INADDR_ANY, per cui bind() utilizza l'indirizzo TCP/IP del computer)
				sockaddr_in.sin_family           = PF_INET;
				sockaddr_in.sin_port             = (u_short)CWinsock::htons((u_short)nPort);
				sockaddr_in.sin_addr.S_un.S_addr = INADDR_ANY;

				// configura il socket per la modalita' asincrona e registra gli eventi da monitorare
				if(CWinsock::WSAAsyncSelect(m_Socket.socket,hWnd,uMsg,FD_CONNECT|FD_ACCEPT|FD_READ|FD_WRITE|FD_CLOSE)==0)
				{
					// da' il nome al socket
					if(CWinsock::bind(m_Socket.socket,(SOCKADDR *)&sockaddr_in,sockaddr_size)==0)
					{
						// mette il socket in ascolto
						if(CWinsock::listen(m_Socket.socket,5)==0)
							nWsaError = 0;
					}
				}

				if(nWsaError!=0)
					GetWSALastError();
			}
		}
	}
	else
		SetWSALastError(WSANOTINITIALISED);
	
	return(nWsaError==0 ? INVALID_SOCKET : m_Socket.socket);
}
#endif

/*
	AcceptConnectingSocket()

	Accetta la connessione sul socket.
*/
#if defined(_WINDOWS)
CSock* CSock::AcceptConnectingSocket(HWND hWnd,UINT uMsg)
{
	SOCKET socket;
	SOCKADDR_IN sockaddr_in;
	int sockaddr_size = sizeof(SOCKADDR_IN);
	CSock* pSocket = NULL;

	// controlla che il costruttore abbia terminato correttamente
	if(IsValid())
	{
		// accetta la connessione sul socket in ascolto
		if((socket = CWinsock::accept(m_Socket.socket,(SOCKADDR*)&sockaddr_in,&sockaddr_size))!=INVALID_SOCKET)
		{
			// imposta gli eventi da monitorare
			CWinsock::WSAAsyncSelect(socket,hWnd,uMsg,FD_CONNECT|FD_ACCEPT|FD_READ|FD_WRITE|FD_CLOSE);
			
			pSocket = new CSock();
			if(pSocket)
				pSocket->Init(socket,OPEN);
		}
		else
			GetWSALastError();
	}
	else
		SetWSALastError(WSANOTINITIALISED);

	return(pSocket);
}
#endif

/*
	Send()

	Invia i dati presenti nel buffer di output.
*/
int CSock::Send(int nLen/*=-1*/)
{
	int nSent = SOCKET_ERROR;

	// controlla che il costruttore abbia terminato correttamente
	if(IsValid())
	{
		// calcola la dimensione del buffer
		// (se non viene passato il numero di bytes da inviare, il buffer deve essere terminato con \0)
		nLen = (nLen <= 0 ? strlen(m_szSendBuffer) : nLen);
		if(nLen > 0 && nLen <= WSA_BUF_SIZE)
		{
			// invia i dati
			if((nSent = CWinsock::send(m_Socket.socket,(const char FAR *)m_szSendBuffer,nLen,0))==SOCKET_ERROR)
				GetWSALastError();
		}
		else
			SetWSALastError(WSAENOBUFS);
	}
	else
		SetWSALastError(WSANOTINITIALISED);

	return(nSent);
}

/*
	Send()

	Invia i dati.
*/
int CSock::Send(LPCSTR pData,int nLen)
{
	int nSent = SOCKET_ERROR;

	// controlla che il costruttore abbia terminato correttamente
	if(IsValid())
	{
		// invia i dati
		if((nSent = CWinsock::send(m_Socket.socket,(const char FAR *)pData,nLen,0))==SOCKET_ERROR)
			GetWSALastError();
	}
	else
		SetWSALastError(WSANOTINITIALISED);

	return(nSent);
}

/*
	Receive()

	Riceve i dati.
*/
const char* CSock::Receive(int* nRecv/*=NULL*/,int nLen/*=-1*/)
{
	int nReceived = SOCKET_ERROR;
	int nWsaError = WSANOTINITIALISED;

	// controlla che il costruttore abbia terminato correttamente
	if(IsValid())
	{
		// calcola il numero di bytes da ricevere
		// (se non viene passato il numero di bytes da ricevere, assume WSA_BUF_SIZE)
		nLen = (nLen <= 0 ? WSA_BUF_SIZE : nLen);
		if(nLen > 0 && nLen <= WSA_BUF_SIZE)
		{
			// riceve i dati
			if((nReceived = CWinsock::recv(m_Socket.socket,(char FAR *)m_szRecvBuffer,nLen,0))!=SOCKET_ERROR)
			{
				nWsaError = 0;
				m_szRecvBuffer[nReceived] = '\0';
			}
			else
				nWsaError = GetWSALastError();
		}
		else
			nWsaError = WSAENOBUFS;
	}
	else
		nWsaError = WSANOTINITIALISED;

	if(nWsaError!=0)
		SetWSALastError(nWsaError);

	if(nRecv)
		*nRecv = nReceived;

	return(nReceived!=SOCKET_ERROR ? m_szRecvBuffer : NULL);
}

/*
	Receive()

	Riceve i dati nel buffer di input.
*/
int CSock::Receive(LPSTR pBuffer,int nLen)
{
	int nReceived = SOCKET_ERROR;

	// controlla che il costruttore abbia terminato correttamente
	if(IsValid())
	{
		// riceve i dati
		if((nReceived = CWinsock::recv(m_Socket.socket,(char FAR *)pBuffer,nLen,0))==SOCKET_ERROR)
			GetWSALastError();
		else
			pBuffer[nReceived] = '\0';
	}
	else
		SetWSALastError(WSANOTINITIALISED);

	return(nReceived);
}

/*
	GetLocalHostName()

	Restituisce il nome dell'host locale.
*/
LPCSTR CSock::GetLocalHostName(void)
{
	// controlla che il costruttore abbia terminato correttamente
	if(!IsValid())
	{
		SetWSALastError(WSANOTINITIALISED);
		return(NULL);
	}
	else
		return(m_szLocalHostName);
}

/*
	GetLocalHostAddr()

	Restituisce l'indirizzo ip dell'host locale.
*/
LPCSTR CSock::GetLocalHostAddr(void)
{
	// controlla che il costruttore abbia terminato correttamente
	if(!IsValid())
	{
		SetWSALastError(WSANOTINITIALISED);
		return(NULL);
	}
	else
		return(m_szLocalHostIP);
}

/*
	GetHostLocalName()

	Ricava il nome dell'host locale.
*/
LPCSTR CSock::GetHostLocalName(void)
{
	char* p = m_szLocalHostName;
	
	//  ricava il nome
	if(CWinsock::gethostname(m_szLocalHostName,sizeof(m_szLocalHostName))==SOCKET_ERROR)
	{
		GetWSALastError();
		memset(m_szLocalHostName,'\0',sizeof(m_szLocalHostName));
		p = NULL;
	}

	return(p);
}

/*
	GetHostLocalAddr()

	Ricava l'ip dell'host locale.
*/
LPCSTR CSock::GetHostLocalAddr(void)
{
	LPHOSTENT pHostEnt;
	SOCKADDR_IN sockaddr_in_local;
	SOCKADDR_IN sockaddr_in_remote;
	int sockaddr_size = sizeof(SOCKADDR);
	char* p = NULL;

	// inizializza l'indirizzo locale
	strcpy(m_szLocalHostIP,NULL_HOST);
	sockaddr_in_local.sin_addr.s_addr = INADDR_ANY;

	// ricava il nome
	if(CWinsock::gethostname(m_szLocalHostName,sizeof(m_szLocalHostName))!=SOCKET_ERROR)
	{
		// ricava le informazioni sull'host relative al nome
		if((pHostEnt = CWinsock::gethostbyname(m_szLocalHostName))!=(LPHOSTENT)NULL)
		{
			sockaddr_in_local.sin_addr.s_addr = *((u_long FAR*)(pHostEnt->h_addr));
			strncpy(m_szLocalHostIP,CWinsock::inet_ntoa(sockaddr_in_local.sin_addr),HOSTNAME_SIZE);
			p = m_szLocalHostIP;
		}
	} 

	// errore, prova con un socket fittizzio
	if(sockaddr_in_local.sin_addr.s_addr==INADDR_ANY)
	{
		SOCKET socket;

		// prova con un socket UDP
		if((socket = CWinsock::socket(AF_INET,SOCK_DGRAM,0))!=INVALID_SOCKET)
		{
			// collega ad un indirizzo fittizzio (non usare il loopback) */
			sockaddr_in_remote.sin_family		= AF_INET;
			sockaddr_in_remote.sin_port		= CWinsock::htons(IPPORT_ECHO);
			sockaddr_in_remote.sin_addr.s_addr	= CWinsock::inet_addr(DUMMY_HOST);

			if(CWinsock::connect(socket,(LPSOCKADDR)&sockaddr_in_remote,sizeof(SOCKADDR))!=SOCKET_ERROR)
			{
				// ricava l'indirizzo locale
				if(CWinsock::getsockname(socket,(LPSOCKADDR)&sockaddr_in_local,(int FAR*)&sockaddr_size)!=SOCKET_ERROR)
				{
					strncpy(m_szLocalHostIP,CWinsock::inet_ntoa(sockaddr_in_local.sin_addr),HOSTNAME_SIZE);
					p = m_szLocalHostIP;
				}
			}
			
			CWinsock::closesocket(socket);
		}
	}

	return(p);
}

/*
	GetHostByName()

	Ricava l'ip dell'host a partire del nome.
*/
LPCSTR CSock::GetHostByName(LPCSTR lpcszHost)
{
	LPHOSTENT pHostEnt;
	char* pHostAddr = NULL;
	
	if((pHostEnt = GetHostInfo(lpcszHost))!=(LPHOSTENT)NULL)
	{
		struct in_addr st_addr;
		st_addr.s_addr = *((u_long FAR*)(pHostEnt->h_addr));
		pHostAddr = CWinsock::inet_ntoa(st_addr);
	}

	return(pHostAddr);
}

/*
	GetHostByAddr()

	Ricava il nome dell' host partire dell'indirizzo ip.
*/
const char* CSock::GetHostByAddr(const char* lpcszHostAddr)
{
	LPHOSTENT pHostEnt;
	char* pHostName = NULL;
	
	if((pHostEnt = GetHostInfo(lpcszHostAddr))!=(LPHOSTENT)NULL)
		pHostName = pHostEnt->h_name;

	return(pHostName);
}

/*
	GetHostInfo()

	Ricava le informazioni relative all'host specificato, distinguendo se si sta' referenziando
	l'host locale (ad es. MiPC.medusa.es o 127.0.0.1) o meno.
	Notare che considera come host locale il nome del computer (MiPC.medusa.es) o quanto indicato
	dalla macro LOCAL_HOST (vedi lmhosts.h).
	L' host puo' essere specificato nei due formati: stringa (MiPC.medusa.es) o n.n.n.n (127.0.0.1).
	Il formato utilizzato per il socket e' PF_INET.
*/
LPHOSTENT CSock::GetHostInfo(LPCSTR lpcszHost)
{
	// valori per la struct HOSTENT statica
	static char* host_alias[] = {NULL,NULL};
	static struct in_addr st_addr;
	st_addr.S_un.S_addr = LOCAL_HOST_NUM;
	static char* host_names[] = {(char FAR *)&st_addr,NULL};
	static HOSTENT host_ent = {0};
	LPHOSTENT pHostEnt = (LPHOSTENT)NULL;

	// controlla che il costruttore abbia terminato correttamente
	if(!IsValid())
	{
		SetWSALastError(WSANOTINITIALISED);
		return((LPHOSTENT)NULL);
	}

	// se viene referenziato l'host locale collega sulla struttura interna
	if(strcmp(lpcszHost,m_szLocalHostName)==0 || strcmp(lpcszHost,host_names[0])==0 || strcmp(lpcszHost,LOCAL_HOST)==0)
	{
		host_ent.h_name      = m_szLocalHostName;
		host_ent.h_aliases   = host_alias;
		host_ent.h_addrtype  = PF_INET;
		host_ent.h_length    = 4;
		host_ent.h_addr_list = host_names;
		pHostEnt             = &host_ent;
	}
	else
	{
		unsigned long lAddr;

		/* "n.n.n.n" -> long */
		if((lAddr=CWinsock::inet_addr(lpcszHost))!=INADDR_NONE)
			pHostEnt = CWinsock::gethostbyaddr((const char FAR *)&lAddr,4,PF_INET); // n.n.n.n (long)
		else
			pHostEnt = CWinsock::gethostbyname((const char FAR *)lpcszHost); // "host.domain"
	}

	if(pHostEnt==(LPHOSTENT)NULL)
		GetWSALastError();

	return(pHostEnt);
}

/*
	GetServiceByName()

	Ricava il # della porta corrispondente al servizio.
	Prima di chiamare winsock controlla nel database (locale).
*/
int CSock::GetServiceByName(LPCSTR lpcszService,LPCSTR lpcszProto/*="tcp"*/,BOOL bUseLocalDabatase/*=TRUE*/)
{
	struct servent *se;
	int port = -1;

	// cerca il servizio nell'array
	if(bUseLocalDabatase)
	{
		if(m_pServicesList.Count() <= 0)
			LoadServices();

		ITERATOR iter;
		SERVICES* s;
		if((iter = m_pServicesList.First())!=(ITERATOR)NULL)
			while(iter!=(ITERATOR)NULL)
			{
				s = (SERVICES*)iter->data;
				
				if(stricmp(lpcszService,s->service)==0)
					if(stricmp(lpcszProto,s->proto)==0)
					{
						port = s->port;
						break;
					}

				iter = m_pServicesList.Next(iter);
			}
	}

	// se non trova il servizio chiama winsock
	if(port < 0)
		if((se = CWinsock::getservbyname(lpcszService,lpcszProto))!=(struct servent *)NULL)
			port = (int)se->s_port;

	return(port);
}

/*
	GetServiceByPort()

	Ricava il nome del servizio corrispondente al # porta.
	Prima di chiamare winsock controlla nel database (locale).
*/
LPCSTR CSock::GetServiceByPort(UINT port,LPCSTR lpcszProto/*="tcp"*/,BOOL bUseLocalDabatase/*=TRUE*/)
{
	struct servent *se;
	char* p;
	static char name[SERVICE_NAME + 1];
	
	p = NULL;
	memset(name,'\0',sizeof(name));

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -