socket

本文介绍了一个基于Cocos2d-x的游戏网络通信模块实现细节,包括跨平台的Socket编程接口封装、多线程消息队列管理、数据加密解密流程等关键技术点。
头文件
#ifndef _MTNotification_H_
#define _MTNotification_H_

#include <thread>
#include "SocketSinkHead.h"

#if (CC_TARGET_PLATFORM==CC_PLATFORM_WIN32)
#include <WinSock2.h>  
#include <WS2tcpip.h>
#pragma comment (lib,"WS2_32.Lib")  
#define LHS_EAGAIN          WSAEWOULDBLOCK    
#define LHS_EWOULDBLOCK     WSAEWOULDBLOCK  

#define LHS_ETIMEDOUT		WSAETIMEDOUT  
#define LHS_ENETDOWN		WSAENETDOWN  
#define LHS_WSAEINVAL		WSAEINVAL  

#else
#include <signal.h>  
#include <sys/socket.h>  
#include <netinet/in.h>  
#include<netinet/tcp.h>  
#include <netdb.h>  
#include <errno.h>  
#include <fcntl.h>  
#include <unistd.h>  
#include <sys/stat.h>  
#include <sys/types.h>  
#include <arpa/inet.h> 
typedef int					SOCKET;
#define INVALID_SOCKET		(SOCKET)(~0)  
#define SOCKET_ERROR		(-1)  
#define LHS_EAGAIN          EAGAIN              //此操作会令线程阻塞,但socket为不可阻塞的  
#define LHS_EWOULDBLOCK     EWOULDBLOCK         //资源暂时不可用  
#define LHS_ETIMEDOUT		ETIMEDOUT  
#define LHS_ENETDOWN		ENETDOWN  
#define LHS_WSAEINVAL		10022
#endif

USING_NS_CC;
//  TCP 网络连接
class CSocketEngine : public ITCPSocket
{
	friend class MTSocketQueue;
	// 辅助变量
private:
	WORD											m_wSocketID;					//  网络标识
	int												m_SocketIndex;					//	网络索引
	BYTE											m_cbSocketStatus;				//  网络状态
	//  计数变量
private:
	DWORD											m_dwSendTickCount;				//  发送时间
	DWORD											m_dwRecvTickCount;				//  接收时间
	//  接收变量
private:
	WORD											m_wRecvSize;					//  接收长度
	BYTE											m_cbRecvBuf[SOCKET_TCP_BUFFER * 10]; //  接收缓冲
	//  内核变量
private:
	SOCKET											m_hSocket;						//  连接句柄
	ITCPSocketSink*									m_pITCPSocketSink;				//  回调接口
	std::mutex										m_MutexRecv;
	
	// 函数定义
public:
	// 构造函数
	CSocketEngine();
	// 析构函数
	virtual ~CSocketEngine();
	// 标识接口
public:
	// 获取标识
	virtual WORD GetSocketID() { return m_wSocketID; }
	// 设置标识
	virtual void SetSocketID(WORD wSocketID) { m_wSocketID = wSocketID; }

	// 配置接口
public:
	// 设置接口
	virtual bool SetTCPSocketSink(ITCPSocketSink* pIUnknownEx);
	// 信息接口
public:
	// 获取状态
	virtual BYTE GetSocketStatus() { return m_cbSocketStatus; }
	// 操作接口
public:
	// 连接操作
	virtual BYTE Connect(std::string szServerIP, WORD wPort);
	// 发送函数
	virtual WORD SendData(WORD wMainCmdID, WORD wSubCmdID);
	// 发送函数
	virtual WORD SendData(WORD wMainCmdID, WORD wSubCmdID, VOID* pData, WORD wDataSize);
	// 关闭连接
	virtual VOID CloseSocket();

