www.pudn.com > Paint_SockAPI.rar > CConnection.cpp


/* 
* Copyright (c) 2003,Rainsoft Studio 
* All rights reserved. 
* 
* 文件名称:CConnection.cpp 
* 文件标识:04-02 
* 摘要:网络传输类,使用WinSock 
* 
* 当前版本:1.0 
* 作者:try2it.com 
* 完成日期:2003年07月30日 
*/ 
 
#include "StdAfx.h" 
#include "CConnection.h" 
 
#define	BACKLOG		10 
#define TIMEOUT		10 
 
long CNetworking::m_count = 0; 
// 构建函数,初始化套接口 
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 (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_socket 
	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; 
} 
// 获取本地IP地址 
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; 
} 
// 获取本地的所有IP地址 
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; 
} 
// 通过查找IP来获取远端机器名 
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; 
} 
// 通过查找机器名来获取远端机器的IP地址 
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; 
} 
// 通过查找机器名来获取远端机器的所有IP地址 
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 (); 
    // m_count == 1 表示最后一个析构了,所有的连接都不存在了 
	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; 
	} 
    // 调用CloseSocket时,是否等待缓冲区中的数据发送完 
	linger lg; 
	lg.l_onoff = 1; // 等待 
	lg.l_linger = 1;// 1秒 
	// 设置套接字属性 
	setsockopt (sock, SOL_SOCKET, SO_LINGER, reinterpret_cast  (&lg), sizeof (linger)); 
    // 创建接收线程 
	hRecvThread = CreateThread (NULL, 
								0, 
								(LPTHREAD_START_ROUTINE) RecvThread, 
								this, 
								0, 
								(LPDWORD) &dwRecvThreadID); 
 
	if (hRecvThread == NULL) 
	{ 
		CConnection::SetLastError (1002); 
		closesocket (sock); 
		return false; 
	} 
    // 保存套接字和地址信息 
	m_sync.Enter (); 
	m_socket = sock; 
	m_addr = addr; 
	m_sync.Leave (); 
 
	return true; 
} 
// 断开连接 
void CConnection::Disconnect () 
{ 
    // 没有连接,出错 
	if (!IsConnected ()) 
	{ 
		CConnection::SetLastError (WSAENOTCONN); 
		return; 
	} 
 
	int		status; 
	fd_set	readfds; 
	timeval	timeout; 
 
	//	设置事件为non-signaled 
	ResetEvent (m_event); 
     
	m_sync.Enter (); 
	SOCKET s = m_socket; 
	m_socket = INVALID_SOCKET; 
	m_sync.Leave (); 
 
/* 
#define SD_RECEIVE      0x00 
#define SD_SEND         0x01 
#define SD_BOTH         0x02 
*/ 
    // 禁止发送数据 
	shutdown (s, 0x01); 
 
	FD_ZERO (&readfds); 
	FD_SET (s, &readfds); 
 
	timeout.tv_sec = TIMEOUT; 
	timeout.tv_usec = 0; 
 
	status = select (1, &readfds, NULL, NULL, &timeout); 
	if (status == SOCKET_ERROR) 
	{ 
		int err = WSAGetLastError(); 
		CConnection::SetLastError (err); 
	} 
 
	//	now wait until receive-thread is done (5 seconds max!) 
	//Sleep (10); 
	WaitForSingleObject (hRecvThread, 5000); 
	closesocket (s); 
 
	DWORD dwExitCode; 
	GetExitCodeThread (hRecvThread, &dwExitCode); 
	// 如果接收线程还在活动 
	if (dwExitCode == STILL_ACTIVE) 
	{ 
		//	wait for the event to be set and then reset 
		WaitForSingleObject (m_event, 2000); 
		ResetEvent (m_event); 
 
		//	if still active, we might have a dead-lock 
		//	might be caused by the callback fct 
		TerminateThread (hRecvThread, 0); 
	} 
	hRecvThread = NULL; 
} 
// 获取服务器断点的信息 
bool CConnection::PeerInfo (char* host, int host_len, unsigned int* port) 
{ 
	if (!IsConnected ()) 
	{ 
		CConnection::SetLastError (WSAENOTCONN); 
		return false; 
	} 
 
	sockaddr_in addr; 
 
	m_sync.Enter (); 
	addr = m_addr; 
	m_sync.Leave (); 
 
	if (port != NULL) 
		*port = (unsigned int) ntohs (addr.sin_port); 
 
	if (host != NULL) 
	{ 
		char* ip = inet_ntoa (addr.sin_addr); 
 
		memset (host, 0, host_len); 
 
		int uselen = strlen (ip) + 1; 
		if (host_len < uselen) uselen = host_len; 
 
		memcpy (host, ip, host_len); 
	} 
	return true; 
} 
// 发送数据 
int CConnection::Send (const char* buffer, int bufferlen) 
{ 
	// 没有连接则出错 
	if (!IsConnected ()) 
	{ 
		CConnection::SetLastError (WSAENOTCONN); 
		return 0; 
	} 
    // 取出套接字  
	m_sync.Enter (); 
	SOCKET sock = m_socket; 
	m_sync.Leave (); 
    // 发送数据 
	return send (sock, buffer, bufferlen, 0); 
} 
// 接收数据 
int CConnection::Receive (char* buffer, int bufferlen) 
{ 
	int iRecvd; 
    // 从m_data中取下一个数据 
	m_sync.Enter (); 
	iRecvd = m_data.Remove (buffer, bufferlen); 
	m_sync.Leave (); 
 
	return iRecvd; 
} 
// 设置关闭连接回调函数 
void CConnection::SetCloseFunc (CALLBACKFUNC hFunc) 
{ 
	m_sync.Enter (); 
	hCloseFunc = hFunc; 
	m_sync.Leave (); 
} 
// 设置关闭连接事件 
void CConnection::SetCloseEvent (HANDLE hEvent) 
{ 
	m_sync.Enter (); 
	hCloseEvent = hEvent; 
	m_sync.Leave (); 
} 
// 设置接收回调函数 
void CConnection::SetReceiveFunc (CALLBACKFUNC hFunc) 
{ 
	m_sync.Enter (); 
	hRecvFunc = hFunc; 
	m_sync.Leave (); 
} 
// 设置接收事件 
void CConnection::SetReceiveEvent (HANDLE hEvent) 
{ 
	m_sync.Enter (); 
	hRecvEvent = hEvent; 
	m_sync.Leave (); 
} 
// 判断是否处于连接状态 
bool CConnection::IsConnected () 
{ 
	bool bConnd; 
 
	m_sync.Enter (); 
	bConnd = m_socket != INVALID_SOCKET; 
	m_sync.Leave (); 
 
	return bConnd; 
} 
// 获取接收到的数据字节数 
int CConnection::HasReceived () 
{ 
	int iRecvd; 
 
	m_sync.Enter (); 
	iRecvd = m_data.Length (); 
	m_sync.Leave (); 
 
	return iRecvd; 
} 
// 等待接收线程的实际运行函数 
int CConnection::RecvWait () 
{ 
	const int MSG_CHUNK = 50;//要与发送的数据长度一致,否则 
	                         //数据发送较快时,容易接收错误数据 
 
	int		status = 0; 
	char	buffer[MSG_CHUNK]; 
	SOCKET	sock; 
 
	while (true) 
	{ 
		// 取出套接字 
		m_sync.Enter (); 
		sock = m_socket; 
		m_sync.Leave (); 
        // 如果套接字无效,设置m_event 
		if (sock == INVALID_SOCKET) 
		{ 
			SetEvent (m_event); 
			return 0; 
		} 
 
		//	By default sockets are created in blocking mode. 
		//	Just keep reading until process destroyed. 
		memset (buffer, 0, MSG_CHUNK); 
        // 接收数据,阻塞 
		status = recv (sock, buffer, MSG_CHUNK, 0); 
		if (status == SOCKET_ERROR) 
		{ 
			int err = WSAGetLastError(); 
			CConnection::SetLastError (err); 
            // 触发关闭回调函数  
			if (hCloseEvent) SetEvent (hCloseEvent);		//	if an event was given, pulse the event 
			if (hCloseFunc) (hCloseFunc) ((DWORD) this);	//	if a function ptr was given, call the function 
 
			Disconnect (); 
			SetEvent (m_event); 
			return 0; 
		} 
 
		if (status > 0) 
		{ 
			// 把接收到的数据存入m_data 
			m_sync.Enter (); 
			m_data.Append (buffer, status); 
 
			// 触发接收回调函数和事件 
			HANDLE hEvent = hRecvEvent; 
			CALLBACKFUNC fncCallback = hRecvFunc; 
			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 
		} 
		else 
		{ 
			//	socket was "gracefully" closed - thus, no error 
			if (hCloseEvent) SetEvent (hCloseEvent);		//	if an event was given, pulse the event 
			if (hCloseFunc) (hCloseFunc) ((DWORD) this);	//	if a function ptr was given, call the function 
 
			Disconnect (); 
			SetEvent (m_event); 
			return 0; 
/* 
			m_sync.Enter (); 
			SOCKET s = m_socket; 
			m_socket = INVALID_SOCKET; 
			hRecvThread = NULL; 
			m_sync.Leave (); 
 
			#define SD_RECEIVE      0x00 
			#define SD_SEND         0x01 
			#define SD_BOTH         0x02 
 
			//	be nice and shut the socket gracefully 
			shutdown (s, 0x01); 
			closesocket (s); 
*/ 
		} 
	} 
 
	return 0; 
} 
// 等待接收线程 
int CConnection::RecvThread (void* pThis) 
{ 
	return ((CConnection*) (pThis))->RecvWait (); 
} 
 
 
 
 
// 保存连接列表 
CNetworking::CConnectionList::CConnectionList () 
{ 
	m_first = NULL; 
	m_last = NULL; 
	m_length = 0; 
} 
// 析构函数,删除所有内容 
CNetworking::CConnectionList::~CConnectionList () 
{ 
	if (m_length == 0) return; 
	Node* next = m_first->m_next; 
 
	do 
	{ 
		delete m_first; 
		m_first = next; 
 
		if (m_first) 
			next = m_first->m_next; 
	} 
	while (m_first); 
} 
 
