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

📄 csock.cpp

📁 <Visual C++ 网络程序设计实例详解>配套源码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
/*
	CSock.cpp
	Classe derivata per interfaccia Winsock (WIN32/WINDOWS/MFC).
	Luca Piergentili, 06/07/98
	lpiergentili@yahoo.com
	http://www.geocities.com/lpiergentili/
*/
#include "env.h"
#include "pragma.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "strcpyn.h"
#include <ctype.h>
#include "window.h"
#include "CTextFile.h"
#include "CNodeList.h"
#include <winsock.h>
#include "lmhosts.h"
#include "CWinsock.h"
#include "CSock.h"

// codici di ritorno
static const int wsa_errorcode_num[] = {
	// propri
	WSA_SUCCESS,WSA_FAILURE,
	// wsa
	WSAEINTR,
	WSAEBADF,
	WSAEACCES,
	WSAEFAULT,
	WSAEINVAL,
	WSAEMFILE,
	WSAEWOULDBLOCK,
	WSAEINPROGRESS,
	WSAEALREADY,
	WSAENOTSOCK,
	WSAEDESTADDRREQ,
	WSAEMSGSIZE,
	WSAEPROTOTYPE,
	WSAENOPROTOOPT,
	WSAEPROTONOSUPPORT,
	WSAESOCKTNOSUPPORT,
	WSAEOPNOTSUPP,
	WSAEPFNOSUPPORT,
	WSAEAFNOSUPPORT,
	WSAEADDRINUSE,
	WSAEADDRNOTAVAIL,
	WSAENETDOWN,
	WSAENETUNREACH,
	WSAENETRESET,
	WSAECONNABORTED,
	WSAECONNRESET,
	WSAENOBUFS,
	WSAEISCONN,
	WSAENOTCONN,
	WSAESHUTDOWN,
	WSAETOOMANYREFS,
	WSAETIMEDOUT,
	WSAECONNREFUSED,
	WSAEDISCON,
	WSAELOOP,
	WSAENAMETOOLONG,
	WSAEHOSTDOWN,
	WSAEHOSTUNREACH,
	WSAENOTEMPTY,
	WSAEPROCLIM,
	WSAEUSERS,
	WSAEDQUOT,
	WSAESTALE,
	WSAEREMOTE,
	WSASYSNOTREADY,
	WSAVERNOTSUPPORTED,
	WSANOTINITIALISED,
	WSAHOST_NOT_FOUND,
	WSATRY_AGAIN,
	WSANO_RECOVERY,
	WSANO_DATA,
	WSANO_ADDRESS,
	// lasciare per ultimo
	WSA_UNKNOWERROR
};