	// 辅助函数
protected:
	// 连接事件
	void OnSocketLink(int nErrorCode);
	// 发送数据
	WORD SendDataBuffer(void* pBuffer, WORD wSendSize);
	// 应答事件
	void OnSocketRead(void* pBuffer, WORD wSendSize);
	// 关闭连接
	void CloseSocket(BYTE cbShutReason);
	// 解密数据
	WORD CrevasseBuffer(BYTE cbDataBuffer[], WORD wDataSize);
	// 加密数据
	WORD EncryptBuffer(BYTE cbDataBuffer[], WORD wDataSize, WORD wBufferSize);
private:
    
    static void PerformConnectThread(std::string szServerIP, WORD wPort, int nSocketIndex);
	static void PerformRecvectThread(int nSocketIndex);
	
};

//////////////////////////////////////////////////////////////////////////
#endif // _MTNotification_H_

源文件
#include <iostream>
#include <map>
#include "cocos2d.h"
#include <mutex>
#include "SocketEngine.h"

USING_NS_CC;
//////////////////////////////////////////////////////////////////////////
// 多线程共享消息队列
//////////////////////////////////////////////////////////////////////////
void socket_close(int s)
{
#if (CC_TARGET_PLATFORM==CC_PLATFORM_WIN32)  
	shutdown(s, SD_BOTH);
	closesocket(s);
#else  
	shutdown(s, 2);
	close(s);
#endif 
}

int socket_send(int s, const char* data, int size)
{
	unsigned int flags = 0;
#if (CC_TARGET_PLATFORM==CC_PLATFORM_ANDROID)  
	flags = MSG_NOSIGNAL;
#endif  
	return send(s, data, size, flags);
}

int socket_recv(int s, char* data, int size)
{
	unsigned int flags = 0;
#if (CC_TARGET_PLATFORM==CC_PLATFORM_ANDROID)  
	flags = MSG_NOSIGNAL;
#endif  
	return recv(s, data, size, flags);
}

int socket_error()
{
#if (CC_TARGET_PLATFORM==CC_PLATFORM_WIN32)
	return WSAGetLastError();
#else
	return errno;
#endif
}

void socket_sleep(unsigned int delay)
{
#if (CC_TARGET_PLATFORM==CC_PLATFORM_WIN32)
	Sleep(delay);
#else
	usleep(delay * 1000);
#endif
}

long socket_TickCount()
{
	timeval now;
	gettimeofday(&now, 0);
	return (LONG)(now.tv_sec * 1000 + now.tv_usec / 1000);
}

//////////////////////////////////////////////////////////////////////////
static bool					__isSetSig = true;
static int					__SocketIndex = 0;
static const BYTE			__SocketCount = 100;
static CSocketEngine*		__SocketMap[__SocketCount];
static const BYTE			EVENT_TCP_SOCKET_LINK = 0;		//连接事件
static const BYTE			EVENT_TCP_SOCKET_READ = 1;		//读取事件
static const BYTE			EVENT_TCP_SOCKET_SHUT = 2;		//关闭事件
#define GetMTSocketQueue	MTSocketQueue::GetInstance()
//////////////////////////////////////////////////////////////////////////
class CInitSock
{
public:
	CInitSock()
	{
		ZeroMemory(__SocketMap, sizeof(__SocketMap));

#if (CC_TARGET_PLATFORM==CC_PLATFORM_WIN32)
		if (__isSetSig)
		{
			__isSetSig = false;
			WSADATA wsaData;
			//初始化Socket环境
			if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
			{
				//初始化DLL错误,显示错误提示,程序退出
				CCLOG("WSAStartup failed!\nInitialize socket failed.\n");
	}
}
#endif
#if (CC_TARGET_PLATFORM==CC_PLATFORM_IOS)
		if (__isSetSig)
		{
			__isSetSig = false;
			struct sigaction Sa;
			Sa.sa_handler = SIG_IGN;
			sigaction(SIGPIPE, &Sa, 0);
		}
#endif 
	}

