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

📄 cnet.cpp

📁 这是我用vc编写的一个黑白棋网络游戏的使用程序
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// Cnet.cpp: implementation of the CCnet class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "BWChess.h"
#include "Cnet.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

#define	BACKLOG		10
#define TIMEOUT		10

long CNetworking::m_count = 0;
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CNetworking::CNetworking () : m_lasterror (0)
{
	if (m_count == 0 && CConnection::m_count == 0)
	{
		WSADATA	wsd;
		int		err;

		err = WSAStartup (MAKEWORD (1, 1), &wsd);

		if (err != 0)
			throw CError (err);
	}

	hAcceptEvent = NULL;
	hAcceptFunc = NULL;

	dwAcceptThreadID = 0;
	hAcceptThread = NULL;

	m_socket = INVALID_SOCKET;

	m_count ++;
}

CNetworking::~CNetworking ()
{
	StopListen ();

	if (m_count == 1 && CConnection::m_count == 0)
		WSACleanup();

	m_count --;
}

void CNetworking::SetLastError (long err)
{
	m_sync.Enter ();
	m_lasterror.m_number = err;
	m_sync.Leave ();
}

void CNetworking::GetLastError (char* str, long len)
{
	m_sync.Enter ();
	m_lasterror.GetErrorString (str, len);
	m_sync.Leave ();
}

bool CNetworking::Listen (int port)
{
	if (IsListening ())
		StopListen ();

	sockaddr_in	addr;
	SOCKET		sock;

	sock = socket(AF_INET, SOCK_STREAM, 0);			// Create socket

	addr.sin_family = AF_INET;						// Address family Internet
	addr.sin_port = htons ((u_short)port);					// Assign port 'port' to this socket
	addr.sin_addr.s_addr = htonl (INADDR_ANY);		// No destination

	if (bind (sock, (LPSOCKADDR) &addr, sizeof (addr)) == SOCKET_ERROR)
	{
		closesocket (sock);
		long err = WSAGetLastError ();
		CNetworking::SetLastError (err);
		return false;
	}

	if (listen (sock, BACKLOG) == SOCKET_ERROR)
	{
		closesocket (sock);
		long err = WSAGetLastError ();
		CNetworking::SetLastError (err);
		return false;
	}

	m_sync.Enter ();
	m_socket = sock;
	m_addr = addr;
	m_sync.Leave ();

	hAcceptThread = CreateThread (NULL,
								  0,
								  (LPTHREAD_START_ROUTINE) AcceptThread,
								  this,
								  0,
								  (LPDWORD) &dwAcceptThreadID);
	if (!hAcceptThread)
	{
		StopListen ();
		return false;
	}

	return true;
}

void CNetworking::StopListen ()
{
	if (!IsListening ())
	{
		CNetworking::SetLastError (WSAENOTCONN);
		return;
	}

	m_sync.Enter ();
	closesocket (m_socket);
	m_socket = INVALID_SOCKET;
	m_sync.Leave ();

	WaitForSingleObject (hAcceptThread, INFINITE);
}

void CNetworking::SetAcceptFunc (CALLBACKFUNC hFunc)
{
	m_sync.Enter ();
	hAcceptFunc = hFunc;
	m_sync.Leave ();
}

void CNetworking::SetAcceptEvent (HANDLE hEvent)
{
	m_sync.Enter ();
	hAcceptEvent = hEvent;
	m_sync.Leave ();
}

CConnection* CNetworking::GetAccepted ()
{
	CConnection* cAccepted;

	m_sync.Enter ();
	cAccepted = m_accepted.Remove ();
	m_sync.Leave ();

	return cAccepted;
}

int CNetworking::HasAccepted ()
{
	int iAccepted;

	m_sync.Enter ();
	iAccepted = m_accepted.Length ();
	m_sync.Leave ();

	return iAccepted;
}