// messaggi relativi ai codici di ritorno
static const char* wsa_errorcode_str[] = {
	// propri
	"WSA_SUCCESS","WSA_FAILURE",
	// wsa
	"WSAEINTR: the call was cancelled via WSACancelBlockingCall()",
	"WSAEBADF: bad file number",
	"WSAEACCES: the address specified is a broadcast address, but the socket doesn't support sending broadcast packets",
	"WSAEFAULT: the address length supplied is too small",
	"WSAEINVAL: this function shouldn't be called at this time because listen() wasnt called before accept()",
	"WSAEMFILE: the queue is empty and no descriptors are available",
	"WSAEWOULDBLOCK: this is a non-blocking socket and no connections are present",
	"WSAEINPROGRESS: a blocking call is now in progress",
	"WSAEALREADY: the non-blocking routine has already finished",
	"WSAENOTSOCK: the socket number used isn't a socket",
	"WSAEDESTADDRREQ: a destination address wasn't given",
	"WSAEMSGSIZE: the datagram was too large for the buffer and was truncated",
	"WSAEPROTOTYPE: the socket can't use the protocol specified",
	"WSAENOPROTOOPT: the option is unknown or unsupported",
	"WSAEPROTONOSUPPORT: this protocol isn't supported",
	"WSAESOCKTNOSUPPORT: this address family doesn't support the socket type specified",
	"WSAEOPNOTSUPP: the socket referenced isn't open for connection oriented services",
	"WSAEPFNOSUPPORT: the address family specified isn't supported by this protocol",
	"WSAEAFNOSUPPORT: the address family specified isn't supported by this protocol",
	"WSAEADDRINUSE: the address given is already in use",
	"WSAEADDRNOTAVAIL: the address isn't available from this machine",
	"WSAENETDOWN: Winsock has reported that the network subsystem has failed",
	"WSAENETUNREACH: the network can't be reached",
	"WSAENETRESET: Winsock dropped the connection",
	"WSAECONNABORTED: the connection was aborted due to a network failure",
	"WSAECONNRESET: the connection was reset by the remote host",
	"WSAENOBUFS: no buffer space is available",
	"WSAEISCONN: the socket is already connected",
	"WSAENOTCONN: the socket isn't connected",
	"WSAESHUTDOWN: the socket has been shut down",
	"WSAETOOMANYREFS",
	"WSAETIMEDOUT: a connection attempt timed out; no connection was established",
	"WSAECONNREFUSED: the connection was refused",
	"WSAEDISCON: the message terminated gracefully",
	"WSAELOOP",
	"WSAENAMETOOLONG",
	"WSAEHOSTDOWN",
	"WSAEHOSTUNREACH",
	"WSAENOTEMPTY",
	"WSAEPROCLIM",
	"WSAEUSERS",
	"WSAEDQUOT",
	"WSAESTALE",
	"WSAEREMOTE",
	"WSASYSNOTREADY: the network subsystem isn't ready for communications",
	"WSAVERNOTSUPPORTED: the Winsock API version requested isn't supported",
	"WSANOTINITIALISED: WSAStartup() must be called successfully before you can use this function",
	"WSAHOST_NOT_FOUND: the authoritative answer host isn't available",
	"WSATRY_AGAIN: the non-authoritative host isn't available",
	"WSANO_RECOVERY: this is a non-recoverable error or SERVERFAIL",
	"WSANO_DATA: valid name but no data record of that type",
	"WSANO_ADDRESS",
	// lasciare per ultimo
	"unknow Winsock error"
};

// dimensione dell'array
#define WSAERRORCODE_ARRAY_SIZE ARRAY_SIZE(wsa_errorcode_str)

/*
	CSock()
*/
#ifdef WIN32_MFC
CSock::CSock(CWnd* pParent/*=NULL*/)
#else
#ifdef WIN32_SDK
CSock::CSock(HWND hWnd/*=NULL*/)
#else
CSock::CSock()
#endif
#endif
{
	// ptr/handle finestra applicazione principale
#ifdef WIN32_MFC
	m_pParent = pParent;
	if(pParent)
		m_hWnd = pParent->m_hWnd;
	else
		m_hWnd = (HWND)NULL;
#else
	#ifdef WIN32_SDK
		m_hWnd = hWnd;
	#endif
#endif

	// flag per inizializzazione
	m_bInitialized = FALSE;

	// flag per visualizzazione errori
#if defined(_WINDOWS)
	m_bShowErrors = FALSE;
#endif

	// inizializza
	Reset();

	// local host
	memset(m_szLocalHostIP,'\0',sizeof(m_szLocalHostIP));
	memset(m_szLocalHostName,'\0',sizeof(m_szLocalHostName));

	// inizializza la DLL
	if((m_WsaData.error = CWinsock::WSAStartup(WSA_VERSION,&(m_WsaData.data)))!=0) 
	{
		GetWSALastError(m_WsaData.error);
		return;
	}
 
	// controlla la versione (1.1)
	if(LOBYTE(m_WsaData.data.wVersion)!=WSA_MINOR_VERSION || HIBYTE(m_WsaData.data.wVersion)!=WSA_MAJOR_VERSION)
	{
		SetWSALastError(WSAEINVAL);
		CWinsock::WSACleanup();
		return;
	}

	// ricava il nome e l'ip dell'host locale
	GetHostLocalAddr();
	GetHostLocalName();

	m_bInitialized = TRUE;
}

/*
	~CSock()
*/
CSock::~CSock(void)
{
	// chiude il socket
	Close();

	// resetta la DLL
	CWinsock::WSACleanup();
}

/*
	Init()

	Inizializzazione dei dati relativi al socket.
*/
void CSock::Init(SOCKET socket/*=INVALID_SOCKET*/,SOCKETSTATE state/*=UNDEFINED*/)
{
	m_Socket.socket = socket;
	m_Socket.status = state;
	m_Socket.error  = 0;
	m_Socket.format = PF_INET;
	m_Socket.type   = SOCK_STREAM;
	m_Socket.proto  = 0;
	memset(&m_WsaData,'\0',sizeof(WSADATA_EXT));
	ResetData();
	SetWSALastError(0);
}