	~CInitSock()
	{
#if (CC_TARGET_PLATFORM==CC_PLATFORM_WIN32)
		WSACleanup();
#endif
	}
};
CInitSock __InitSock;
//////////////////////////////////////////////////////////////////////////
// 循环消息处理
class MTSocketQueue : public Ref
{
	struct MTData
	{
		BYTE			onwer;		//数据拥有者
		int				cmd;		//命令:0关闭连接 1:错误码(dataSize) 2:消息
		BYTE*			data;
		int				dataSize;
	};

	std::list<MTData>	m_DataQueues;
	std::mutex			m_Mutex;

	static MTSocketQueue*	m_sInstance;
private:
	MTSocketQueue()
	{
		Director::getInstance()->getScheduler()->schedule(CC_SCHEDULE_SELECTOR(MTSocketQueue::post), this, 0.0f, false);
	}

	~MTSocketQueue()
	{
		std::lock_guard<std::mutex> lk(m_Mutex); //线程开始加锁,退出时自动解锁  
		while (!m_DataQueues.empty())
		{
			MTData& mtData = m_DataQueues.front();
			if (mtData.data)	delete[]mtData.data;
			m_DataQueues.pop_front();
		}
	}
public:
	static MTSocketQueue* GetInstance()
	{
		if (m_sInstance == 0)
			m_sInstance = new MTSocketQueue();
		return m_sInstance;
	}
public:
	void PostAsynEventData(BYTE cbIndex, WORD cmd, void* data, WORD dataSize)
	{
		std::lock_guard<std::mutex> lk(m_Mutex); //线程开始加锁,退出时自动解锁  
		if (cbIndex > __SocketCount && __SocketMap[cbIndex] == 0)	{ return; }
		MTData mtData;
		memset(&mtData, 0, sizeof(mtData));
		mtData.onwer = cbIndex;
		mtData.cmd = cmd;
		mtData.dataSize = dataSize;

		if (data != 0)
		{
			mtData.data = new BYTE[dataSize];
			if (mtData.data == 0){ return; }
			memcpy(mtData.data, data, dataSize);
		}
		m_DataQueues.push_back(mtData);
	}
	// 处理消息
	void post(float dt)
	{
		std::lock_guard<std::mutex> lk(m_Mutex); //线程开始加锁,退出时自动解锁  

		while (!m_DataQueues.empty())
		{
			const MTData& mtData = m_DataQueues.front();
			if (mtData.onwer < __SocketIndex)
			{
				CSocketEngine* owner = __SocketMap[mtData.onwer];
				if (owner)
				{
					if (mtData.cmd == EVENT_TCP_SOCKET_LINK)		owner->OnSocketLink(mtData.dataSize);
					else if (mtData.cmd == EVENT_TCP_SOCKET_READ)	owner->OnSocketRead(mtData.data, mtData.dataSize);
					else if (mtData.cmd == EVENT_TCP_SOCKET_SHUT)	owner->CloseSocket(mtData.dataSize);
				}
				if (mtData.data)		delete[]mtData.data;
			}

			m_DataQueues.pop_front();
		}
	}
};
//////////////////////////////////////////////////////////////////////////
MTSocketQueue* MTSocketQueue::m_sInstance = 0;
//////////////////////////////////////////////////////////////////////////
void CSocketEngine::PerformConnectThread(std::string szServerIP, WORD wPort, int nSocketIndex)
{
	if (nSocketIndex > __SocketCount) return;

	struct addrinfo * res = NULL;
    
    char szPort[10]={0};
    sprintf(szPort,"%d",wPort);

	int error = getaddrinfo(szServerIP.c_str(), szPort, NULL, &res);
    
	if (error != 0)
	{
		CCLOG("域名解析失败,[%s] line [%d] error in ServerIP[%s], Port[%d], getaddrinfo:%d, strErr=%s",
              __FUNCTION__, __LINE__, szServerIP.c_str(), wPort, error, gai_strerror(error));
        
        if (GetMTSocketQueue)	GetMTSocketQueue->PostAsynEventData(nSocketIndex, EVENT_TCP_SOCKET_SHUT, 0, SHUT_REASON_EXCEPTION);        return;
		return;
	}
    if (__SocketMap[nSocketIndex])			__SocketMap[nSocketIndex]->m_hSocket = socket(res->ai_family,SOCK_STREAM,0);
    
    if (__SocketMap[nSocketIndex] && __SocketMap[nSocketIndex]->m_hSocket < 0)
    {
        CCLOG("TcpClientSocket::function [%s] line [%d]", __FUNCTION__, __LINE__);
        if (GetMTSocketQueue)	GetMTSocketQueue->PostAsynEventData(nSocketIndex, EVENT_TCP_SOCKET_SHUT, 0, SHUT_REASON_EXCEPTION);        return;
    }
    
    if (__SocketMap[nSocketIndex] && connect(__SocketMap[nSocketIndex]->m_hSocket, res->ai_addr, res->ai_addrlen) < 0)
    {
        CCLOG("Socket::%s  connect err... line [%d]", __FUNCTION__, __LINE__);
        if (GetMTSocketQueue)	GetMTSocketQueue->PostAsynEventData(nSocketIndex, EVENT_TCP_SOCKET_SHUT, 0, SHUT_REASON_EXCEPTION);         return;
    }


    freeaddrinfo(res);

	int nSendtimeout = 3000; //3s
	if (__SocketMap[nSocketIndex])	setsockopt(__SocketMap[nSocketIndex]->m_hSocket, SOL_SOCKET, SO_SNDTIMEO, (const char*)&nSendtimeout, sizeof(nSendtimeout));
	int nRecvtimeout = 21000;	//21s
	if (__SocketMap[nSocketIndex])	setsockopt(__SocketMap[nSocketIndex]->m_hSocket, SOL_SOCKET, SO_RCVTIMEO, (const char*)&nRecvtimeout, sizeof(nRecvtimeout));
    
    if (__SocketMap[nSocketIndex])__SocketMap[nSocketIndex]->m_wSocketID = (WORD)__SocketMap[nSocketIndex]->m_hSocket;
    
	std::thread tThread(&CSocketEngine::PerformRecvectThread, nSocketIndex);
	tThread.detach();
}
// 客户端线程接收连接
void CSocketEngine::PerformRecvectThread(int nSocketIndex)
{
	if (nSocketIndex > __SocketCount) return;

	if (__SocketMap[nSocketIndex])	std::lock_guard<std::mutex> lk(__SocketMap[nSocketIndex]->m_MutexRecv); //线程开始加锁,退出时自动解锁  

	if (__SocketMap[nSocketIndex]) __SocketMap[nSocketIndex]->m_cbSocketStatus = SOCKET_STATUS_CONNECT;

	if (__SocketMap[nSocketIndex] && GetMTSocketQueue)	GetMTSocketQueue->PostAsynEventData(nSocketIndex, EVENT_TCP_SOCKET_LINK, 0, SOCKET_STATUS_CONNECT);

	socket_sleep(10);

	while (__SocketMap[nSocketIndex] && __SocketMap[nSocketIndex]->GetSocketStatus() == SOCKET_STATUS_CONNECT)
	{
		char cbRecvBuf[SOCKET_TCP_BUFFER] = { 0 };	//接收缓冲

		if (!__SocketMap[nSocketIndex]) continue;
		int nDataSize = socket_recv(__SocketMap[nSocketIndex]->m_hSocket, cbRecvBuf, SOCKET_TCP_BUFFER);
		if (SOCKET_ERROR == nDataSize)
		{
			int errCode = socket_error();
			//CCLOG("recv failed %d !", errCode);
			//无法立即完成非阻塞Socket上的操作
			if (errCode == 10004) 	break;
			else if (errCode == LHS_EWOULDBLOCK)
			{
				socket_sleep(20);
				CCLOG("waiting back msg!\n");
				continue;
			}
			else if (errCode == LHS_EAGAIN)
			{
				continue;
			}
			if (GetMTSocketQueue)	GetMTSocketQueue->PostAsynEventData(nSocketIndex, EVENT_TCP_SOCKET_SHUT, 0, SHUT_REASON_EXCEPTION);
			return;
		}
		if (nDataSize == 0)	break;
		if (GetMTSocketQueue)	GetMTSocketQueue->PostAsynEventData(nSocketIndex, EVENT_TCP_SOCKET_READ, cbRecvBuf, nDataSize);
	}


	if (__SocketMap[nSocketIndex] && __SocketMap[nSocketIndex]->m_hSocket != INVALID_SOCKET &&  GetMTSocketQueue)	GetMTSocketQueue->PostAsynEventData(nSocketIndex, EVENT_TCP_SOCKET_SHUT, 0, SHUT_REASON_NORMAL);
}