bool CNetworking::IsListening ()
{
	bool bListening;

	m_sync.Enter ();
	bListening = m_socket != INVALID_SOCKET;
	m_sync.Leave ();

	return bListening;
}

int CNetworking::AcceptWait ()
{
	int			addr_size = sizeof (sockaddr_in);

	SOCKET		lsock;
	SOCKET		csock = INVALID_SOCKET;
	sockaddr_in	caddr = { 0 };

	m_sync.Enter ();
	lsock = m_socket;
	m_sync.Leave ();

	while (IsListening ())
	{
		m_sync.Enter ();
		bool bRightSock = (lsock == m_socket);
		m_sync.Leave ();
		if (!bRightSock) return 1;

		csock = accept (lsock, (LPSOCKADDR) &caddr, &addr_size); // accept a connection
		if (csock == INVALID_SOCKET)
		{
			int aErr = WSAGetLastError();
			if (aErr == WSAEINTR)
			{
				StopListen ();
				return 1;
			}
			else
			{
				//	error: could not accept
				long err = WSAGetLastError ();
				CNetworking::SetLastError (err);

				StopListen ();
				return 1;
			}
		}
		else
		{
			CConnection* cAccepted = new CConnection ();
			cAccepted->m_socket = csock;
			cAccepted->m_addr = caddr;

			cAccepted->hRecvThread = CreateThread (NULL,
												   0,
												   (LPTHREAD_START_ROUTINE) cAccepted->RecvThread,
												   cAccepted,
												   0,
												   (LPDWORD) &cAccepted->dwRecvThreadID);

			if (cAccepted->hRecvThread == NULL)
			{
				cAccepted->Disconnect ();
				CNetworking::SetLastError (1002);
			}
			else
			{
				m_sync.Enter ();
				m_accepted.Add (cAccepted);

				HANDLE hEvent = hAcceptEvent;
				CALLBACKFUNC fncCallback = hAcceptFunc;
				m_sync.Leave ();

				if (hEvent) SetEvent (hEvent);				//	if an event was given, pulse the event
				if (fncCallback) (fncCallback) ((DWORD) this);	//	if a function ptr was given, call the function
			}
		}
	}

	return 0;
}

int CNetworking::AcceptThread (void* pThis)
{
	return ((CNetworking*) (pThis))->AcceptWait ();
}

bool CNetworking::GetNeighborhood(char* names, int len)
{
	DWORD	status;
	HANDLE	hEnum;
	DWORD	cbBuffer = 16384;
	DWORD	cEntries = 0xffffffff;
	LPNETRESOURCE lpnr;
	DWORD	namesLast = 0;
	char	nms[2048] = "";

	status = WNetOpenEnum (RESOURCE_CONTEXT, RESOURCETYPE_ANY, 0, NULL, &hEnum);
	if (status != NO_ERROR)
		return false;

	do
	{
		lpnr = (LPNETRESOURCE) GlobalAlloc (GPTR, cbBuffer);
		status = WNetEnumResource (hEnum, &cEntries, lpnr, &cbBuffer);

		if (status == NO_ERROR)
		{
			for(DWORD i = 0; i < cEntries; i++)
			{
				if (lpnr[i].lpRemoteName != NULL)
				{	// it is a computer in the network...
					if (lpnr[i].lpRemoteName[0] == '\\' && lpnr[i].lpRemoteName[1] == '\\')
					{	// recheck, if it really is a computer (because of the "\\")
						int rname_len = strlen (lpnr[i].lpRemoteName);

						for (int j = 2; j < rname_len; j++)
							nms[namesLast + j - 2] = lpnr[i].lpRemoteName[j];

						namesLast += (rname_len - 2);
						nms[namesLast] = 13;
						namesLast++;
					}
				}
			}
		}
		else if (status != ERROR_NO_MORE_ITEMS )
		{
			GlobalFree ((HGLOBAL) lpnr);
			WNetCloseEnum (hEnum);
			return false;
		}

		GlobalFree ((HGLOBAL) lpnr);
	}
	while (status != ERROR_NO_MORE_ITEMS);
	WNetCloseEnum (hEnum);

	memset (names, 0, len);

	int uselen = 2048;
	if (len < uselen) uselen = len;

	memcpy (names, nms, uselen);

	return true;
}