/*
	Reset()

	Resetta i dati del socket.
*/
void CSock::Reset(void)
{
	m_Socket.socket = INVALID_SOCKET;
	m_Socket.status = UNDEFINED;
	m_Socket.error  = 0;
	m_Socket.format = PF_INET;
	m_Socket.type   = SOCK_STREAM;
	m_Socket.proto  = 0;
	memset(&m_WsaData,'\0',sizeof(WSADATA_EXT));
	ResetData();
	SetWSALastError(0);
}

/*
	SetFormat()

	Imposta il formato per il socket (da chiamare prima di creare il socket).
*/
int CSock::SetFormat(int nFormat/*=PF_INET*/)
{
	int nWsaError = WSANOTINITIALISED;

	// controlla che il costruttore abbia terminato correttamente
	if(IsValid())
	{
		if(m_Socket.socket==INVALID_SOCKET && m_Socket.status==UNDEFINED)
		{
			m_Socket.format = nFormat;
			nWsaError = 0;
		}
	}
	else
		SetWSALastError(nWsaError);
	
	return(nWsaError);
}

/*
	SetType()

	Imposta il tipo di socket (da chiamare prima di creare il socket).
*/
int CSock::SetType(int nType/*=SOCK_STREAM*/)
{
	int nWsaError = WSANOTINITIALISED;

	// controlla che il costruttore abbia terminato correttamente
	if(IsValid())
	{
		if(m_Socket.socket==INVALID_SOCKET && m_Socket.status==UNDEFINED)
		{
			m_Socket.type = nType;
			nWsaError = 0;
		}
	}
	else
		SetWSALastError(nWsaError);
	
	return(nWsaError);
}

/*
	SetProto()

	Imposta il protocollo per il socket (da chiamare prima di creare il socket).
*/
int CSock::SetProto(int nProto/*=0*/)
{
	int nWsaError = WSANOTINITIALISED;

	// controlla che il costruttore abbia terminato correttamente
	if(IsValid())
	{
		if(m_Socket.socket==INVALID_SOCKET && m_Socket.status==UNDEFINED)
		{
			m_Socket.proto = nProto;
			nWsaError = 0;
		}
	}
	else
		SetWSALastError(nWsaError);

	return(nWsaError);
}

/*
	SetBufferSize()

	Imposta le dimensioni dei buffer di I/O del socket.
*/
int CSock::SetBufferSize(UINT nSize/*=WSA_BUF_SIZE*/)
{
	int nWsaError;

	if(nSize < 512 || nSize > WSA_BUF_SIZE)
		nSize = WSA_BUF_SIZE;

	// dimensione del buffer di ricezione
	if(CWinsock::setsockopt(m_Socket.socket,SOL_SOCKET,SO_RCVBUF,(const char FAR *)&nSize,sizeof(int))==SOCKET_ERROR)
		nWsaError = GetWSALastError();
	else
		nWsaError = 0;

	// dimensione del buffer di invio
	if(CWinsock::setsockopt(m_Socket.socket,SOL_SOCKET,SO_SNDBUF,(const char FAR *)&nSize,sizeof(int))==SOCKET_ERROR)
		nWsaError = GetWSALastError();
	else
		nWsaError = 0;

	return(nWsaError);
}

/*
	SetTimeout()

	Imposta il tempo limite (in secondi) per il timeout sul socket.
*/
int CSock::SetTimeout(UINT nSecs/*=15*/)
{
	int nWsaError;

	if(nSecs <= 0)
		nSecs = 15;
	nSecs *= 1000;

	// timeout in ricezione
	if(CWinsock::setsockopt(m_Socket.socket,SOL_SOCKET,SO_RCVTIMEO,(const char FAR *)&nSecs,sizeof(int))==SOCKET_ERROR)
		nWsaError = GetWSALastError();
	else
		nWsaError = 0;

	// timeout in invio
	if(CWinsock::setsockopt(m_Socket.socket,SOL_SOCKET,SO_SNDTIMEO,(const char FAR *)&nSecs,sizeof(int))==SOCKET_ERROR)
		nWsaError = GetWSALastError();
	else
		nWsaError = 0;

	return(nWsaError);
}