//////////////////////////////////////////////////////////////////////////

// 构造函数
CSocketEngine::CSocketEngine()
{
	// 辅助变量
	m_wSocketID = INVALID_WORD;
	m_SocketIndex = -1;
	m_cbSocketStatus = SOCKET_STATUS_IDLE;				//  网络状态
	m_dwSendTickCount = INVALID_DWORD;					//  发送时间
	m_dwRecvTickCount = INVALID_DWORD;					//  接收时间
	m_wRecvSize = 0;									//  接收长度
	ZeroMemory(m_cbRecvBuf, sizeof(m_cbRecvBuf));		//  接收缓冲
	m_hSocket = INVALID_SOCKET;							//  连接句柄
	m_pITCPSocketSink = nullptr;						//  回调接口
}

// 析构函数
CSocketEngine::~CSocketEngine()
{
	__SocketMap[m_SocketIndex] = 0;
	m_pITCPSocketSink = nullptr;							//  回调接口
	CloseSocket(SHUT_REASON_NORMAL);
}

// 设置接口
bool CSocketEngine::SetTCPSocketSink(ITCPSocketSink* pIUnknownEx)
{
	m_pITCPSocketSink = pIUnknownEx;
	return (m_pITCPSocketSink != NULL);
}

// 连接服务器
BYTE CSocketEngine::Connect(std::string szServerIP, WORD wPort)
{
	// 效验数据
	if (szServerIP.empty() || (wPort == 0)) return CONNECT_FAILURE;

	m_cbSocketStatus = SOCKET_STATUS_WAIT;

	if (m_SocketIndex == -1)
	{
		m_SocketIndex = __SocketIndex++;
		__SocketMap[m_SocketIndex] = this;
		if (__SocketIndex >= __SocketCount)__SocketIndex = 0;
	}
	std::thread tThread(&CSocketEngine::PerformConnectThread, szServerIP, wPort, m_SocketIndex);
	tThread.detach();
	return CONNECT_SUCCESS;
}

