#include "StdAfx.h" #include "TraceService.h" #include "TCPSocketService.h" //内核命令码 #define MDM_KN_COMMAND 0 //内核命令 #define SUB_KN_DETECT_SOCKET 1 //检测命令 #define SUB_KN_SHUT_DOWN_SOCKET 2 //中断网络 //宏定义 #define ID_SOCKET_WND 10 //SOCKET 窗口 ID #define MY_WM_SOCKET_NOTIFY WM_USER+10 //SOCKET 消息 ////////////////////////////////////////////////////////////////////////// BEGIN_MESSAGE_MAP(CTCPSocketService, CWnd) ON_MESSAGE(MY_WM_SOCKET_NOTIFY, OnSocketNotify) END_MESSAGE_MAP() //#define MY_ENCRYPT //函数定义 ////////////////////////////////////////////////////////////////////////// //构造函数 CTCPSocketService::CTCPSocketService(void) { //恢复数据 m_cbSendRound = 0; m_cbRecvRound = 0; m_dwSendXorKey = 0; m_dwRecvXorKey = 0; m_hSocket = INVALID_SOCKET; m_dwSendTickCount = 0; m_dwRecvTickCount = 0; m_dwSendPacketCount = 0; m_dwRecvPacketCount = 0; m_wServiceID = 0; m_cbSocketStatus = SOCKET_STATUS_IDLE; m_wRecvSize = 0; m_dwServerIP = INADDR_NONE; m_wPort = 0; m_bSuccess = false; ZeroMemory(m_szIp,sizeof(TCHAR) * 72); } //析构函数 CTCPSocketService::~CTCPSocketService(void) { if (m_bService) ConcludeService(); } //基础接口 ////////////////////////////////////////////////////////////////////////// //接口查询 void * CTCPSocketService::QueryInterface(const IID & Guid, DWORD dwQueryVer) { QUERYINTERFACE(ITCPSocketService, Guid, dwQueryVer); QUERYINTERFACE(IQueueServiceSink, Guid, dwQueryVer); QUERYINTERFACE_IUNKNOWNEX(ITCPSocketService, Guid, dwQueryVer); return NULL; } //服务接口 ////////////////////////////////////////////////////////////////////////// //启动服务 bool CTCPSocketService::StartService() { //效验状态 if (m_bService == true) { CTraceService::TraceString(TEXT("网络服务重复启动,启动操作忽略"), TraceLevel_Warning); return true; } //绑定对象 if (m_QueueService.SetQueueServiceSink(QUERY_ME_INTERFACE(IUnknownEx)) == false) { CTraceService::TraceString(TEXT("网络服务与触发服务绑定失败"), TraceLevel_Exception); return false; } try { //绑定对象 if (m_QueueService.SetQueueServiceSink(QUERY_ME_INTERFACE(IUnknownEx)) == false) { CTraceService::TraceString(TEXT("网络引擎与触发服务绑定失败"), TraceLevel_Exception); return false; } // m_hSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); // if (m_hSocket == INVALID_SOCKET) return false; if ((m_hWnd == NULL) && (!Create(NULL, NULL, WS_CHILD, CRect(0, 0, 0, 0), GetDesktopWindow(), ID_SOCKET_WND, NULL))) return false; if (m_QueueService.StartService()) { m_bService = true; } } catch (LPCTSTR pszError) { CTraceService::TraceString(pszError, TraceLevel_Exception); return false; } return m_bService; } //停止服务 bool CTCPSocketService::ConcludeService() { //设置变量 m_bService = false; CTraceService::TraceString(TEXT("网络引擎 停止服务成功"), TraceLevel_Normal); if (m_hSocket != INVALID_SOCKET) { //LINGER lingerStruct; //lingerStruct.l_onoff = 1; //lingerStruct.l_linger = 0; //setsockopt(m_hSocket, SOL_SOCKET, SO_LINGER, (char *)&lingerStruct, sizeof(lingerStruct)); closesocket(m_hSocket); WSAAsyncSelect(m_hSocket, GetSafeHwnd(), MY_WM_SOCKET_NOTIFY, 0); m_hSocket = INVALID_SOCKET; } //恢复数据 m_cbSendRound = 0; m_cbRecvRound = 0; m_dwSendXorKey = 0; m_dwRecvXorKey = 0; m_hSocket = INVALID_SOCKET; m_dwSendTickCount = 0; m_dwRecvTickCount = 0; m_dwSendPacketCount = 0; m_dwRecvPacketCount = 0; m_cbSocketStatus = SOCKET_STATUS_IDLE; m_wRecvSize = 0; m_dwServerIP = INADDR_NONE; m_wPort = 0; m_bSuccess = false; m_MyEncrypt.Reset(); m_QueueServiceEvent.SetQueueServiceSink(NULL); m_QueueService.ConcludeService(); return true; } //配置接口 ////////////////////////////////////////////////////////////////////////// //配置函数 bool CTCPSocketService::SetServiceID(WORD wServiceID) { m_wServiceID = wServiceID; return true; } //设置接口 bool CTCPSocketService::SetTCPSocketEvent(IUnknownEx * pIUnknownEx) { //状态判断 if (m_bService == true) { CTraceService::TraceString(TEXT("网络组件处于服务状态,绑定操作忽略"), TraceLevel_Warning); return false; } //设置接口 if (m_QueueServiceEvent.SetQueueServiceSink(pIUnknownEx) == false) { CTraceService::TraceString(TEXT("网络组件与触发服务绑定失败"), TraceLevel_Warning); return false; } return true; } //功能接口 ////////////////////////////////////////////////////////////////////////// //关闭连接 bool CTCPSocketService::CloseSocket() { //关闭连接 bool bClose = (m_hSocket != INVALID_SOCKET); if (bClose) return m_QueueService.AddToQueue(QUEUE_SAFE_CLOSE, NULL, 0); //恢复数据 m_cbSendRound = 0; m_cbRecvRound = 0; m_dwSendXorKey = 0; m_dwRecvXorKey = 0; m_hSocket = INVALID_SOCKET; m_dwSendTickCount = 0; m_dwRecvTickCount = 0; m_dwSendPacketCount = 0; m_dwRecvPacketCount = 0; m_cbSocketStatus = SOCKET_STATUS_IDLE; m_wRecvSize = 0; m_dwServerIP = INADDR_NONE; m_wPort = 0; m_MyEncrypt.Reset(); return true; } //连接地址 bool CTCPSocketService::Connect(DWORD dwServerIP, WORD wPort) { m_wPort = wPort; m_dwServerIP = dwServerIP; //设置参数 m_cbSendRound = 0; m_cbRecvRound = 0; m_dwSendXorKey = 0x12345678; m_dwRecvXorKey = 0x12345678; m_MyEncrypt.Reset(); try { return m_QueueService.AddToQueue(QUEUE_CONNECT_REQUEST, NULL, 0); } catch (LPCTSTR pszError) { CTraceService::TraceString(pszError, TraceLevel_Warning); CTraceService::TraceString(TEXT("Connect1 "), TraceLevel_Warning); CloseSocket(SHUT_REASON_EXCEPTION); throw pszError; } catch (...) { CTraceService::TraceString(TEXT("Connect2 "), TraceLevel_Warning); CloseSocket(SHUT_REASON_EXCEPTION); throw TEXT("连接产生未知异常错误"); } return false; } //连接地址 bool CTCPSocketService::Connect(LPCTSTR szServerIP, WORD wPort) { //效验数据 ASSERT(wPort != 0); ASSERT(szServerIP != NULL); if ((szServerIP == NULL) || (wPort == 0)) return false; //CString csIpPort; //csIpPort.Format(_T("%s:%d"), szServerIP, wPort); //StringCchCopy(m_szIp, sizeof(TCHAR) * 72, csIpPort.GetBuffer()); //csIpPort.ReleaseBuffer(); return Connect(TranslateAddr(szServerIP), wPort); } //发送函数 bool CTCPSocketService::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), pHead->TCPInfo.cbDataKind); //发送数据 return SendDataBuffer(cbDataBuffer, wSendSize); } //通知回调 void CTCPSocketService::OnQueueServiceSink(WORD wIdentifier, void * pBuffer, WORD wDataSize) { switch (wIdentifier) { case QUEUE_SEND_REQUEST: { ASSERT(pBuffer); ASSERT(wDataSize > 0); if (!pBuffer || wDataSize <= 0) return; //发送数据 WORD wSended = 0; while (wSended < wDataSize) { int iErrorCode = send(m_hSocket, (char *)pBuffer + wSended, wDataSize - wSended, 0); if (iErrorCode == SOCKET_ERROR) { if (WSAGetLastError() == WSAEWOULDBLOCK) { return; } return; } wSended += iErrorCode; } break; } case QUEUE_CONNECT_REQUEST: { //效验状态 if (m_dwServerIP == INADDR_NONE) throw TEXT("目标服务器地址格式不正确,请检查后再次尝试!"); if (m_wPort == 0) throw TEXT("目标服务器地址格式不正确,请检查后再次尝试!"); //建立 SOCKET m_hSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (m_hSocket == INVALID_SOCKET) throw TEXT("SOCKET 创建失败"); //效验参数 ASSERT(m_hSocket != INVALID_SOCKET); ASSERT(m_cbSocketStatus == SOCKET_STATUS_IDLE); int iErrorCode = WSAAsyncSelect(m_hSocket, m_hWnd, MY_WM_SOCKET_NOTIFY, FD_READ | FD_CONNECT | FD_CLOSE); if (iErrorCode == SOCKET_ERROR) throw TEXT("绑定内部窗口错误"); //填写服务器地址 SOCKADDR_IN SocketAddr; memset(&SocketAddr, 0, sizeof(SocketAddr)); SocketAddr.sin_family = AF_INET; SocketAddr.sin_port = htons(m_wPort); SocketAddr.sin_addr.S_un.S_addr = (m_dwServerIP); iErrorCode = connect(m_hSocket, (sockaddr*)& SocketAddr, sizeof(sockaddr)); if (SOCKET_ERROR == iErrorCode) iErrorCode = WSAGetLastError(); break; } case QUEUE_SAFE_CLOSE: { if (m_hSocket != INVALID_SOCKET) { //closesocket(m_hSocket); ///+++ WSAAsyncSelect(m_hSocket, GetSafeHwnd(), MY_WM_SOCKET_NOTIFY, 0); closesocket(m_hSocket); ///+++ m_hSocket = INVALID_SOCKET; } //恢复数据 m_cbSendRound = 0; m_cbRecvRound = 0; m_dwSendXorKey = 0; m_dwRecvXorKey = 0; m_hSocket = INVALID_SOCKET; m_dwSendTickCount = 0; m_dwRecvTickCount = 0; m_dwSendPacketCount = 0; m_dwRecvPacketCount = 0; m_cbSocketStatus = SOCKET_STATUS_IDLE; m_wRecvSize = 0; m_dwServerIP = INADDR_NONE; m_wPort = 0; m_MyEncrypt.Reset(); break; } case QUEUE_DETECT_SOCKET: { } default: { ASSERT(FALSE); return; } } } //发送函数 bool CTCPSocketService::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_BUFFER); if (wDataSize > SOCKET_TCP_BUFFER) 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), pHead->TCPInfo.cbDataKind); #ifdef _DEBUG CString csSend; CString AppName = _T("GameServer"); CString AppName1 = _T("游戏服务器"); CString csTest = AfxGetAppName(); if (!(wSubCmdID == SUB_KN_DETECT_SOCKET && wMainCmdID == MDM_KN_COMMAND) && !(wMainCmdID == 5 && wSubCmdID == 3) && !(wMainCmdID == 2 && wSubCmdID == 1 && (AppName1 == csTest || AppName == csTest))) { csSend.Format(_T("【服务器间通讯】进程【%s】【发送】 -> %s 主命令码【%d】 子命令码【%d】\n\r"), AfxGetAppName(), m_szIp, wMainCmdID, wSubCmdID); //OutputDebugString(csSend); } #endif //发送数据 return SendDataBuffer(cbDataBuffer, wSendSize); } //发送数据 bool CTCPSocketService::SendDataBuffer(void * pBuffer, WORD wSendSize) { //效验参数 ASSERT(wSendSize != 0); ASSERT(pBuffer != NULL); if (NULL == pBuffer || 0 == wSendSize) return false; if (!m_bService){ return true; } return m_QueueService.AddToQueue(QUEUE_SEND_REQUEST, pBuffer, wSendSize); } //关闭连接 VOID CTCPSocketService::CloseSocket(BYTE cbShutReason) { //关闭连接 if (m_bService){ m_QueueServiceEvent.PostTCPSocketCloseEvent(m_wServiceID, cbShutReason); } CloseSocket(); } //解释服务器地址 DWORD CTCPSocketService::TranslateAddr(LPCTSTR pszServerAddr) { USES_CONVERSION;; char * pServerAddr = W2A(pszServerAddr); //转化地址 DWORD dwServerIP = inet_addr(pServerAddr); if (dwServerIP == INADDR_NONE) { LPHOSTENT lpHost = gethostbyname(pServerAddr); if (lpHost == NULL) return INADDR_NONE; dwServerIP = ((LPIN_ADDR)lpHost->h_addr)->s_addr; } return dwServerIP; } //加密数据 WORD CTCPSocketService::EncryptBuffer(BYTE pcbDataBuffer[], WORD wDataSize, WORD wBufferSize, BYTE cbDataKind) { int i = 0; //效验参数 ASSERT(wDataSize >= sizeof(TCP_Head)); ASSERT(wBufferSize >= (wDataSize + 2 * sizeof(DWORD))); ASSERT(wDataSize <= (sizeof(TCP_Head)+SOCKET_TCP_BUFFER)); //填写信息头 TCP_Head * pHead = (TCP_Head *)pcbDataBuffer; pHead->TCPInfo.wPacketSize = wDataSize; pHead->TCPInfo.cbDataKind = DK_MAPPED_NEW; #ifdef MY_ENCRYPT BYTE checkCode = 0; for (WORD i = sizeof(TCP_Info); i < wDataSize; i++) { checkCode += pcbDataBuffer[i]; pcbDataBuffer[i] = MapSendByteEx(pcbDataBuffer[i]); } pHead->TCPInfo.cbCheckCode = ~checkCode + 1; //设置变量 m_dwSendPacketCount++; #else m_MyEncrypt.EncryptBuffer(pcbDataBuffer + 4, wDataSize - 4); #endif return wDataSize; } //解密数据 WORD CTCPSocketService::CrevasseBuffer(BYTE pcbDataBuffer[], WORD wDataSize) { //效验参数 //ASSERT(m_dwSendPacketCount > 0); ASSERT(wDataSize >= sizeof(TCP_Head)); ASSERT(((TCP_Head *)pcbDataBuffer)->TCPInfo.wPacketSize == wDataSize); #ifdef MY_ENCRYPT //效验码与字节映射 TCP_Head * pHead = (TCP_Head *)pcbDataBuffer; for (int i = sizeof(TCP_Info); i < wDataSize; i++) { pcbDataBuffer[i] = MapRecvByteEx(pcbDataBuffer[i]); } #else m_MyEncrypt.DecryptBuffer(pcbDataBuffer + 4, wDataSize - 4); #endif return wDataSize; } //随机映射 WORD CTCPSocketService::SeedRandMap(WORD wSeed) { DWORD dwHold = wSeed; return (WORD)((dwHold = dwHold * 241103L + 2533101L) >> 16); } //映射发送数据 BYTE CTCPSocketService::MapSendByte(BYTE const cbData) { BYTE cbMap; cbMap = g_SendByteMap[cbData]; return cbMap; } //映射接收数据 BYTE CTCPSocketService::MapRecvByte(BYTE const cbData) { BYTE cbMap; cbMap = g_RecvByteMap[cbData]; return cbMap; } //映射发送数据 BYTE CTCPSocketService::MapSendByteEx(BYTE const cbData) { BYTE cbMap; cbMap = g_SendByteMapNew[cbData]; return cbMap; } //映射接收数据 BYTE CTCPSocketService::MapRecvByteEx(BYTE const cbData) { BYTE cbMap; cbMap = g_RecvByteMapNew[cbData]; return cbMap; } //网络连接 LRESULT CTCPSocketService::OnSocketNotifyConnect(WPARAM wParam, LPARAM lParam) { //判断状态 int iErrorCode = WSAGETSELECTERROR(lParam); if (iErrorCode == 0) { m_cbSocketStatus = SOCKET_STATUS_CONNECT; m_bSuccess = true; //发送通知 m_QueueServiceEvent.PostTCPSocketConnectedEvent(m_wServiceID, iErrorCode); } else CloseSocket(SHUT_REASON_TIME_OUT); return 1; } //网络读取 LRESULT CTCPSocketService::OnSocketNotifyRead(WPARAM wParam, LPARAM lParam) { try { //读取数据 int iRetCode = recv(m_hSocket, (char *)m_cbRecvBuf + m_wRecvSize, sizeof(m_cbRecvBuf)-m_wRecvSize, 0); if (iRetCode == SOCKET_ERROR) { throw TEXT("网络连接关闭,读取数据失败"); } ASSERT(m_dwSendPacketCount > 0); m_wRecvSize += iRetCode; m_dwRecvTickCount = GetTickCount() / 1000L; //变量定义 WORD wPacketSize = 0; BYTE cbDataBuffer[SOCKET_TCP_BUFFER + sizeof(TCP_Head)]; TCP_Head * pHead = (TCP_Head *)m_cbRecvBuf; int nCount = 0; while (m_wRecvSize >= sizeof(TCP_Head)) { //效验参数 wPacketSize = pHead->TCPInfo.wPacketSize; if (wPacketSize > (SOCKET_TCP_BUFFER + sizeof(TCP_Head))) { ZeroMemory(m_cbRecvBuf, m_wRecvSize); m_wRecvSize = 0; //throw TEXT("数据包太大"); CTraceService::TraceString(TEXT("数据包太大,丢弃乱包数据重新接收"), TraceLevel_Warning); } if (m_wRecvSize < wPacketSize) return 1; //拷贝数据 m_dwRecvPacketCount++; 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) { switch (Command.wSubCmdID) { case SUB_KN_DETECT_SOCKET: //网络检测 { //发送数据 SendData(MDM_KN_COMMAND, SUB_KN_DETECT_SOCKET, pDataBuffer, wDataSize); break; } default: break; } continue; } //处理数据 const bool bSuccess = m_QueueServiceEvent.PostTCPSocketReadEvent(m_wServiceID, Command, pDataBuffer, wDataSize); if (bSuccess == false) { CString csTestB; csTestB.Format(_T("636行 读取事件 响应失败 ->(MainCmdID:wSubCmdID):(%d:%d),wDataSize=%d"), Command.wMainCmdID, Command.wSubCmdID, wDataSize); CTraceService::TraceString(csTestB, TraceLevel_Warning); throw TEXT("网络数据包处理失败"); } }; } catch (LPCTSTR pszError) { CTraceService::TraceString(pszError, TraceLevel_Warning); CloseSocket(SHUT_REASON_EXCEPTION); } return 1; } //网络关闭 LRESULT CTCPSocketService::OnSocketNotifyClose(WPARAM wParam, LPARAM lParam) { CloseSocket(SHUT_REASON_REMOTE); return 1; } //SOCKET 消息处理程序 LRESULT CTCPSocketService::OnSocketNotify(WPARAM wParam, LPARAM lParam) { switch (WSAGETSELECTEVENT(lParam)) { case FD_CONNECT: //网络连接 { return OnSocketNotifyConnect(wParam, lParam); } case FD_READ: //数据读取 { return OnSocketNotifyRead(wParam, lParam); } case FD_CLOSE: //网络关闭 { return OnSocketNotifyClose(wParam, lParam); } } return 0; } ////////////////////////////////////////////////////////////////////////// //建立对象函数 extern "C" __declspec(dllexport) void * CreateTCPSocketService(const GUID & Guid, DWORD dwInterfaceVer) { //建立对象 CTCPSocketService * pTCPSocketService = NULL; try { pTCPSocketService = new CTCPSocketService(); if (pTCPSocketService == NULL) throw TEXT("创建失败"); void * pObject = pTCPSocketService->QueryInterface(Guid, dwInterfaceVer); if (pObject == NULL) throw TEXT("接口查询失败"); return pObject; } catch (...) {} //清理对象 SafeDelete(pTCPSocketService); return NULL; }