bool CNetworking::GetLocalName(char *localname, int len)
{
	char locname[512] = "";

	int status = gethostname (locname, 512);

	if (status != 0)
	{
		long err = WSAGetLastError ();
		CNetworking::SetLastError (err);
		return false;
	}

	memset (localname, 0, len);

	int uselen = strlen (locname) + 1;
	if (uselen > len) uselen = len;

	memcpy (localname, locname, uselen);

	return true;
}

bool CNetworking::GetLocalIP(char *localip, int len)
{
	char locname[512];
	char locip[16];

	if (!(GetLocalName(locname, 512) && ResolveIP(locname, locip, 16)))
		return false;
	// not raising an error, bcause GetLocalName or ResolveIP already did it

	memset (localip, 0, len);

	int uselen = strlen (locip) + 1;
	if (len < uselen) uselen = len;

	memcpy (localip, locip, uselen);

	return true;
}

bool CNetworking::GetLocalIPs(char *localips, int len)
{
	char locname[512] = "";
	char locips[256] = "";

	if (!GetLocalName(locname, 512) || !ResolveIPs(locname, locips, 256))
		return false;

	memset (localips, 0, len);

	int uselen = strlen (locips) + 1;
	if (len < uselen) uselen = len;

	memcpy (localips, locips, uselen);

	return true;
}

bool CNetworking::ResolveName(char *hostip, char *hostname, int len)
{
	unsigned long hstaddr = inet_addr (hostip);
	hostent* phe = gethostbyaddr ((char*) &hstaddr, sizeof (unsigned long), AF_INET);

	if (phe == NULL)
	{
		long err = WSAGetLastError ();
		CNetworking::SetLastError (err);
		return false;
	}

	char *hstname = (char*) phe->h_name;

	memset (hostname, 0, len);

	int uselen = strlen (hstname) + 1;
	if (len < uselen) uselen = len;

	memcpy (hostname, hstname, uselen);

	return true;
}

bool CNetworking::ResolveIP(char *hostname, char *hostip, int len)
{
	hostent* phe = gethostbyname (hostname);

	if (phe == NULL)
	{
		long err = WSAGetLastError ();
		CNetworking::SetLastError (err);
		return false;
	}

	char hstip[15] = "";
	if (phe->h_addr_list[0] != NULL)
	{
		sprintf (hstip, "%u.%u.%u.%u", 
			(unsigned char) phe->h_addr_list[0][0],
			(unsigned char) phe->h_addr_list[0][1],
			(unsigned char) phe->h_addr_list[0][2],
			(unsigned char) phe->h_addr_list[0][3]);
	}
	else
	{
		long err = WSAGetLastError ();
		CNetworking::SetLastError (err);
		return false;
	}

	memset (hostip, 0, len);

	int uselen = strlen (hstip) + 1;
	if (len < uselen) uselen = len;

	memcpy (hostip, hstip, uselen);

	return true;
}