// 发送函数
WORD CSocketEngine::SendData(WORD wMainCmdID, WORD wSubCmdID)
{
	// 效验状态
	if (m_hSocket == INVALID_SOCKET) return false;
	if (m_cbSocketStatus != SOCKET_STATUS_CONNECT) return false;

	// 构造数据
	BYTE cbDataBuffer[SOCKET_TCP_BUFFER];
	TCP_Head* pHead = (TCP_Head*)cbDataBuffer;
	pHead->CommandInfo.wMainCmdID = wMainCmdID;
	pHead->CommandInfo.wSubCmdID = wSubCmdID;

	// 加密数据
	WORD wSendSize = EncryptBuffer(cbDataBuffer, sizeof(TCP_Head), sizeof(cbDataBuffer));

	// 发送数据
	return SendDataBuffer(cbDataBuffer, wSendSize) != 0;
}

// 发送函数
WORD CSocketEngine::SendData(WORD wMainCmdID, WORD wSubCmdID, void* pData, WORD wDataSize)
{
	// 效验状态
	if (m_hSocket == INVALID_SOCKET) return false;
	if (m_cbSocketStatus != SOCKET_STATUS_CONNECT) return false;

	// 效验大小
	ASSERT(wDataSize <= SOCKET_TCP_PACKET);
	if (wDataSize > SOCKET_TCP_PACKET) return false;

	BYTE cbDataBuffer[SOCKET_TCP_BUFFER];
	TCP_Head* pHead = (TCP_Head*)cbDataBuffer;
	pHead->CommandInfo.wMainCmdID = wMainCmdID;
	pHead->CommandInfo.wSubCmdID = wSubCmdID;
	if (wDataSize > 0)
	{
		ASSERT(pData != NULL);
		CopyMemory(pHead + 1, pData, wDataSize);
	}

	// 加密数据
	WORD wSendSize = EncryptBuffer(cbDataBuffer, sizeof(TCP_Head) + wDataSize, sizeof(cbDataBuffer));

	// 发送数据
	return SendDataBuffer(cbDataBuffer, wSendSize);
}