//	在列表尾添加一个连接 
void CNetworking::CConnectionList::Add (CConnection* con) 
{ 
	if (m_length == 0) 
	{ 
		m_last = m_first = new Node (); 
	} 
	else 
	{ 
		m_last->m_next = new Node (); 
		m_last = m_last->m_next; 
	} 
	m_last->m_con = con; 
 
	m_length ++; 
} 
 
//	从列表头移除一个记录 
CConnection* CNetworking::CConnectionList::Remove () 
{ 
	if (m_length == 0) return NULL; 
 
	CConnection* ret = m_first->m_con; 
	Node* newfirst = m_first->m_next; 
 
	delete m_first; 
	m_first = newfirst; 
 
	m_length --; 
 
	return ret; 
} 
 
//	remove a connection at index i 
CConnection* CNetworking::CConnectionList::Remove (int i) 
{ 
	if (m_length == 0) return NULL; 
	if (i == 0) return Remove (); 
 
	Node* ret = m_first; 
	for (int j = 0; j < i - 1; j++) 
		ret = ret->m_next; 
 
	Node* d = ret->m_next; 
	CConnection* cret = d->m_con; 
	ret->m_next = d->m_next; 
 
	delete d; 
	m_length --; 
 
	return cret; 
} 
 
CConnection* CNetworking::CConnectionList::Item (int i) 
{ 
	return operator[] (i); 
} 
 