bool CNetworking::ResolveIPs(char *hostname, char *hostips, int len)
{
	hostent *phe = gethostbyname (hostname);
	char	allips[256], null_ip[256];

	if (phe == NULL || phe->h_addr_list[0] == NULL)
	{
		long err = WSAGetLastError ();
		CNetworking::SetLastError (err);
		return false;
	}
	
	int count = 0,
		i = 0;

	for (i = 0; i < 256; i++)
	{
		allips[i] = 0;
		null_ip[i] = 0;
	}

	while (phe->h_addr_list[count] != NULL && count * 15 < 240)
	{
		char oneip[15] = "";
		for (i = 0; i < 15; i++)
			oneip[i] = 0;

		sprintf(oneip, "%u.%u.%u.%u", 
			(unsigned char) phe->h_addr_list[count][0],
			(unsigned char) phe->h_addr_list[count][1],
			(unsigned char) phe->h_addr_list[count][2],
			(unsigned char) phe->h_addr_list[count][3]);

		for (i = (count * 15); i < (count * 15 + 15); i++)
			null_ip[i] = oneip[i % 15];

		count++;
	}

	int lEnd = 0;
	for (i = 0; i < 15; i++)
	{
		if (null_ip[i * 15] == 0) break;
		for (int j = 0; j < 15; j++)
			allips[lEnd + j] = null_ip[i * 15 + j];

		lEnd = strlen(allips);
		allips[lEnd] = 13;
		lEnd ++;
	}

	for (i = 0; i < len; i++)
		hostips[i] = 0;

	int uselen = strlen(allips);
	if (uselen > len) uselen = len;

	for (i = 0; i < uselen; i++)
		hostips[i] = allips[i];
	hostips[uselen] = 0;

	return true;
}

long CConnection::m_count = 0;

CConnection::CConnection () : m_lasterror (0)
{
	if (m_count == 0 && CNetworking::m_count == 0)
	{
		WSADATA	wsd;
		int		err;

		err = WSAStartup (MAKEWORD (1, 1), &wsd);

		if (err != 0)
			throw CError (err);
	}

	m_lasterror.m_number = 0;

	m_event = CreateEvent (NULL, TRUE, FALSE, NULL);
	hCloseEvent = NULL;
	hCloseFunc = NULL;
	hRecvEvent = NULL;
	hRecvFunc = NULL;

	dwRecvThreadID = 0;
	hRecvThread = NULL;

	m_socket = INVALID_SOCKET;

	m_count ++;
}

CConnection::CConnection (const char* host, unsigned short port) : m_lasterror (0)
{
	if (m_count == 0 && CNetworking::m_count == 0)
	{
		WSADATA	wsd;
		int		err;

		err = WSAStartup (MAKEWORD (1, 1), &wsd);

		if (err != 0)
			throw CError (err);
	}

	m_event = CreateEvent (NULL, TRUE, FALSE, NULL);
	hCloseEvent = NULL;
	hCloseFunc = NULL;
	hRecvEvent = NULL;
	hRecvFunc = NULL;

	dwRecvThreadID = 0;
	hRecvThread = NULL;

	m_socket = INVALID_SOCKET;

	m_count ++;

	if (!Connect (host, port))
	{
		long err = WSAGetLastError ();

		if (err == 0)
			err = m_lasterror.m_number;

		throw CError (err);
	}
}

CConnection::~CConnection ()
{
	Disconnect ();

	if (m_count == 1 && CNetworking::m_count == 0)
		WSACleanup();

	CloseHandle (m_event);
	m_count --;
}

void CConnection::SetLastError (long err)
{
	m_sync.Enter ();
	m_lasterror.m_number = err;
	m_sync.Leave ();
}

void CConnection::GetLastError (char* str, long len)
{
	m_sync.Enter ();
	m_lasterror.GetErrorString (str, len);
	m_sync.Leave ();
}

bool CConnection::Connect (const char* host, unsigned short port)
{
	Disconnect ();

	sockaddr_in	addr;
	SOCKET		sock;

	sock = socket (AF_INET, SOCK_STREAM, 0);	// create socket
	addr.sin_family = AF_INET;					// address family Internet
	addr.sin_port = htons (port);				// set server port number
	addr.sin_addr.s_addr = inet_addr (host);	// set server IP

	if (connect (sock, (LPSOCKADDR) &addr, sizeof (addr)) == SOCKET_ERROR)
	{
		long err = WSAGetLastError ();
		CConnection::SetLastError (err);
		return false;
	}

⌨️ 快捷键说明

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