// 关闭连接
VOID CSocketEngine::CloseSocket()
{
	CloseSocket(SHUT_REASON_NORMAL);
}

// 连接事件
void CSocketEngine::OnSocketLink(int nErrorCode)
{
	if (m_pITCPSocketSink)	m_pITCPSocketSink->OnEventTCPSocketLink(m_wSocketID, nErrorCode);
}

// 发送数据
WORD CSocketEngine::SendDataBuffer(void* pBuffer, WORD wSendSize)
{
	// 效验参数
	ASSERT(wSendSize != 0);
	ASSERT(pBuffer != NULL);

	// 发送数据
	WORD wSended = 0;
	while (wSended < wSendSize)
	{
		while (true)
		{
			int retVal = socket_send(m_hSocket, (char*)pBuffer + wSended, wSendSize - wSended);
			if (SOCKET_ERROR == retVal)
			{
				if (socket_error() == LHS_EWOULDBLOCK)
				{
					//无法立即完成非阻塞Socket上的操作
					socket_sleep(5);
					continue;
				}
				else
				{
					CCLOG("send failed %d!\n", socket_error());
					if (GetMTSocketQueue)	GetMTSocketQueue->PostAsynEventData(m_SocketIndex, EVENT_TCP_SOCKET_SHUT, 0, SHUT_REASON_EXCEPTION);
					return 0;
				}
			}
			wSended += retVal;
			break;
		}
	}

	m_dwSendTickCount = socket_TickCount();
	return wSended;
}

// 网络消息
void CSocketEngine::OnSocketRead(void* pBuffer, WORD wSendSize)
{
	try
	{
		CopyMemory(&m_cbRecvBuf[m_wRecvSize], pBuffer, wSendSize);
		m_wRecvSize += wSendSize;

		DWORD dwLong = socket_TickCount() - m_dwRecvTickCount;
		//CCLOG("---------- %d ms", dwLong);
		m_dwRecvTickCount = socket_TickCount();

		// 变量定义
		WORD wPacketSize = 0;
		BYTE cbDataBuffer[SOCKET_TCP_BUFFER] = { 0 };
		TCP_Head* pHead = (TCP_Head*)m_cbRecvBuf;

		while (m_wRecvSize >= sizeof(TCP_Head) && m_cbSocketStatus == SOCKET_STATUS_CONNECT)
		{
			// 效验参数
			wPacketSize = pHead->TCPInfo.wPacketSize;
			ASSERT(pHead->TCPInfo.cbDataKind == DK_MAPPED);
			ASSERT(wPacketSize <= SOCKET_TCP_BUFFER);
			if (pHead->TCPInfo.cbDataKind != DK_MAPPED)
			{
				cocos2d::MessageBox("只支持加密映射", "");
				throw "只支持映射加密";
			}
			if (wPacketSize > SOCKET_TCP_BUFFER)
			{
				cocos2d::MessageBox("只支持加密映射", "");
				throw "数据包太大";
			}
			if (m_wRecvSize < wPacketSize) return;

			// 拷贝数据
			CopyMemory(cbDataBuffer, m_cbRecvBuf, wPacketSize);
			m_wRecvSize -= wPacketSize;
			MoveMemory(m_cbRecvBuf, m_cbRecvBuf + wPacketSize, m_wRecvSize);

			// 解密数据
			WORD wRealySize = CrevasseBuffer(cbDataBuffer, wPacketSize);
			ASSERT(wRealySize >= sizeof(TCP_Head));
			// 解释数据
			WORD wDataSize = wRealySize - sizeof(TCP_Head);
			void * pDataBuffer = cbDataBuffer + sizeof(TCP_Head);
			TCP_Command Command = ((TCP_Head*)cbDataBuffer)->CommandInfo;

			// 内核命令 --> 网络检测
			if (Command.wMainCmdID == MDM_KN_COMMAND && Command.wSubCmdID == SUB_KN_DETECT_SOCKET)
			{
				// 发送数据
				SendData(MDM_KN_COMMAND, SUB_KN_DETECT_SOCKET, pDataBuffer, wDataSize);
				continue;
			}

			// 处理数据
			bool bSuccess = m_pITCPSocketSink->OnEventTCPSocketRead(m_wSocketID, Command, pDataBuffer, wDataSize);
			if (bSuccess == false) throw "网络数据包处理失败";
		}
	}
	catch (...)
	{
		CloseSocket(SHUT_REASON_EXCEPTION);
	}
}