CConnection* CNetworking::CConnectionList::operator [] (int i) 
{ 
	if (m_length == 0) return NULL; 
	Node* ret = m_first; 
 
	for (int j = 0; j < i; j++) 
		ret = ret->m_next; 
 
	return ret->m_con; 
} 
 
long CNetworking::CConnectionList::Length () 
{ 
	return m_length; 
} 
 
 
 
 
 
CNetworking::CConnectionList::Node::Node () 
{ 
	m_con = NULL; 
	m_next = NULL; 
} 
 
 
 
 
 
// 数据堆栈 
CConnection::CDataStack::CDataStack () 
{ 
	m_buffer = NULL; 
	m_length = 0; 
} 
 
CConnection::CDataStack::~CDataStack () 
{ 
	delete[] m_buffer; 
} 
// 增加数据到后面 
void CConnection::CDataStack::Append (const char* data, int len) 
{ 
	if (data == NULL || len <= 0) return; 
 
	m_sync.Enter (); 
	if (m_length == 0) 
	{ 
		m_buffer = new char[len]; 
		memcpy(m_buffer, data, len); 
		m_length = len; 
	} 
	else 
	{ 
		//	backup old buffer (temporarily) 
		char* oldbuff = new char[m_length]; 
		memcpy(oldbuff, m_buffer, m_length); 
 
		//	create a new buffer that holds the old one PLUS the new stuff 
		delete[] m_buffer; 
		m_buffer = new char[m_length + len]; 
 
		//	copy old buffer and new data into the new (bigger) buffer 
		memcpy(m_buffer, oldbuff, m_length); 
		memcpy(&m_buffer[m_length], data, len); 
 
		//	store the new length of the data 
		m_length += len; 
 
		//	do clean-up 
		delete[] oldbuff; 
	} 
	m_sync.Leave (); 
} 
// 在前面移除数据 
int CConnection::CDataStack::Remove (char* data, int len) 
{ 
	memset(data, 0, len); 
 
	m_sync.Enter (); 
	//	if the buffer is empty, don't remove anything 
	if (m_length == 0) 
	{ 
		m_sync.Leave (); 
		return 0; 
	} 
 
	//	determine how much we will actually copy 
	int remlen = len; 
	if (remlen > m_length) 
		remlen = m_length; 
 
	//	backup old buffer (temporarily) 
	char* oldbuff = new char[m_length]; 
	memcpy(oldbuff, m_buffer, m_length); 
 
	//	copy part of buffer (or all) to 'data' 
	memcpy(data, oldbuff, remlen); 
 
	//	create a new buffer that holds the old one MINUS the removed stuff 
	delete[] m_buffer; 
	if (m_length - remlen <= 0) 
	{ 
		m_buffer = NULL; 
		m_length = 0; 
	} 
	else 
	{ 
		m_buffer = new char[m_length - remlen]; 
 
		//	remove the part that has been copied from the buffer 
		memcpy(m_buffer, &oldbuff[remlen], m_length - remlen); 
 
		//	store the new length of the data 
		m_length -= remlen; 
	} 
 
	//	do clean-up 
	delete[] oldbuff; 
 
	m_sync.Leave (); 
	return remlen; 
} 
 