/*
	Open()

	Apre il socket.
*/
BOOL CSock::Open(int nFormat/*=PF_INET*/,int nType/*=SOCK_STREAM*/,int nProto/*=0*/)
{
	int nWsaError = WSANOTINITIALISED;

	// 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)
			{
				m_Socket.format = nFormat;
				m_Socket.type   = nType;
				m_Socket.proto  = nProto;
				m_Socket.status = OPEN;
				nWsaError = 0;
			}
		}
	}
	else
		SetWSALastError(WSANOTINITIALISED);
	
	return(nWsaError==0);
}

/*
	Create()

	Crea un nuovo socket.
*/
SOCKET CSock::Create(void)
{
	if((m_Socket.socket = CWinsock::socket(m_Socket.format,m_Socket.type,m_Socket.proto))==INVALID_SOCKET)
		GetWSALastError();
	else
		SetBufferSize();

	return(m_Socket.socket);
}

/*
	Connect()

	Collega il socket all'host/porta specificato.
*/
BOOL CSock::Connect(LPCSTR lpcszHost,UINT nPort)
{
	LPHOSTENT pHostEnt = (LPHOSTENT)NULL;
	SOCKADDR_IN sockaddr_in;
	int nWsaError = WSANOTINITIALISED;

	// controlla che il costruttore abbia terminato correttamente
	if(IsValid())
	{
		// ricava i dati relativi all'host
		if((pHostEnt = GetHostInfo(lpcszHost))!=(LPHOSTENT)NULL)
		{
			// imposta il socket (tipo, porta, indirizzo)
			sockaddr_in.sin_family = PF_INET;
			sockaddr_in.sin_port   = CWinsock::htons((u_short)nPort);
			sockaddr_in.sin_addr   = *((LPIN_ADDR)*pHostEnt->h_addr_list);

			// collega il socket
			if(CWinsock::connect(m_Socket.socket,(SOCKADDR *)&sockaddr_in,SOCKADDR_IN_LEN)==SOCKET_ERROR)
				GetWSALastError();
			else
				nWsaError = 0;
		}
	}
	else
		SetWSALastError(WSANOTINITIALISED);

	return(nWsaError==0);
}

/*
	Abort()

	Taglia le gambe socket.
*/
BOOL CSock::Abort(void)
{
	int nWsaError = WSANOTINITIALISED;

	// controlla che il costruttore abbia terminato correttamente
	if(IsValid())
	{
		// resetta e chiude il socket
		if(m_Socket.socket!=INVALID_SOCKET && m_Socket.status!=UNDEFINED)
		{
			LINGER stLinger;
			stLinger.l_onoff = TRUE;
			stLinger.l_linger = 1;
			CWinsock::setsockopt(m_Socket.socket,SOL_SOCKET,SO_LINGER,(const char FAR *)&stLinger,sizeof(LINGER));
			CWinsock::closesocket(m_Socket.socket);
			Reset();
			nWsaError = WSAECONNABORTED;
		}
	}

	// imposta il codice d'errore
	SetWSALastError(nWsaError);

	return(nWsaError==0);
}

/*
	Close()

	Chiude il socket.
*/
BOOL CSock::Close(void)
{
	int nWsaError = WSANOTINITIALISED;

	// controlla che il costruttore abbia terminato correttamente
	if(IsValid())
	{
		// chiude e resetta il socket
		if(m_Socket.socket!=INVALID_SOCKET && m_Socket.status!=UNDEFINED)
		{
			nWsaError = Shutdown();
			Reset();
		}
	}

	// imposta il codice d'errore
	SetWSALastError(nWsaError);

	return(nWsaError==0);
}

/*
	Shutdown()

	Sdraia il socket.
*/
int CSock::Shutdown(LPSTR lpszDiscard/*=NULL*/,int nSize/*=0*/)
{
	int nWsaError = 0;
	int remain = 1;
	int offset = 0;

	// disabilita il socket (solo in invio) per una chiusura morbida
	if(CWinsock::shutdown(m_Socket.socket,1)==SOCKET_ERROR)

⌨️ 快捷键说明

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