// 关闭连接
VOID CSocketEngine::CloseSocket(BYTE cbShutReason)
{
	// 关闭连接
	if (m_hSocket != INVALID_SOCKET)
	{
		socket_close(m_hSocket);
		m_hSocket = INVALID_SOCKET;
		m_cbSocketStatus = SOCKET_STATUS_IDLE;
		if (m_SocketIndex != -1 && __SocketMap[m_SocketIndex]) __SocketMap[m_SocketIndex] = 0;
		m_SocketIndex = -1;
		
	}
	if (m_pITCPSocketSink)
	{
		try { m_pITCPSocketSink->OnEventTCPSocketShut(m_wSocketID, cbShutReason); }
		catch (...) {}
	}
	// 恢复数据
	m_wRecvSize = 0;
	m_dwSendTickCount = 0;
	m_dwRecvTickCount = 0;
}

// 加密数据
WORD CSocketEngine::EncryptBuffer(BYTE pcbDataBuffer[], WORD wDataSize, WORD wBufferSize)
{
	// 效验参数
	CC_ASSERT(wDataSize >= sizeof(TCP_Head));
	CC_ASSERT(wBufferSize >= wDataSize);
	CC_ASSERT(wDataSize <= SOCKET_TCP_BUFFER);
	// 效验码与字节映射
	BYTE cbCheckCode = 0;
	for (WORD i = sizeof(TCP_Info); i < wDataSize; i++)
	{
		cbCheckCode += pcbDataBuffer[i];
		pcbDataBuffer[i] = g_SendByteMap[pcbDataBuffer[i]];
	}

	// 填写信息头
	TCP_Head* pHead = (TCP_Head*)pcbDataBuffer;
	pHead->TCPInfo.cbCheckCode = ~cbCheckCode + 1;
	pHead->TCPInfo.wPacketSize = wDataSize;
	pHead->TCPInfo.cbDataKind = DK_MAPPED;
	return wDataSize;
}

// 解密数据
WORD CSocketEngine::CrevasseBuffer(BYTE pcbDataBuffer[], WORD wDataSize)
{
	// 效验参数
	CC_ASSERT(wDataSize >= sizeof(TCP_Head));
	CC_ASSERT(((TCP_Head*)pcbDataBuffer)->TCPInfo.wPacketSize == wDataSize);

	// 效验码与字节映射
	TCP_Head* pHead = (TCP_Head*)pcbDataBuffer;
	BYTE cbCheckCode = pHead->TCPInfo.cbCheckCode;
	for (int i = sizeof(TCP_Info); i < wDataSize; i++)
	{
		pcbDataBuffer[i] = g_RecvByteMap[pcbDataBuffer[i]];
		cbCheckCode += pcbDataBuffer[i];
	}
	if (cbCheckCode != 0) { CC_ASSERT(false || "数据包效验码错误"); }
	return wDataSize;
}