int CConnection::CDataStack::Length () 
{ 
	long length; 
 
	m_sync.Enter (); 
	length = m_length; 
	m_sync.Leave (); 
 
	return length; 
} 
 
 
 
 
 
CSync::CSync () 
{ 
	m_sync = CreateMutex (NULL, false, NULL); 
	if (m_sync == NULL) 
		throw CError (1001); 
} 
 
CSync::~CSync() 
{ 
	if (m_sync != NULL) 
	{ 
		CloseHandle (m_sync); 
		m_sync = NULL; 
	} 
} 
 
void CSync::Enter () const 
{ 
	WaitForSingleObject (m_sync, INFINITE); 
} 
 
void CSync::Leave () const 
{ 
	ReleaseMutex (m_sync); 
} 
 
 
 
 
 
CError::CError (long err) 
{ 
	m_number = err; 
} 
 
long CError::GetErrorString (char* str, long len) 
{ 
	static const long lErrCodes[] =  
		{ 
			WSAEACCES,  
			WSAEADDRINUSE,  
			WSAEADDRNOTAVAIL,  
			WSAEAFNOSUPPORT,  
			WSAEALREADY,  
			WSAECONNABORTED,  
			WSAECONNREFUSED,  
			WSAECONNRESET,  
			WSAEDESTADDRREQ,  
			WSAEFAULT,  
			WSAEHOSTDOWN,  
			WSAEHOSTUNREACH,  
			WSAEINPROGRESS,  
			WSAEINTR,  
			WSAEINVAL,  
			WSAEISCONN,  
			WSAEMFILE,  
			WSAEMSGSIZE,  
			WSAENETDOWN,  
			WSAENETRESET,  
			WSAENETUNREACH,  
			WSAENOBUFS,  
			WSAENOPROTOOPT,  
			WSAENOTCONN,  
			WSAENOTSOCK,  
			WSAEOPNOTSUPP,  
			WSAEPFNOSUPPORT,  
			WSAEPROCLIM,  
			WSAEPROTONOSUPPORT,  
			WSAEPROTOTYPE,  
			WSAESHUTDOWN,  
			WSAESOCKTNOSUPPORT,  
			WSAETIMEDOUT,  
			WSAEWOULDBLOCK,  
			WSAHOST_NOT_FOUND,  
			WSANOTINITIALISED,  
			WSANO_DATA,  
			WSANO_RECOVERY,  
			WSASYSNOTREADY,  
			WSATRY_AGAIN,  
			WSAVERNOTSUPPORTED,  
			WSAEDISCON,  
			1001,  
			1002 
		}; 
 
	static const char lpErrMsgs[][64] =  
		{ 
			"Permission denied.",  
			"Address already in use.",  
			"Cannot assign requested address.",  
			"Address family not supported by protocol family.",  
			"Operation already in progress.",  
			"Software caused connection abort.",  
			"Connection refused.",  
			"Connection reset by peer.",  
			"Destination address required.",  
			"Bad address.",  
			"Host is down.",  
			"No route to host.",  
			"Operation now in progress.",  
			"Interrupted function call.",  
			"Invalid argument.",  
			"Socket is already connected.",  
			"Too many open sockets.",  
			"Message too long.",  
			"Network is down.",  
			"Network dropped connection on reset.",  
			"Network is unreachable.",  
			"No buffer space available.",  
			"Bad protocol option.",  
			"Socket is not connected.",  
			"Socket operation on nonsocket.",  
			"Operation not supported.",  
			"Protocol family not supported.",  
			"Too many processes.",  
			"Protocol not supported.",  
			"Protocol wrong type for socket.",  
			"Cannot send after socket shutdown.",  
			"Socket type not supported.",  
			"Connection timed out.",  
			"Resource temporarily unavailable.",  
			"Host not found.",  
			"Successful WSAStartup not yet performed.",  
			"Valid name, no data record of requested type.",  
			"This is a nonrecoverable error.",  
			"Network subsystem is unavailable.",  
			"Nonauthoritative host not found.",  
			"Winsock.dll version out of range.",  
			"Graceful shutdown in progress." 
			"Mutex not created.",  
			"Thread not created." 
		}; 
 
	for (int i = 0; i < sizeof (lErrCodes) / sizeof (long); i++)		 
	{ 
		if (m_number == lErrCodes[i]) 
		{ 
			int slen = strlen (lpErrMsgs[i]); 
 
			if (len > slen + 1) len = slen + 1; 
			if (str) memcpy (str, lpErrMsgs[i], len); 
 
			return slen; 
		} 
	} 
 
	char lpUnknown[] = "Unknown error."; 
	int slen = strlen (lpUnknown); 
 
	if (len > slen + 1) len = slen + 1; 
	if (str) memcpy (str, lpUnknown, len); 
	return slen; 
}