//////////////////////////////////////////////////////////////////////////
//bool TcpClientSocket::subConnectServerIPV6(const char *pServerIP, unsigned short ServerPort)
//{
//	CCLog("TcpClientSocket::function [%s] line [%d]", __FUNCTION__, __LINE__);
//	struct sockaddr_in6     addrServer;
//	int tempSocket = -1;
//
//	memset(&addrServer, 0, sizeof(addrServer));
//	addrServer.sin6_family = AF_INET6;
//	addrServer.sin6_port = htons(ServerPort);
//	inet_pton(AF_INET6, pServerIP, &addrServer.sin6_addr);
//	if ((tempSocket = socket(AF_INET6, SOCK_STREAM, 0)) < 0)
//	{
//		state = NETWORK_STATE_FAILED;
//		CCLog("TcpClientSocket::%s  socket err... line [%d]", __FUNCTION__, __LINE__);
//		return false;
//	}
//
//	if (connect(tempSocket, (struct sockaddr*)&addrServer, sizeof(addrServer)) < 0)
//	{
//		CCLog("TcpClientSocket::%s  connect err... line [%d]", __FUNCTION__, __LINE__);
//
//		return false;
//	}
//	return true;
//}





网狐6.6 服务器源代码&共享组件&数据库,包括服务器端所有组件(内核除外,现在市面上还没有6.6内核),共享组件(公共服务,界面控件,界面资源),以及全部数据库文件和脚本文件,6.6较6.5有较大改动,是学习研究的上等程序代码。 结合本人上次发布的客户端组件,即为网狐66系统模块全部源代码!!!官方售价几万,网上有人卖几百到几千不等,本程序绝对6.6新版代码(带道具),识货的下。 总共140M,7个解压包:1~7。 #ifndef KERNEL_ENGINE_HEAD_HEAD_FILE #define KERNEL_ENGINE_HEAD_HEAD_FILE ////////////////////////////////////////////////////////////////////////// //包含文件 #include #include #include #include #include //平台文件 #include "..\..\模板库\Template.h" #include "..\..\公共文件\Constant.h" #include "..\..\公共文件\GlobalDef.h" #include "..\..\共享组件\公共服务\ComService.h" ////////////////////////////////////////////////////////////////////////// //ADO 定义 #import "MSADO15.DLL" rename_namespace("ADOCG") rename("EOF","EndOfFile") using namespace ADOCG; typedef _com_error CComError; //COM 错误 typedef _variant_t CDBVarValue; //数据库数值 ////////////////////////////////////////////////////////////////////////// //导出定义 //导出定义 #ifndef KERNEL_ENGINE_CLASS #ifdef KERNEL_ENGINE_DLL #define KERNEL_ENGINE_CLASS _declspec(dllexport) #else #define KERNEL_ENGINE_CLASS _declspec(dllimport) #endif #endif //模块定义 #ifndef _DEBUG #define KERNEL_ENGINE_DLL_NAME TEXT("KernelEngine.dll") //组件 DLL 名字 #else #define KERNEL_ENGINE_DLL_NAME TEXT("KernelEngineD.dll") //组件 DLL 名字 #endif ////////////////////////////////////////////////////////////////////////// //系统常量 //常量定义 #define TIME_CELL 200 //时间单元 #define TIMES_INFINITY DWORD(-1) //无限次数 #define MAX_ASYNCHRONISM_DATA 8192 //异步数据 ////////////////////////////////////////////////////////////////////////// //网络定义 //连接错误 #define CONNECT_SUCCESS 0 //连接成功 #define CONNECT_FAILURE 1 //连接失败 #define CONNECT_EXCEPTION 2 //参数异常 //关闭原因 #define SHUT_REASON_INSIDE 0 //内部原因 #define SHUT_REASON_NORMAL 1 //正常关闭 #define SHUT_REASON_REMOTE 2 //远程关闭 #define SHUT_REASON_TIME_OUT 3 //网络超时
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值