This commit is contained in:
aixianling
2025-01-09 17:45:40 +08:00
commit 5c9f1dae4a
3482 changed files with 1146531 additions and 0 deletions

View File

@@ -0,0 +1,17 @@
{
"configurations": [
{
"name": "Linux",
"includePath": [
"${workspaceFolder}/**"
],
"defines": [],
"compilerPath": "/usr/bin/gcc",
"cStandard": "c11",
"cppStandard": "c++14",
"intelliSenseMode": "clang-x64",
"compileCommands": "${workspaceFolder}/build/compile_commands.json"
}
],
"version": 4
}

46
server/GateServer/.vscode/launch.json vendored Normal file
View File

@@ -0,0 +1,46 @@
{
// 使用 IntelliSense 了解相关属性。
// 悬停以查看现有属性的描述。
// 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "(gdb) 启动",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/../../build/GateServer/gateserver_d",
"args": ["${workspaceFolder}/../../build/GateServer/GateServerLinux.txt"],
"stopAtEntry": false,
"cwd": "${workspaceFolder}",
"environment": [],
"externalConsole": false,
"MIMode": "gdb",
"setupCommands": [
{
"description": "为 gdb 启用整齐打印",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
],
"showDisplayString": true,
"additionalSOLibSearchPath": "${workspaceFolder}/../common/libs;${workspaceFolder}/../srvlib/libs;${workspaceFolder}/../../common/cpp/libs/3rd/bin;"
},
{
"name": "(gdb) 附加",
"type": "cppdbg",
"request": "attach",
"program": "${workspaceFolder}/../../build/GateServer/gateserver_d",
"processId": "${command:pickProcess}",
"MIMode": "gdb",
"setupCommands": [
{
"description": "为 gdb 启用整齐打印",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
],
"showDisplayString": true,
"additionalSOLibSearchPath": "${workspaceFolder}/../common/libs;${workspaceFolder}/../srvlib/libs;${workspaceFolder}/../../common/cpp/libs/3rd/bin;"
}
]
}

165
server/GateServer/.vscode/settings.json vendored Normal file
View File

@@ -0,0 +1,165 @@
{
"C_Cpp.default.cppStandard": "c++11",
"C_Cpp.default.cStandard": "c11",
"C_Cpp.default.intelliSenseMode": "gcc-x64",
"C_Cpp.intelliSenseEngineFallback": "Enabled",
"C_Cpp.intelliSenseEngine": "Tag Parser",
"C_Cpp.default.includePath": [
"${default}",
"${workspaceFolder}/include/**"
],
"cmake.buildDirectory": "${workspaceFolder}/../build",
"cmake.configureOnOpen": true,
// 启用跟踪日志到文件和控制台(非常嘈杂)。
"cmake.enableTraceLogging": true,
"workbench.list.horizontalScrolling": true,
"workbench.tree.indent": 10,
"workbench.editor.tabSizing": "shrink",
"workbench.settings.openDefaultSettings": true,
"workbench.settings.openDefaultKeybindings": true,
"workbench.sideBar.location": "right",
"terminal.integrated.cursorBlinking": true,
"terminal.integrated.confirmOnExit": true,
"editor.renderWhitespace": "none",
"editor.renderControlCharacters": false,
// 启用后,扩展将本地下载并安装在远程上。
"remote.downloadExtensionsLocally": true,
// 始终显示SSH登录终端。
"remote.SSH.showLoginTerminal": true,
// 默认行尾字符。
// - \n: LF
// - \r\n: CRLF
// - auto: 使用具体操作系统规定的行末字符。
"files.eol": "auto",
// 配置排除的文件和文件夹的 glob 模式。
// 例如,文件资源管理器将根据此设置决定要显示或隐藏的文件和文件夹。
"files.exclude": {
"bin": true,
"build": true,
"lib": true,
"cmake": true,
"test/bin": true,
"test/lib": true,
"**/.vscode": false
},
// 配置文件路径的 glob 模式以从文件监视排除。
// 模式必须在绝对路径上匹配(例如 ** 前缀或完整路径需正确匹配)。
// 更改此设置需要重启。如果在启动时遇到 Code 消耗大量 CPU 时间,则可以排除大型文件夹以减少初始加载。
"files.watcherExclude": {
"**/.git/objects/**": true,
"**/.git/subtree-cache/**": true,
"**/node_modules/*/**": true,
"**/.vscode": true,
"bin": true,
"build": true,
"cmake": true,
"test/bin": true,
"test/lib": true
},
// 控制已更新文件的自动保存。可在[此处](https://code.visualstudio.com/docs/editor/codebasics#_save-auto-save)阅读有关自动保存的详细信息。
// - off: 永不自动保存更新后的文件。
// - afterDelay: 当文件修改后的时间超过 `files.autoSaveDelay` 中配置的值时自动进行保存。
// - onFocusChange: 编辑器失去焦点时自动保存更新后的文件。
// - onWindowChange: 窗口失去焦点时自动保存更新后的文件。
"files.autoSave": "off",
// 启用后,保存文件时在文件末尾插入一个最终新行。
"files.insertFinalNewline": true,
// 实验性:启用后,允许在编辑器中打开工作区搜索结果。
"search.enableSearchEditorPreview": true,
// 控制调试工具栏的位置。可在所有视图中“浮动”、在调试视图中“停靠”,也可“隐藏”。
//"search.location": "panel",
// 控制是否显示搜索结果所在的行号。
"search.showLineNumbers": true,
// 控制在搜索文件时是否使用 `.gitignore` 和 `.ignore` 文件。
"search.useIgnoreFiles": true,
// 控制在搜索文件时是否使用全局 `.gitignore` 和 `.ignore` 文件。
"search.useGlobalIgnoreFiles": true,
// 配置在搜索中排除的文件和文件夹的 glob 模式。已经继承 `files.exclude` 设置的所有 glob 模式。可在[此处](https://code.visualstudio.com/docs/editor/codebasics#_advanced-search-options)阅读有关 glob 模式的详细信息。
"search.exclude": {
"**/node_modules": true,
"**/bower_components": true,
"**/*.code-search": true
},
"files.associations": {
"ctime": "cpp",
"ratio": "cpp",
"chrono": "cpp",
"system_error": "cpp",
"type_traits": "cpp",
"bitset": "cpp",
"deque": "cpp",
"forward_list": "cpp",
"list": "cpp",
"string": "cpp",
"unordered_map": "cpp",
"vector": "cpp",
"functional": "cpp",
"optional": "cpp",
"tuple": "cpp",
"array": "cpp",
"string_view": "cpp",
"utility": "cpp",
"future": "cpp",
"typeinfo": "cpp",
"atomic": "cpp",
"hash_map": "cpp",
"hash_set": "cpp",
"*.tcc": "cpp",
"cctype": "cpp",
"clocale": "cpp",
"cmath": "cpp",
"condition_variable": "cpp",
"csignal": "cpp",
"cstdarg": "cpp",
"cstddef": "cpp",
"cstdint": "cpp",
"cstdio": "cpp",
"cstdlib": "cpp",
"cstring": "cpp",
"cwchar": "cpp",
"cwctype": "cpp",
"exception": "cpp",
"algorithm": "cpp",
"iterator": "cpp",
"map": "cpp",
"memory": "cpp",
"memory_resource": "cpp",
"numeric": "cpp",
"random": "cpp",
"regex": "cpp",
"set": "cpp",
"fstream": "cpp",
"initializer_list": "cpp",
"iomanip": "cpp",
"iosfwd": "cpp",
"iostream": "cpp",
"istream": "cpp",
"limits": "cpp",
"mutex": "cpp",
"new": "cpp",
"ostream": "cpp",
"sstream": "cpp",
"stdexcept": "cpp",
"streambuf": "cpp",
"thread": "cpp",
"cinttypes": "cpp"
},
}

View File

@@ -0,0 +1,66 @@
cmake_minimum_required(VERSION 2.6)
project(gateserver)
add_definitions(-std=c++11)
# Avoid warnings in higher versions
if("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" GREATER 2.6)
CMAKE_POLICY(VERSION 2.8)
endif()
MESSAGE(STATUS "Running cmake version ${CMAKE_VERSION}")
if( NOT CMAKE_BUILD_TYPE )
set(CMAKE_BUILD_TYPE "Release")
endif()
add_definitions(-D_GNU_SOURCE -D_REENTRANT)
#is or not shared type
if( BUILD_SHARED_LIBS )
SET ( LIBS_TYPE SHARED)
else()
SET ( LIBS_TYPE STATIC)
endif()
set( ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR} )
set( CMAKE_MODULE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../common)
set( CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_MODULE_DIR}/cmake/modules)
set(LIBRARY_OUTPUT_PATH ${ROOT_PATH}/libs)
set(BINARY_OUTPUT_PATH ${ROOT_PATH}/libs)
set(CMAKE_CXX_FLAGS_DEBUG "$ENV{CXXFLAGS} -O0 -w -g2 -ggdb -fPIC -z muldefs -lpthread -lrt -lz -ldl -lm -D_DEBUG")
set(CMAKE_CXX_FLAGS_RELEASE "$ENV{CXXFLAGS} -O3 -w -fPIC -z muldefs -lpthread -lrt -lz -ldl -lm")
include_directories(
${CMAKE_CURRENT_SOURCE_DIR}/../srvlib/include
${CMAKE_CURRENT_SOURCE_DIR}/../../common/cpp/libs/src/wylib/include
${CMAKE_CURRENT_SOURCE_DIR}/../../common/cpp/libs/src/lua-5.1/src
${CMAKE_CURRENT_SOURCE_DIR}/../../common/cpp/libs/src/tolua++/src
${CMAKE_CURRENT_SOURCE_DIR}/../../common/cpp/libs/3rd/inc/mysql-5.2/include
${CMAKE_CURRENT_SOURCE_DIR}/../../common/cpp/libs/3rd/inc/breakpad/
${CMAKE_CURRENT_SOURCE_DIR}/../common/include
${CMAKE_CURRENT_SOURCE_DIR}/../common/def
${CMAKE_CURRENT_SOURCE_DIR}
)
file(GLOB sources1 *.cpp)
file(GLOB sources2 */*.cpp)
file(GLOB sources3 */*/*.cpp)
if ( ${CMAKE_BUILD_TYPE} STREQUAL "Release" )
set( _DEBUG 0 )
else ()
set( _DEBUG 1 )
endif()
if ( _DEBUG )
set( EXE_NAME gateserver_d )
else()
set( EXE_NAME gateserver_r )
endif()
SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/../../build/GateServer)
add_executable(${EXE_NAME} ${sources1} ${sources2} ${sources3} )
include(../common/cmake/libs.cmake)

View File

@@ -0,0 +1,11 @@
#include "StdAfx.h"
#include "StackWalker.h"
#ifdef WIN32
DWORD CustomExceptHandler(const LPEXCEPTION_POINTERS lpPointers)
{
SHOW_CALLSTACK();
return DefaultExceptHandler(lpPointers);
}
#endif

View File

@@ -0,0 +1,9 @@
#pragma once
#ifdef WIN32
/************************************************************************/
/* 自定义SEH异常处理Handler输出异常类型、异常发生地址等信息并且进行栈回溯。用于解决
某些不是 特别重要的异常发生被捕获后,继续程序的执行,但是可能导致的一些潜在的问题不被发现,
导致后面很定位的问题。
/************************************************************************/
DWORD CustomExceptHandler(const LPEXCEPTION_POINTERS lpPointers);
#endif

View File

@@ -0,0 +1,583 @@
#include "StdAfx.h"
CCustomGateClient::CCustomGateClient()
{
m_szSrvHost[0] = _T('\0');
m_szClientName[0] = _T('\0');
m_nSrvPort = 0;
m_bStoped = false;
m_bConnected = false;
m_hConnectThread = INVALID_HANDLE_VALUE;
m_hSendDataThread = INVALID_HANDLE_VALUE;
m_hRecvDataThread = INVALID_HANDLE_VALUE;
m_socket = INVALID_SOCKET;
m_SendMsgList.setLock(&m_SendMsgLock);
m_FreeMsgList.setLock(&m_FreeMsgLock);
m_RecvMsgList.setLock(&m_RecvMsgLock);
m_RecvFreeMsgList.setLock(&m_RecvFreeMsgLock);
ZeroMemory(&m_RecvMsg, sizeof(m_RecvMsg));
m_SendBigPacket.setAllocator(&m_Allocator);
}
CCustomGateClient::~CCustomGateClient()
{
Stop();
UnintSocketLib();
// 删除所有的数据包
DestroyPacketList(m_SendingPacketList);
DestroyPacketList(m_FreeMsgList);
DestroyPacketList(m_RecvMsgList);
DestroyPacketList(m_RecvFreeMsgList);
}
bool CCustomGateClient::Startup()
{
OutputMsg(rmTip, _T("CustomGateClient[%s] Start..."), m_szClientName);
Stop();
if (!InitSockLib())
return false;
m_bStoped = false;
// 创建连接线程
#ifdef _MSC_VER
m_hConnectThread = ::CreateThread(NULL, 0, staticConnectThreadRountine, this, 0, NULL);
#else
pthread_create(&m_hConnectThread, NULL, staticConnectThreadRountine, this);
#endif
if (m_hConnectThread != INVALID_HANDLE_VALUE)
{
#ifdef _MSC_VER
CloseHandle(m_hConnectThread);
#endif
}
else
{
OutputMsg(rmError, _T("%s Create Connect Thread Failed[errcode:%d]"), __FUNCTION__, GetLastError());
return false;
}
// 创建发送线程
#ifdef _MSC_VER
m_hSendDataThread = ::CreateThread(NULL, 0, staticSendDataThreadRountine, this, 0, NULL);
#else
pthread_create(&m_hSendDataThread, NULL, staticSendDataThreadRountine, this);
#endif
if (m_hSendDataThread != INVALID_HANDLE_VALUE)
{
#ifdef _MSC_VER
CloseHandle(m_hSendDataThread);
#endif
}
else
{
OutputMsg(rmError, _T("%s Create SendData Thread Failed[errcode:%d]"), __FUNCTION__, GetLastError());
return false;
}
// 创建接收数据线程
#ifdef _MSC_VER
m_hRecvDataThread = ::CreateThread(NULL, 0, staticRecvDataThreadRountine, this, 0, NULL);
#else
pthread_create(&m_hRecvDataThread, NULL, staticRecvDataThreadRountine, this);
#endif
if (m_hRecvDataThread != INVALID_HANDLE_VALUE)
{
#ifdef _MSC_VER
CloseHandle(m_hRecvDataThread);
#endif
}
else
{
OutputMsg(rmError, _T("%s Create SendData Thread Failed[errcode:%d]"), __FUNCTION__, GetLastError());
return false;
}
return true;
}
void CCustomGateClient::Stop()
{
m_bStoped = true;
Close();
Sleep(3000);
}
void CCustomGateClient::Close()
{
if (m_socket != INVALID_SOCKET)
{
closesocket(m_socket);
m_socket = INVALID_SOCKET;
}
if (m_bConnected)
{
m_bConnected = false;
// 清空缓存数据数据
m_RecvMsgList.flush();
m_RecvFreeMsgList.appendArray(m_RecvMsgList, m_RecvMsgList.count());
m_RecvMsgList.trunc(0);
m_SendingPacketList.flush();
m_FreeMsgList.appendArray(m_SendingPacketList, m_SendingPacketList.count());
m_SendingPacketList.trunc(0);
OutputMsg(rmTip, _T("与[%s]连接断开..."), m_szClientName);
}
OnClosed();
}
void CCustomGateClient::SendRegisteClient()
{
}
void CCustomGateClient::SendKeepAlive()
{
}
void CCustomGateClient::SendDataRoutine()
{
while (!m_bStoped)
{
// 如果已经连接上,发送数据
if (m_bConnected)
{
TICKCOUNT nStartTick = _getTickCount();
m_SendMsgList.flush();
INT_PTR nCount = m_SendMsgList.count();
if (nCount > 0)
{
for (INT_PTR i = 0; i < nCount; i++)
{
CDataPacket* packet = m_SendMsgList[i];
size_t nAvailableLen = packet->getAvaliableLength();
if (nAvailableLen > 0)
{
//if (!SendPointedData(packet->getOffsetPtr(), nAvailableLen)) // 发送数据出错,退出
// break;
m_SendBigPacket.writeBuf(packet->getOffsetPtr(), nAvailableLen);
}
}
// 采取打包的方式发送给服务器
m_SendBigPacket.setPosition(0);
INT_PTR nAvailableLen = m_SendBigPacket.getAvaliableLength();
if (nAvailableLen > 0)
{
SendPointedData(m_SendBigPacket.getOffsetPtr(), nAvailableLen);
m_SendBigPacket.setLength(0);
}
m_FreeMsgList.appendArray(m_SendMsgList, nCount);
m_SendMsgList.trunc(0);
}
Sleep(3);
}
else
{
Sleep(100);
}
}
}
bool CCustomGateClient::SendPointedData(const char* pData, size_t nLen)
{
DECLARE_FUN_TIME_PROF()
int nRet;
while (nLen > 0)
{
nRet = ::send(m_socket, pData, (int)nLen, 0);
if (SOCKET_ERROR == nRet)
{
Close();
return false;
}
pData += nRet;
nLen -= nRet;
}
return true;
}
void CCustomGateClient::RecvDataRoutine()
{
nPacketCount = 0;
while (!m_bStoped)
{
if (!m_bConnected)
{
Sleep(20);
continue;
}
// 读取消息头
bool bRet = ReadPointedData((char *)&(m_RecvMsg.header), sizeof(GATEMSGHDR));
if (!bRet)
{
OutputMsg(rmError, _T("Recv MsgHeader failed req=%d"), sizeof(GATEMSGHDR));
continue;
}
// 读取消息体
int nLen = m_RecvMsg.header.nDataSize;
if (m_RecvMsg.nBuffLen < nLen)
{
if (m_RecvMsg.data != NULL)
m_Allocator.FreeBuffer(m_RecvMsg.data);
m_RecvMsg.data = (char *)m_Allocator.AllocBuffer(nLen);
m_RecvMsg.nBuffLen = nLen;
}
bRet = ReadPointedData(m_RecvMsg.data, nLen);
if (!bRet)
{
OutputMsg(rmError, _T("Recv Msg Data Failed Req=%d"), nLen);
continue;
}
nPacketCount++;
// 拷贝数据到接收队列中, 不直接处理数据
CDataPacket* packet = AllocRecvPacket();
*packet << m_RecvMsg.header;
if (nLen > 0)
packet->writeBuf(m_RecvMsg.data, nLen);
*packet << (int)0xeeff;
packet->setPosition(0);
m_RecvMsgList.append(packet);
#ifdef _DEBUG
memset(&m_RecvMsg, 0, sizeof(m_RecvMsg));
#endif
//ProcessRecvBuffers(&m_RecvMsg);
}
}
bool CCustomGateClient::ReadPointedData(char* pBuff, size_t len)
{
DECLARE_FUN_TIME_PROF()
int nBytesRead;
while (len)
{
nBytesRead = recv(m_socket, pBuff, (int)len, 0);
if (nBytesRead <= 0)
{
Close();
return false;
}
pBuff += nBytesRead;
len -= nBytesRead;
}
return true;
}
void CCustomGateClient::PutMessage(int nIdent,
int nSessionIdx,
SOCKET nSocket,
int nServerIdx,
unsigned long long param,
char *pBuffer,
int nBufSize)
{
DECLARE_FUN_TIME_PROF()
if (!m_bConnected)
return;
//这个是消息头
RUNGATEMSGHDR Hdr;
Hdr.dwGateCode = RUNGATECODE;
Hdr.nSocket = nSocket;
Hdr.wSessionIdx = nSessionIdx;
Hdr.wIdent = nIdent;
Hdr.wServerIdx = nServerIdx;
Hdr.nDataSize = nBufSize;
Hdr.tickCount = param + _getTickCount();
SIZE_T headSize = sizeof(Hdr);
CDataPacket* packet = AllocPacket();
if (packet->getPosition() != 0)
{
OutputMsg(rmError, _T("-------------------------------"));
}
if (packet->getAvaliableLength() != 0)
{
OutputMsg(rmError, _T("--------------|||-----------------"));
}
packet->operator<<(Hdr);
if (nBufSize > 0)
{
packet->writeBuf(pBuffer, nBufSize);
}
packet->setPosition(0);
if (packet->getAvaliableLength() != sizeof(Hdr) + nBufSize)
{
OutputMsg(rmError, _T("--------------packet error[%d]--------------"), nBufSize);
}
m_SendMsgList.append(packet);
}
CDataPacket* CCustomGateClient::AllocPacket()
{
if (m_FreeMsgList.count() > 0)
{
CDataPacket* pkg = m_FreeMsgList.pop();
pkg->setLength(0);
return pkg;
}
if (m_FreeMsgList.appendCount() > 0)
m_FreeMsgList.flush();
if (m_FreeMsgList.count() <= 0 )
allocSendPacketList(m_FreeMsgList, 512);
CDataPacket* pkg = m_FreeMsgList.pop();
pkg->setLength(0);
return pkg;
}
CDataPacket* CCustomGateClient::AllocRecvPacket()
{
if (m_RecvFreeMsgList.count() > 0)
{
CDataPacket* pkg = m_RecvFreeMsgList.pop();
pkg->setLength(0);
return pkg;
}
if (m_RecvFreeMsgList.appendCount() > 0)
m_RecvFreeMsgList.flush();
if (m_RecvFreeMsgList.count() <= 0 )
allocSendPacketList(m_RecvFreeMsgList, 512);
CDataPacket* pkg = m_RecvFreeMsgList.pop();
pkg->setLength(0);
return pkg;
}
bool CCustomGateClient::CreateSocket()
{
if (m_socket != INVALID_SOCKET)
{
OutputMsg(rmError, _T("Socket is createdc already"));
return false;
}
m_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
return m_socket != INVALID_SOCKET ? true : false;
}
bool CCustomGateClient::ConnectToServerImpl()
{
int nErr;
TICKCOUNT dwCurTick = _getTickCount();
//创建套接字
if (INVALID_SOCKET == m_socket)
{
if (!CreateSocket())
{
OutputMsg(rmError, _T("[%s]Create Socket Failed"), __FUNCTION__);
return false;
}
}
hostent *phost;
#ifdef UNICODE
wylib::string::CWideString ws(addr);
wylib::string::CAnsiString *as = ws.toAStr();
phost = gethostbyname(*as);
delete as;
#else
phost = gethostbyname(m_szSrvHost);
#endif
if (phost)
{
in_addr addr;
addr.s_addr = *(u_long*)phost->h_addr_list[0];
SOCKADDR_IN addrin;
ZeroMemory(&addrin, sizeof(addrin));
addrin.sin_family = AF_INET;
addrin.sin_addr.s_addr = addr.s_addr;
addrin.sin_port = (htons((u_short)m_nSrvPort));
nErr = ::connect(m_socket, (sockaddr*)&addrin, sizeof(addrin));
if ( nErr == 0 )
{
OnConnected();
return true;
}
else
{
OutputMsg(rmNormal, _T("连接到%s服务器失败..."), m_szClientName);
return false;
}
}
else
{
OutputMsg(rmError, _T("GetHostByName resolve failed"));
return false;
}
return true;
}
void CCustomGateClient::OnConnected()
{
m_bConnected = true;
}
void CCustomGateClient::OnClosed()
{
}
void CCustomGateClient::ProcessRecvDataImpl()
{
DECLARE_FUN_TIME_PROF()
m_RecvMsgList.flush();
CDataPacket* packet;
INT_PTR nCount = m_RecvMsgList.count();
for (INT_PTR i = 0; i < nCount; i++)
{
packet = m_RecvMsgList[i];
GATEMSGHDR* pHeader = (GATEMSGHDR *)packet->getMemoryPtr();
ProcessRecvBuffers(pHeader, (LPCSTR)(pHeader+1), pHeader->nDataSize);
int *pVerify = (int *)((char *)pHeader + sizeof(GATEMSGHDR) + pHeader->nDataSize);
Assert(*pVerify == 0xeeff);
}
m_RecvFreeMsgList.appendArray(m_RecvMsgList, m_RecvMsgList.count());
m_RecvMsgList.trunc(0);
}
void CCustomGateClient::ConnectToServerRoutine()
{
TICKCOUNT dwReconnectTick = _getTickCount();
while (!m_bStoped)
{
if (m_bConnected)
{
ProcessRecvDataImpl();
Sleep(3);
}
else
{
// Try Connect To Server
if (_getTickCount() >= dwReconnectTick)
{
if (ConnectToServerImpl())
{
OutputMsg(rmNormal, _T("连接到服务器[%s]成功"), m_szClientName);
}
dwReconnectTick = _getTickCount() + 5000;
}
Sleep(200);
}
}
return;
}
void CCustomGateClient::SingleRun()
{
}
bool CCustomGateClient::InitSockLib()
{
#ifdef WIN32
WSADATA wsaData;
int nErr = WSAStartup(0x0202, &wsaData);
if (nErr != 0)
{
OutputMsg(rmError, _T("%s Init Socket Lib Failed, errcode=%d"), __FUNCTION__, nErr);
return false;
}
if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2)
{
OutputMsg(rmError, "Could not find a usable version[2.2] of Winsock.dll\n");
return false;
}
#endif
return true;
}
void CCustomGateClient::UnintSocketLib()
{
#ifdef WIN32
WSACleanup();
#endif
}
#ifdef _MSC_VER
DWORD CCustomGateClient::staticConnectThreadRountine(LPVOID pParam)
#else
void* CCustomGateClient::staticConnectThreadRountine(void* pParam)
#endif
{
CCustomGateClient* pThis = (CCustomGateClient *)pParam;
if (pThis)
pThis->ConnectToServerRoutine();
return 0;
}
#ifdef _MSC_VER
DWORD CCustomGateClient::staticSendDataThreadRountine(LPVOID pParam)
#else
void* CCustomGateClient::staticSendDataThreadRountine(void* pParam)
#endif
{
CCustomGateClient* pThis = (CCustomGateClient *)pParam;
if (pThis)
pThis->SendDataRoutine();
return 0;
}
#ifdef _MSC_VER
DWORD CCustomGateClient::staticRecvDataThreadRountine(LPVOID pParam)
#else
void* CCustomGateClient::staticRecvDataThreadRountine(void* pParam)
#endif
{
CCustomGateClient* pThis = (CCustomGateClient *)pParam;
if (pThis)
pThis->RecvDataRoutine();
return 0;
}
void CCustomGateClient::SetClientName(LPCTSTR sClientName)
{
_tcsncpy(m_szClientName, sClientName, ArrayCount(m_szClientName) - 1);
m_szClientName[ArrayCount(m_szClientName) - 1] = 0;
}
void CCustomGateClient::SetServerHost(LPCTSTR sHost)
{
_tcsncpy(m_szSrvHost, sHost, ArrayCount(m_szSrvHost) - 1);
m_szSrvHost[ArrayCount(m_szSrvHost) - 1] = 0;
}
void CCustomGateClient::SetServerPort(const INT_PTR nPort)
{
m_nSrvPort = nPort;
}
void CCustomGateClient::Dump()
{
OutputMsg(rmTip, _T("等待发送数据包数量: %d个\r\n"), (int)(m_SendMsgList.count() + m_SendMsgList.appendCount()));
}
void CCustomGateClient::DestroyPacketList(CQueueList<CDataPacket*>& pkgList)
{
if (pkgList.appendCount() > 0)
pkgList.flush();
for (INT_PTR i = pkgList.count()-1; i >= 0; i--)
{
CDataPacket* pkg = pkgList[i];
pkg->~CDataPacket();
}
pkgList.clear();
}

View File

@@ -0,0 +1,139 @@
#pragma once
// 网关客户端类,负责处理和服务器数据包的接收和发送
// 采取阻塞方式实现
class CCustomGateClient : protected CSendPacketPool
{
public:
typedef struct tagGateMsg
{
GATEMSGHDR header;
int nBuffLen; // 数据buff的长度
char* data;
}GateMsg;
// ctor and dtor
CCustomGateClient();
virtual ~CCustomGateClient();
// 启动客户端
bool Startup();
// 停止客户端
void Stop();
// 判读是否连接上服务器
bool connected() const { return m_bConnected; }
// 增加发送数据
void PutMessage(int nIdent,
int nSessionIdx,
SOCKET nSocket,
int nServerIdx,
unsigned long long param,
char *pBuffer,
int nBufSize);
// 获取客户端名称
inline LPCTSTR GetClientName() const { return m_szClientName; };
// 设置客户端名称
void SetClientName(LPCTSTR sClientName);
// 获取远程服务器地址
inline LPCTSTR GetServerHost() const { return m_szSrvHost; }
// 设置远程服务器地址(支持域名)
void SetServerHost(LPCTSTR sHost);
// 获取远程服务器端口
inline INT_PTR GetServerPort() const { return m_nSrvPort; }
// 设置远程服务器端口
void SetServerPort(const INT_PTR nPort);
// Dump数据包情况
void Dump();
//覆盖例行执行函数
void SingleRun();
protected:
// 连接到服务器
virtual void OnConnected();
virtual void OnClosed();
// 连接到服务器成功后发送注册客户端的消息
virtual void SendRegisteClient();
// 当长时间没有通信后发送保持连接的消息
virtual void SendKeepAlive();
// 接收到网关数据
//virtual void ProcessRecvBuffers(const GateMsg* msgData) = 0;
virtual void ProcessRecvBuffers(const GATEMSGHDR* pHeader, LPCSTR pData, size_t nLen) = 0;
// 关闭套接字
void Close();
// 创建套接字
bool CreateSocket();
// 连接到服务器
bool ConnectToServerImpl();
// 发送指定长度的数据
bool SendPointedData(const char* pData, size_t nLen);
bool ReadPointedData(char* pOutBuff, size_t nLen);
// 分配发送给服务器的数据包
CDataPacket* AllocPacket();
// 分配接收到的数据包
CDataPacket* AllocRecvPacket();
private:
// 初始化套接字库
bool InitSockLib();
// 卸载套接字库
void UnintSocketLib();
// 工作线程函数
#ifdef _MSC_VER
static DWORD WINAPI staticConnectThreadRountine(LPVOID pParam);
#else
static void* staticConnectThreadRountine(void* pParam);
#endif
void ConnectToServerRoutine();
// 发送数据线程
#ifdef _MSC_VER
static DWORD WINAPI staticSendDataThreadRountine(LPVOID pParam);
#else
static void* staticSendDataThreadRountine(void* pParam);
#endif
void SendDataRoutine();
// 接收数据线程
#ifdef _MSC_VER
static DWORD WINAPI staticRecvDataThreadRountine(LPVOID pParam);
#else
static void* staticRecvDataThreadRountine(void* pParam);
#endif
void RecvDataRoutine();
void ProcessRecvDataImpl();
void DestroyPacketList(CQueueList<CDataPacket*>& pkgList);
private:
SOCKET m_socket;
TCHAR m_szSrvHost[256]; // 服务器地址
INT_PTR m_nSrvPort; // 服务器端口
TCHAR m_szClientName[256]; // 客户端名称
bool m_bConnected; // 是否已经连接上
volatile LONG m_bStoped; // 是否标记为停止
#ifdef _MSC_VER
HANDLE m_hConnectThread; // 连接服务器线程
HANDLE m_hSendDataThread; // 发送数据线程
HANDLE m_hRecvDataThread; // 接收数据线程
#else
pthread_t m_hConnectThread;
pthread_t m_hSendDataThread;
pthread_t m_hRecvDataThread;
#endif
CQueueList<CDataPacket*>m_SendMsgList; // 发送消息队列
CCSLock m_SendMsgLock; // 发送消息锁
CQueueList<CDataPacket*>m_FreeMsgList; // 空闲消息队列
CCSLock m_FreeMsgLock; // 空闲消息锁
GateMsg m_RecvMsg; // 当前接受的消息数据
CBufferAllocator m_Allocator; // 内存块管理器
// 接收数据不直接派发上去,而是经过这个缓冲,保证接收数据的及时性
CQueueList<CDataPacket*>m_RecvMsgList; // 接受消息队列
CCSLock m_RecvMsgLock; // 接受消息锁
CQueueList<CDataPacket*>m_RecvFreeMsgList; // 空闲消息队列
CCSLock m_RecvFreeMsgLock; // 空闲消息锁
CDataPacket m_SendBigPacket; // 发送给服务器的大数据包缓存
int nPacketCount;
};

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,207 @@
#ifndef _DATAPROCESS_H_
#define _DATAPROCESS_H_
#define RUNDATA_MAX_SENDTHREAD 8
#define MAX_SEND_BUFF_SIZE 8192 //最大的发送缓从的大小
class CRunDataProcesser;
using namespace wylib::container;
//数据发送线程
typedef struct tagRunDataSendThread
{
#ifdef _MSC_VER
HANDLE hThread;
#else
pthread_t hThread;
#endif
int nThreadIdx;
DWORD dwThreadId;
TICKCOUNT dwProcTick;
TICKCOUNT dwSleepTick;
bool boSendEWouldBlock;
bool boSendFewBuffer;
BYTE btRcvs[2];
CRunDataProcesser *pRunData;
CRITICAL_SECTION SendQueueLock;
CBaseList<LPVOID> *pSendAppendList;
CBaseList<LPVOID> *pSendProcList;
}RUNDATASENDTHREAD, *PRUNDATASENDTHREAD;
//网关数据处理类型
typedef enum tagDataProcesserType
{
dp_Default = 0,
dp_GameEngine = 1
}DATAPROCESSERTYPE;
class CRunSockProcesser;
class CRunDataProcesser : public CCustomGateClient
//: public CCustomClientSocket
{
public:
//typedef CCustomClientSocket Inherited;
typedef CCustomGateClient Inherited;
static int s_nIgnoreDataPacket;
private:
typedef struct tagClientRecvBuf
{
PRUNGATEUSERSESSION pSession;
int nBufferSize;
ULONG_PTR nVerify;
}CLIENTRECVBUF, *PCLIENTRECVBUF,
SENDCLIENTBUF, *PSENDCLIENTBUF;
static const int SIZE_OPENUSER = -1;
static const int SIZE_CLOSEUSER = -2;
private:
int m_nActiveUser; //活动连接数
BOOL m_boStoping; //是否正在停止服务
BOOL m_boStarted; //是否已经启动服务
//HANDLE m_hPipe; //与服务器通信管道
//CHAR m_sPipeName[MAX_PATH]; //管道名称
CHAR m_sGateName[64]; //网关名称
int m_nSendThreadCount; //发送线程数量
DATAPROCESSERTYPE m_DataProcessType;
#ifdef _MSC_VER
HANDLE m_hProcRecvThread;
#else
pthread_t m_hProcRecvThread;
#endif
RUNDATASENDTHREAD m_SendThreads[RUNDATA_MAX_SENDTHREAD];
RTL_CRITICAL_SECTION m_SessionLock;
int m_nMaxSessionCount;
PRUNGATEUSERSESSION m_Sessions; //用户会话队列
RTL_CRITICAL_SECTION m_RecvQueueLock;
CBaseList<LPVOID> m_RecvQueue[2];
CBaseList<LPVOID> *m_pRecvAppendList;
CBaseList<LPVOID> *m_pRecvProcList;
RUNGATEDATABUF m_ServerBuf;
long long m_nUserVerify;
BOOL m_boPrintC2SMsg;//是否打印客户端向服务器发送的数据包
BOOL m_boPrintS2CMsg;//是否打印服务器向客户端发送的数据包
//CCustomClientSocket m_pServerRcvSocket; //接受服务器的数据的socket
//CNetworkDataHandler m_DataPacker; //数据接包器
CRunSockProcesser* m_pSockProcesser; // Sock用户处理
int m_nCheckTimeCount;
long long m_llOccuTimeDiff;
long long m_llSvrTimeDiff; // 服务器与本客户端的时间差
long long m_llSendKeepAliveTime; // 网关发送心跳包给服务器的时间
#ifdef _MSC_VER
static VOID STDCALL RecvDataProcessRoutine(void *pRunData);
static VOID STDCALL SendDataProcessRoutine(void *pRunThread);
//static VOID STDCALL RecvServerProcessRoutine(void *pRunData);
#else
static VOID* RecvDataProcessRoutine(void *pRunData);
static VOID* SendDataProcessRoutine(void *pRunThread);
//static VOID* RecvServerProcessRoutine(void *pRunData);
#endif
VOID InitSessions();
VOID UninitSessions();
VOID FreeRecvBuffers();
VOID FreeSendBuffers(PRUNDATASENDTHREAD pSendThread);
BOOL CopyWaitSendBuffers(PRUNDATASENDTHREAD pSendThread, BOOL boForceCopy);
protected:
VOID GetSessionLoginInfo(PRUNGATEUSERSESSION pSession, char *sBuffer, int nBufferSize);
protected:
VOID GotError(LPCSTR sErrFn, LPCSTR sErrApi, int nErr);
VOID InitSendThreadData();
VOID UninitSendThreadData();
VOID SendCheck(int nIdent);
VOID SendGateUserInfo();
public:
VOID SendOpenSession(PRUNGATEUSERSESSION pSession);
VOID SendCloseSession(PRUNGATEUSERSESSION pSession, BOOL boCloseOnServer = TRUE, INT nReason = 0);
protected:
VOID SendKeepAliveAck(PRUNGATEUSERSESSION pSession, const char *pBuffer, SIZE_T nBufSize);
VOID CloseAllSessions(BOOL boForceClose);
VOID CancelRemainSendSessionBuffers();
BOOL CheckCloseSessions(BOOL boForceCheck);
VOID CheckSendSessionBuffers(PRUNDATASENDTHREAD pSendThread);
//websocket握手
VOID ShakeHandsHandle(PRUNGATEUSERSESSION pSession, char* pBuffer, int BufferSize);
//发送消息到服务器
VOID SendServerMessage(int nIdent, int nSessionIdx, SOCKET nSocket, int nServerIdx, char *pBuffer, int nBufSize);
//发送数据到客户端
VOID PostUserServerData(PRUNGATEUSERSESSION pSession, const char *pBuffer, int nBufferSize, BOOL boWriteWsHdr=TRUE, BOOL boWriteProtoHdr=FALSE, TICKCOUNT nSendTime = 0);
//处理客户端发过来的数据
VOID ProcessUserRecvPacket(PRUNGATEUSERSESSION pSession, char *pBuffer, int nBufferSize);
//重载CustomWorkSocket的函数,处理服务器的数据数据,将调用ProcessServerPacket
virtual void ProcessRecvBuffers(const GATEMSGHDR* pHeader, LPCSTR pData, size_t nLen);
VOID DispathRecvMessage(const PGATEMSGHDR pMsgHdr, const char *pBuffer, SIZE_T nBufSize);
VOID OnConnected();
virtual VOID OnClosed();
VOID OnError(INT errorCode);
VOID OnDisconnected();
public:
CRunDataProcesser(const int nMaxSessionCount);
~CRunDataProcesser();
SIZE_T m_dwProcessRecvSize; //处理客户端接收数据大小
SIZE_T m_dwWaitSendUserSize; //待发送给用户的数据包大小
SIZE_T m_dwWaitSendQueueSize; //待发给用户的数据包队列大小
SIZE_T m_dwRecvSeverSize; //接收服务器数据大小
SIZE_T m_dwSendUserSize; //发送用户数据大小
TICKCOUNT m_dwLastProcUsrMsgTime; //上次处理用户数据时间
TICKCOUNT m_dwLastProcSrvMsgTime; //上次处理服务器数据时间
TICKCOUNT m_dwLastRecvSrvMsgTime; //上次接收服务器数据时间
TICKCOUNT m_dwProcSrvThreadSleep; //处理服务器数据线程休眠时间
SIZE_T m_dwSendQueueSize; //待发数据队列数据包大小
INT GetActiveUserCount();
inline LPCSTR GetName(){ return m_sGateName; }
VOID SetName(LPCSTR sName);
//VOID SetPipeName(LPCSTR sPipeName);
INT GetSendThreadCount();
VOID SetSendThreadCount(INT ThreadCount);
DATAPROCESSERTYPE GetDataProcessType();
VOID SetDataProcessType(DATAPROCESSERTYPE Type);
INT GetMaxSessionCount();
VOID SetRunSockProcesser(CRunSockProcesser* pSockProcesser);
CRunSockProcesser* GetRunSockProcesser() const { return m_pSockProcesser; }
PRUNDATASENDTHREAD GetSendThreadInfo(INT ThreadIdx);
PRUNGATEUSERSESSION GetFirstSession();
VOID SetPrintC2SMessage(const BOOL boPrint);
VOID SetPrintS2CMessage(const BOOL boPrint);
BOOL Startup();
VOID Stop();
PRUNGATEUSERSESSION NewSession(SOCKET nSocket, SOCKADDRIN RemoteAddr);
VOID AddRecvBuf(PRUNGATEUSERSESSION pSession, unsigned long long nVerify, char *pBuffer, int BufferSize);
static VOID ShowGateStatus(CRunDataProcesser *pRunData);
static int ChangeConsoleLine(int nLine, int nPos, LPCSTR sFormat, ...);
static unsigned int s_nSndThreadSleepTime; // 发送线程Sleep时间毫秒为单位
};
#endif

View File

@@ -0,0 +1,292 @@
#include "StdAfx.h"
#include "DataProcess.h"
#include "SockProcess.h"
#include "SelectSockProcess.h"
#include "IOCPSockProcess.h"
#include "GateServer.h"
#include "GateServerConfig.h"
const char szExceptionDumpFile[] = ".\\RunGate.dmp";
#ifdef _USRDLL
BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
static LPTOP_LEVEL_EXCEPTION_FILTER lpOldExceptonFilter;
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
lpOldExceptonFilter = SetUnhandledExceptionFilter( DefaultUnHandleExceptionFilter );
InitDefMsgOut();
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
case DLL_PROCESS_DETACH:
UninitDefMsgOut();
SetUnhandledExceptionFilter( lpOldExceptonFilter );
break;
}
return TRUE;
}
#endif
/*************************作为插件的导出函数*************************/
CRunSockProcesser* EXPORTCALL CreateRunGate(RUNSOCKTYPE SockType, int MaxSession)
{
CRunSockProcesser *pRunSock;
CRunDataProcesser *pRunData;
if ( SockType == rsSelect )
pRunSock = new CSelectRunSockProcesser();
#ifdef WIN32
else if ( SockType == rsIOCP )
pRunSock = new CIOCPRunSockProcesser();
#endif
else return NULL;
pRunData = new CRunDataProcesser( MaxSession );
pRunSock->SetDataProcesser( pRunData );
return pRunSock;
}
VOID EXPORTCALL FreeRunGate(CRunSockProcesser *pRunSock)
{
if ( pRunSock )
{
pRunSock->Stop();
pRunSock->GetDataProcesser()->Stop();
delete pRunSock->GetDataProcesser();
delete pRunSock;
}
}
VOID EXPORTCALL RunGateSetBindAddress(CRunSockProcesser *pRunSock, LPCSTR sBindAddress)
{
pRunSock->SetBindAddress( sBindAddress );
}
VOID EXPORTCALL RunGateSetBindPort(CRunSockProcesser *pRunSock, INT nBindPort)
{
pRunSock->SetBindPort( nBindPort );
}
INT EXPORTCALL RunGateGetIOWorkThreadCount(CRunSockProcesser *pRunSock)
{
#ifdef WIN32
if ( pRunSock->GetRunSockType() == rsIOCP )
return ((CIOCPRunSockProcesser*)pRunSock)->GetWorkThreadCount();
else
#endif
return -1;
}
BOOL EXPORTCALL RunGateSetIOWorkThreadCount(CRunSockProcesser *pRunSock, INT nThreadCount)
{
#ifdef WIN32
if (pRunSock->GetRunSockType() == rsIOCP)
{
((CIOCPRunSockProcesser*)pRunSock)->SetWorkThreadCount(nThreadCount);
return TRUE;
}
#endif
return FALSE;
}
BOOL EXPORTCALL RunGateStartup(CRunSockProcesser *pRunSock)
{
CRunDataProcesser *pRunData = pRunSock->GetDataProcesser();
if ( pRunData->Startup() )
{
if ( pRunSock->InitBase() )
{
if ( pRunSock->Start() )
return TRUE;
else pRunSock->UninitBase();
}
pRunData->Stop();
}
return FALSE;
}
VOID EXPORTCALL RunGateStop(CRunSockProcesser *pRunSock)
{
pRunSock->Stop();
pRunSock->UninitBase();
pRunSock->GetDataProcesser()->Stop();
}
INT EXPORTCALL RunGateGetActiveSessionCount(CRunSockProcesser *pRunSock)
{
return pRunSock->GetDataProcesser()->GetActiveUserCount();
}
VOID EXPORTCALL RunGateSetName(CRunSockProcesser *pRunSock, LPCSTR sName)
{
pRunSock->GetDataProcesser()->SetName( sName );
}
VOID EXPORTCALL RunGateSetServerIP(CRunSockProcesser *pRunSock, LPCSTR sServerName)
{
pRunSock->GetDataProcesser()->SetServerHost( sServerName );
}
VOID EXPORTCALL RunGateSetServerPort(CRunSockProcesser *pRunSock, int port)
{
pRunSock->GetDataProcesser()->SetServerPort( port );
}
INT EXPORTCALL RunGateGetSendThreadCount(CRunSockProcesser *pRunSock)
{
return pRunSock->GetDataProcesser()->GetSendThreadCount();
}
VOID EXPORTCALL RunGateSetSendThreadCount(CRunSockProcesser *pRunSock, INT nThreadCount)
{
pRunSock->GetDataProcesser()->SetSendThreadCount( nThreadCount );
}
DATAPROCESSERTYPE RunGateGetDataProcessType(CRunSockProcesser *pRunSock)
{
return pRunSock->GetDataProcesser()->GetDataProcessType();
}
VOID EXPORTCALL RunGateSetDataProcessType(CRunSockProcesser *pRunSock, DATAPROCESSERTYPE ProcessType)
{
pRunSock->GetDataProcesser()->SetDataProcessType( ProcessType );
}
VOID EXPORTCALL RunGateSetDataProcessPrintMsgPacket(CRunSockProcesser *pRunSock, BOOL boPrintC2S, BOOL boPrintS2C)
{
pRunSock->GetDataProcesser()->SetPrintC2SMessage(boPrintC2S);
pRunSock->GetDataProcesser()->SetPrintS2CMessage(boPrintS2C);
}
BOOL EXPORTCALL RunGateQuerySendThreadInfo(CRunSockProcesser *pRunSock, INT nThreadIdx, PRUNGATESENDTHREADQUERYSTRUCT pQueryStruct)
{
PRUNDATASENDTHREAD pSendThread;
pSendThread = pRunSock->GetDataProcesser()->GetSendThreadInfo( nThreadIdx );
if ( pSendThread )
{
pQueryStruct->hThread = pSendThread->hThread;
pQueryStruct->dwThreadId = pSendThread->dwThreadId;
pQueryStruct->dwProcTick = pSendThread->dwProcTick;
pQueryStruct->dwSleepTick = pSendThread->dwSleepTick;
return TRUE;
}
return FALSE;
}
INT EXPORTCALL RunGateEnumActiveSessions(CRunSockProcesser *pRunSock, RUNGATE_ENUMSESSION_ROUTINE lpCallBack)
{
int nCount = 0;
TICKCOUNT dwCurTick;
PRUNGATEUSERSESSION pSession, pLastSession;
RUNGATEQUERYSESSIONSTRUCT SessionInfo;
dwCurTick = _getTickCount();
pSession = pRunSock->GetDataProcesser()->GetFirstSession();
pLastSession = pSession + pRunSock->GetDataProcesser()->GetMaxSessionCount();
while ( pSession < pLastSession )
{
if ( pSession->nSocket != INVALID_SOCKET && !pSession->boMarkToClose && !pSession->boRemoteClosed )
{
SessionInfo.nSocket = pSession->nSocket;
SessionInfo.pSession = pSession;
SessionInfo.SockAddr = pSession->SockAddr;
SessionInfo.nRecvPacketCount = pSession->nRecvPacketCount;
SessionInfo.nSendPacketCount = pSession->nSendPacketCount;
SessionInfo.wPacketError= pSession->wPacketError;
SessionInfo.btPacketIdx = pSession->btPacketIdx;
SessionInfo.boSendAvaliable = pSession->boSendAvaliable;
SessionInfo.nVerifyIdx = pSession->nVerifyIdx;
SessionInfo.nRecvBufSize = pSession->RecvBuf.nOffset;
SessionInfo.nRecvCacheSize = pSession->RecvBuf.nSize;
SessionInfo.nSendBufSize = pSession->SendBuf.nOffset;
SessionInfo.nSendCacheSize = pSession->SendBuf.nSize;
SessionInfo.dwActiveTick = dwCurTick - pSession->dwConnectTick;
SessionInfo.dwClientMsgTick = dwCurTick - pSession->dwClientMsgTick;
SessionInfo.dwServerMsgTick = dwCurTick - pSession->dwServerMsgTick;
//memcpy( SessionInfo.sLoginAccount, pSession->sLoginAccount, __min(sizeof(SessionInfo.sLoginAccount), sizeof(pSession->sLoginAccount)) );
//memcpy( SessionInfo.sLoginCharName, pSession->sLoginCharName, __min(sizeof(SessionInfo.sLoginCharName), sizeof(pSession->sLoginCharName)) );
//SessionInfo.nSessionId = pSession->nSessionId;
if ( !lpCallBack( pRunSock, &SessionInfo ) )
break;
nCount++;
}
pSession++;
}
return nCount;
}
BOOL EXPORTCALL RunGateCloseSession(CRunSockProcesser *pRunSock, PRUNGATEUSERSESSION pSession)
{
PRUNGATEUSERSESSION pFirstSession;
if ( !pRunSock || !pSession )
return FALSE;
pFirstSession = pRunSock->GetDataProcesser()->GetFirstSession();
if ( pSession < pFirstSession )
return FALSE;
if ( pSession >= pFirstSession + pRunSock->GetDataProcesser()->GetMaxSessionCount() )
return FALSE;
if ( (((size_t)pSession) - ((size_t)pFirstSession)) % sizeof(*pSession) != 0 )
return FALSE;
if ( pSession->nSocket == INVALID_SOCKET || pSession->boMarkToClose || pSession->boRemoteClosed )
return FALSE;
pRunSock->GetDataProcesser()->SendCloseSession( pSession, TRUE, 9999 );
return TRUE;
}
VOID EXPORTCALL RunGateQueryDataStatics(CRunSockProcesser *pRunSock, PRUNDATASTATICS pQueryStruct)
{
CRunDataProcesser *pRunData = pRunSock->GetDataProcesser();
pQueryStruct->dwProcessRecvSize = pRunData->m_dwProcessRecvSize;
pQueryStruct->dwWaitSendUserSize = pRunData->m_dwWaitSendUserSize;
pQueryStruct->dwWaitSendQueueSize = pRunData->m_dwWaitSendQueueSize;
pQueryStruct->dwRecvSeverSize = pRunData->m_dwRecvSeverSize;
pQueryStruct->dwSendUserSize = pRunData->m_dwSendUserSize;
pQueryStruct->dwLastProcUsrMsgTime = pRunData->m_dwLastProcSrvMsgTime;
pQueryStruct->dwLastProcSrvMsgTime = pRunData->m_dwLastProcSrvMsgTime;
pQueryStruct->dwLastRecvSrvMsgTime = pRunData->m_dwLastRecvSrvMsgTime;
pQueryStruct->dwProcSrvThreadSleep = pRunData->m_dwProcSrvThreadSleep;
pQueryStruct->dwSendQueueSize = pRunData->m_dwSendQueueSize;
}
VOID EXPORTCALL RunGateResetDataStatics(CRunSockProcesser *pRunSock)
{
CRunDataProcesser *pRunData = pRunSock->GetDataProcesser();
InterlockedExchange( (LONG*)&pRunData->m_dwProcessRecvSize, 0 );
InterlockedExchange( (LONG*)&pRunData->m_dwRecvSeverSize, 0 );
InterlockedExchange( (LONG*)&pRunData->m_dwSendUserSize, 0 );
}
INT EXPORTCALL RunGateGetKernalVersion(LPVOID lpReseved)
{
return RUNGATE_KRN_VERSION;
}

View File

@@ -0,0 +1,27 @@
LIBRARY RunGate
EXPORTS
CreateRunGate
FreeRunGate
RunGateSetBindAddress
RunGateSetBindPort
RunGateGetIOWorkThreadCount
RunGateSetIOWorkThreadCount
RunGateStartup
RunGateStop
RunGateGetActiveSessionCount
RunGateSetName
RunGateGetSendThreadCount
RunGateSetSendThreadCount
RunGateGetDataProcessType
RunGateSetDataProcessType
RunGateSetDataProcessPrintMsgPacket
RunGateQuerySendThreadInfo
RunGateEnumActiveSessions
RunGateCloseSession
RunGateQueryDataStatics
RunGateResetDataStatics
SetOutputMsgFn
RunGateGetKernalVersion
RunGateSetServerIP
RunGateSetServerPort

View File

@@ -0,0 +1,66 @@
#ifndef _RUNGATE_H_
#define _RUNGATE_H_
#ifndef EXPORTCALL
#define EXPORTCALL __stdcall
#endif
/*作为插件导出函数中查询发送线程状态的结构*/
typedef struct tagRunGateSendThreadQueryStruct
{
#ifdef _MSC_VER
HANDLE hThread;
#else
pthread_t hThread;
#endif
DWORD dwThreadId;
TICKCOUNT dwProcTick;
TICKCOUNT dwSleepTick;
}RUNGATESENDTHREADQUERYSTRUCT, *PRUNGATESENDTHREADQUERYSTRUCT;
/*作为插件导出函数中枚举会话信息的结构*/
typedef struct tagRunGateQuerySessionStruct
{
SOCKET nSocket;
PRUNGATEUSERSESSION pSession;
SOCKADDRIN SockAddr;
int nRecvPacketCount;
int nSendPacketCount;
WORD wPacketError;
BYTE btPacketIdx;
bool boSendAvaliable;
unsigned long long nVerifyIdx;
int nRecvBufSize;
int nRecvCacheSize;
int nSendBufSize;
int nSendCacheSize;
TICKCOUNT dwActiveTick;
TICKCOUNT dwClientMsgTick;
TICKCOUNT dwServerMsgTick;
//CHAR sLoginAccount[32];
//CHAR sLoginCharName[32];
int nSessionId;
}RUNGATEQUERYSESSIONSTRUCT, *PRUNGATEQUERYSESSIONSTRUCT;
/*作为插件导出函数中枚举会话信息的回调函数类型*/
typedef INT (CALLBACK *RUNGATE_ENUMSESSION_ROUTINE) (LPVOID lpRunSockProcesser, PRUNGATEQUERYSESSIONSTRUCT pSessionInfo);
/*作为插件导出函数中查询数据统计信息的结构*/
typedef struct tagRunDataStatics
{
SIZE_T dwProcessRecvSize; //处理客户端接收数据大小
SIZE_T dwWaitSendUserSize; //待发送给用户的数据包大小
SIZE_T dwWaitSendQueueSize; //待发给用户的数据包队列大小
SIZE_T dwRecvSeverSize; //接收服务器数据大小
SIZE_T dwSendUserSize; //发送用户数据大小
TICKCOUNT dwLastProcUsrMsgTime; //上次处理用户数据时间
TICKCOUNT dwLastProcSrvMsgTime; //上次处理服务器数据时间
TICKCOUNT dwLastRecvSrvMsgTime; //上次接收服务器数据时间
TICKCOUNT dwProcSrvThreadSleep; //处理服务器数据线程休眠时间
SIZE_T dwSendQueueSize; //待发数据队列数据包大小
}RUNDATASTATICS, *PRUNDATASTATICS;
#endif

View File

@@ -0,0 +1,95 @@
#include "StdAfx.h"
#include "GateServerConfig.h"
void CGateServerConfig::showError(LPCTSTR sError)
{
m_sLastErrDesc = sError;
RefString s = _T("[Config Error]");
s += sError;
throw s;
}
bool CGateServerConfig::readConfig(CGateConfigList &configList, const char *pszFileName)
{
GATECONFIG config;
if ( !openGlobalTable(pszFileName) )
return false;
//遍历网关配置表,每个网关配置表均会产生一个网关对象
if ( enumTableFirst() )
{
do
{
//读取网关服务配置表
if ( !openFieldTable("LocalService") )
return false;
getFieldStringBuffer("ServerName", config.GateServer.sName, ArrayCount(config.GateServer.sName));
//设置标题
char buff[256];
strcpy(buff,"lcwl-");
strcat(buff,config.GateServer.sName);
strcat(buff,"-V");
in_addr ia;
ia.s_addr = RUNGATE_KRN_VERSION;
strcat(buff,inet_ntoa(ia));
SetConsoleTitle(buff );
getFieldStringBuffer("Address", config.GateServer.sAddress, ArrayCount(config.GateServer.sAddress));
config.GateServer.nPort = getFieldInt("Port");
config.GateServer.nMaxSession = getFieldInt("MaxSession");
config.GateServer.SendThreadCount = getFieldInt("SendThreadCount");
closeTable();
//读取后台服务器配置表
if ( !openFieldTable("BackServer") )
return false;
getFieldStringBuffer("Host", config.BackServer.sHost, ArrayCount(config.BackServer.sHost));
config.BackServer.nPort = getFieldInt("Port");
closeTable();
//将网关配置加到配置列表中
configList.add(config);
}
while (enumTableNext());
}
closeTable();
return true;
}
bool CGateServerConfig::loadConfig(CGateConfigList &configList, char *pszFileName)
{
char * szConfigFileName =pszFileName;
if(szConfigFileName ==NULL)
{
szConfigFileName= _T("GateServer.txt");
}
OutputMsg(rmTip,"load file from %s",szConfigFileName);
bool result = false;
CMemoryStream ms;
try
{
if ( ms.loadFromFile(szConfigFileName) <=0 )
{
showErrorFormat(_T("unable to load %s"), szConfigFileName );
return false;
}
if( !setScript((LPCSTR)ms.getMemory()) )
{
return false;
}
result = readConfig(configList,"GateServer");
}
catch(RefString &s)
{
OutputMsg(rmError, s.rawStr());
}
catch(...)
{
_tprintf(_T("unexpected error on load gate config"));
}
return result;
}

View File

@@ -0,0 +1,41 @@
#ifndef _GATE_SERVER_CONFIG_H_
#define _GATE_SERVER_CONFIG_H_
/*
* 配置文件的读写
*
*/
typedef struct tagGateConfig
{
struct
{
char sName[40]; //自身的名字
CHAR sAddress[40]; //网关服务绑定地址
int nPort; //端口
int nMaxSession; //网关中客户端连接池的最大连接数
int SendThreadCount;//数据发送线程池中工作线程数量
}GateServer; //网关服务配置
struct
{
CHAR sHost[120]; //连接服务器的地址,支持域名
int nPort; //连接服务器的端口
}BackServer; //后台服务器配置
}GATECONFIG, *PGATECONFIG;
typedef CBaseList<GATECONFIG> CGateConfigList;
//配置文件的解析类
class CGateServerConfig:
public CCustomLuaConfig
{
protected:
void showError(LPCTSTR sError);
bool readConfig(CGateConfigList &configList,const char *pszFileName);
public:
bool loadConfig(CGateConfigList &configList, char *pszFileName=NULL);
};
#endif

View File

@@ -0,0 +1,198 @@
#ifndef _RUNGATE_PROTO_
#define _RUNGATE_PROTO_
#ifndef STDCALL
#define STDCALL __stdcall
#endif
#ifndef SCSTR
#define SCSTR static const CHAR*
#endif
//网关核心版本
#define RUNGATE_KRN_VERSION MAKEFOURCC( 15, 5, 18, 1)
//用户接收包缓冲区默认大小
#define SESSION_RECV_BUFSIZE 4096
//用户发送包缓冲区默认大小
#define SESSION_SEND_BUFSIZE 8192
//每用户接收处理队列最长数据大小
#define SESSION_MAX_RECVPROC_SIZE 8192
//用户数据队列处理内存增长单位
#define SESSION_DATAGROW_SIZE 1024
//最大用户数据包序号错误数量
#define SESSION_PACKETERR_MAX 32
//处理服务器数据最大时间
#define RUNGATE_PROCESS_SERVERMSG_LIMIT 32 //32毫秒
//每次向用户发送数据包限制
#define RUNGATE_ONCESENDUSE_LIMIT 2048
//发送检查超时
#define RUNGATE_SENDCHECK_TIMEOUT 300
typedef GATEMSGHDR RUNGATEMSGHDR, *PRUNGATEMSGHDR;
//session的通信状态,具体见开发文档的定义
typedef enum tagSessionStatus
{
enSessionStatusIdle =0, //空闲状态
//enEncryReq =1, //请求服务器的密钥状态
//enEncryAck, //密钥确认阶段
enConn, //连接上
enCommunication, //正常的通信阶段
} SESSIONSTATUS;
typedef enum tagSessionCloseReason
{
enReasonAllSessionClose =1000, //所有的session都要关闭
enReasonIdle =1001, //长时间不活跃
enReasonSenderBuffLarge =1002, //发送缓存太长
enReasonSocketError =1003, //socket错误
enReasonSendSockerError=1004, //发送的时候socket错误
enReasonLargePackLeft =1005, //剩余过量的包
enReasonRecvLargerPack=1006, //所有的session都要关闭
enReasonGM =1007, //GMClose
enReasonKeyError =1011, //密钥错误
enSycDataLengthError= 1012, //salt data length error
} SESSIONCLOSEREASON;
typedef struct tagRunGateDataBuffer
{
char *lpBuffer;
int nSize;
int nOffset;
}RUNGATEDATABUF, *PRUNGATEDATBUF;
typedef struct sockaddr_in SOCKADDRIN, *PSOCKADDRIN;
typedef enum tagRunSockASyncAction
{
aaAccept = 1, //AcceptEx
aaRecv, //WSARecv
aaSend, //WSASend
}RUNSOCKASYNCACTION;
#ifdef WIN32
//会话异步接受数据
typedef struct tagRunSockOverlapped
{
OVERLAPPED Overlapped;
WSABUF WSABuf;
BYTE btAction; //行为类型
BYTE btReceved[3];
struct tagRunGateUserSession *pUser; //会话指针
}RUNSOCKOVERLAPPED, *PRUNSOCKOVERLAPPED;
#endif
#define OrderSwap16(A) (((uint16_t)(A) >> 8) | ((uint16_t)(A & 0xFF) << 8))
#define OrderSwap32(A) (OrderSwap16((uint32_t)(A) >> 16) | ((uint32_t)(OrderSwap16(A)) << 16))
#define OrderSwap64(A) (OrderSwap32((uint64_t)(A) >> 32) | ((uint64_t)(OrderSwap32(A)) << 32));
enum class emOpcode : uint8_t { //操作码定义类型
MID = 0x0, //标识一个中间数据包
TXT = 0x1, //标识一个text类型数据包
BIN = 0x2, //标识一个binary类型数据包
//0x3 - 7保留
CLR = 0x8, //标识一个断开连接类型数据包
PIN = 0x9, //标识一个ping类型数据包
PON = 0xA, //表示一个pong类型数据包
};
#pragma pack(push,1)
typedef struct tagWebSocketHead {
uint8_t fin : 1;//标识是否为此消息的最后一个数据包
uint8_t rsv1 : 1;//保留位1
uint8_t rsv2 : 1;//保留位2
uint8_t rsv3 : 1;//保留位3
emOpcode opcode : 4;//操作码
uint8_t mask : 1; //是否需要掩码
uint8_t len : 7;//长度
union {
uint16_t v16;//长度为126时
uint64_t v64;//长度为127时
} ex_len;
uint8_t mkey[4];
uint8_t rh : 1;//head读取完成
uint8_t rl : 1;//len读取完成
uint8_t rk : 1;//mkey读取完成
uint8_t rs : 5;//扩展保留
tagWebSocketHead(void) { reset(); }
void reset(void) { memset(this,0,sizeof(tagWebSocketHead)); }
inline uint64_t GetLen(void) {
if (len == 126) {
return ex_len.v16;
} else if (len == 127) {
return ex_len.v64;
}
return len;
}
inline uint8_t GetLenNeedByte(void) {
if (len == 126) {
return 2;
} else if (len == 127) {
return 8;
}
return 0;
}
} WEBSOCKETHEAD, *PWEBSOCKETHEAD;
#pragma pack(pop)
//用户会话数据
typedef struct tagRunGateUserSession
{
SOCKET nSocket;
int nIndex;
int nServerIdx;
SOCKADDRIN SockAddr;
int nRecvPacketCount;
int nSendPacketCount;
WORD wPacketError;
BYTE btPacketIdx;
bool boSendAvaliable;
bool boMarkToClose; //标记为关闭状态
bool boRemoteClosed; //远程方是否关闭,如超时或者主动关闭了客户端
BYTE btRcv2[2];
TICKCOUNT dwConnectTick;
TICKCOUNT dwCloseTick;
TICKCOUNT dwSendTimeOut;
TICKCOUNT dwClientMsgTick;
TICKCOUNT dwServerMsgTick;
unsigned long long nVerifyIdx; //通信的时候消息验证码
WEBSOCKETHEAD webSocketHead; // WebSocket封装
bool webSocketShakeHand; // WebSocket握手标志
unsigned short nKey; // 服务端KEY
RUNGATEDATABUF RecvBuf;
//CRITICAL_SECTION SendBufLock;
RUNGATEDATABUF SendBuf;
#ifdef WIN32
RUNSOCKOVERLAPPED Overlapped;
#endif
CHAR sLoginAccount[jxSrvDef::ACCOUNT_NAME_BUFF_LENGTH];
CHAR sLoginCharName[jxSrvDef::ACTOR_NAME_BUFF_LENGTH];
//int nSessionId;//登录会话ID
char sRecvBuf[SESSION_RECV_BUFSIZE+1];//数据接收缓冲区
BYTE btRcv3[3];
short nSessionSatus; // tagSessionStatus里定义
Encrypt encryptHander; // 加密器
int nTimeStampOffset; // 当前发送队列中已经处理过时间戳的偏移量
unsigned long long ullSvrTimeDiff; // 服务器时间和本地时间差
TICKCOUNT nLastSendPacketTime; // 上一次发包间隔
}RUNGATEUSERSESSION, *PRUNGATEUSERSESSION;
#define INIT_SESSION_SEND(s) //InitializeCriticalSection( &(s)->SendBufLock )
#define UNINIT_SESSION_SEND(s) //DeleteCriticalSection( &(s)->SendBufLock )
#define LOCK_SESSION_SEND(s) //EnterCriticalSection( &(s)->SendBufLock )
#define TRYLOCK_SESSION_SEND(s) TRUE//TryEnterCriticalSection( &(s)->SendBufLock )
#define UNLOCK_SESSION_SEND(s) //LeaveCriticalSection( &(s)->SendBufLock )
#endif

View File

@@ -0,0 +1,356 @@
#include "StdAfx.h"
#include "DataProcess.h"
#include "SockProcess.h"
#include "IOCPSockProcess.h"
#ifdef WIN32
VOID CIOCPRunSockProcesser::ComplationPortWorkThreadRoutine(CIOCPRunSockProcesser *pRunSock)
{
HANDLE hIOPort;
DWORD dwBytesTransfered;
ULONG_PTR uComplationKey;
PRUNSOCKOVERLAPPED lpOverlapped;
PRUNGATEUSERSESSION pSession;
int nErr;
hIOPort = pRunSock->m_hIOPort;
while ( !pRunSock->m_boStoping )
{
dwBytesTransfered = 0;
uComplationKey = 0;
lpOverlapped = NULL;
if ( GetQueuedCompletionStatus( hIOPort, &dwBytesTransfered, &uComplationKey, (LPOVERLAPPED*)&lpOverlapped, 10000 ) )
{
if ( !lpOverlapped )
continue;
//AcceptEx
if ( lpOverlapped->btAction == aaAccept )
{
pRunSock->NewSession();
continue;
}
pSession = lpOverlapped->pUser;
//套接字已关闭
if ( !dwBytesTransfered )
{
pSession->boRemoteClosed = true;
pRunSock->m_pDataProcesser->PostCloseSession( pSession );
continue;
}
//WSARecv
if ( lpOverlapped->btAction == aaRecv )
{
pSession->Overlapped.WSABuf.buf[dwBytesTransfered] = 0;
pRunSock->m_pDataProcesser->AddRecvBuf( pSession, uComplationKey, lpOverlapped->WSABuf.buf, dwBytesTransfered );
if ( pSession->nSocket != INVALID_SOCKET && !pSession->boMarkToClose && !pSession->boRemoteClosed )
{
pRunSock->PostRecv( pSession );
}
continue;
}
//WSASend
if ( lpOverlapped->btAction == aaSend )
{
continue;
}
}
else
{
nErr = GetLastError();
if ( nErr == WAIT_TIMEOUT )
continue;
//socket closed
if ( lpOverlapped )
{
pSession = lpOverlapped->pUser;
pSession->boRemoteClosed = true;
pRunSock->m_pDataProcesser->PostCloseSession( pSession );
continue;
}
pRunSock->GotError( __FUNCTION__, "GetQueuedCompletionStatus", nErr );
}
}
ExitThread( 0 );
}
CIOCPRunSockProcesser::CIOCPRunSockProcesser():CRunSockProcesser()
{
m_RunSockType = rsIOCP;
m_hIOPort = NULL;
m_nWorkThreadCount = 1;
ZeroMemory( m_hIOWorkThreads, sizeof(m_hIOWorkThreads) );
m_NewSocket = INVALID_SOCKET;
}
CIOCPRunSockProcesser::~CIOCPRunSockProcesser()
{
Stop();
}
BOOL CIOCPRunSockProcesser::InitComplationPort()
{
if ( !m_hIOPort )
{
m_hIOPort = CreateIoCompletionPort( INVALID_HANDLE_VALUE, NULL, 0, 0 );
if ( !m_hIOPort )
{
GotError( __FUNCTION__, "CreateIoCompletionPort", GetLastError() );
return FALSE;
}
}
return TRUE;
}
VOID CIOCPRunSockProcesser::UninitComplationPort()
{
if ( m_hIOPort )
{
CancelIo( m_hIOPort );
CloseHandle( m_hIOPort );
m_hIOPort = NULL;
}
}
BOOL CIOCPRunSockProcesser::InitAcceptSocket()
{
if ( !INHERITED::InitAcceptSocket() )
return FALSE;
HANDLE hPort = CreateIoCompletionPort( (HANDLE)m_ListenSocket, m_hIOPort, (ULONG_PTR)m_ListenSocket, 0 );
if ( !hPort || hPort != m_hIOPort )
{
GotError( __FUNCTION__, "CreateIoCompletionPort", WSAGetLastError() );
return FALSE;
}
return TRUE;
}
BOOL CIOCPRunSockProcesser::StartIOCPThreads()
{
int i, nThreadCount;
nThreadCount = __max( 1, m_nWorkThreadCount );
for ( i=0; i<nThreadCount; ++i )
{
if ( !m_hIOWorkThreads[i] )
{
m_hIOWorkThreads[i] = CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE)ComplationPortWorkThreadRoutine, this, 0, NULL );
if ( !m_hIOWorkThreads[i] )
{
GotError( __FUNCTION__, "CreateThread", GetLastError() );
return FALSE;
}
}
}
return TRUE;
}
VOID CIOCPRunSockProcesser::StopIOCPThreads()
{
int i;
for ( i=0; i<MAX_ASYNCIO_THREAD; ++i )
{
if ( m_hIOWorkThreads[i] )
{
do
{
PostQueuedCompletionStatus( m_hIOPort, 0, NULL, NULL );
}
while ( WaitForSingleObject( m_hIOWorkThreads[i], 100 ) == WAIT_TIMEOUT );
CloseHandle( m_hIOWorkThreads[i] );
m_hIOWorkThreads[i] = NULL;
}
}
}
VOID CIOCPRunSockProcesser::NewSession()
{
SOCKET nSocket;
PSOCKADDRIN pLocalAddr, pRemoteAddr;
int localSize, remoteSize, nErr;
PRUNGATEUSERSESSION pSession;
u_long uBlock;
nSocket = m_NewSocket;
m_NewSocket = INVALID_SOCKET;
//继续接受新的连接
PostAccept();
//更新接受的套接字的信息
nErr = setsockopt( nSocket, SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT, (char*)&m_ListenSocket, sizeof(m_ListenSocket) );
if ( nErr == SOCKET_ERROR )
{
closesocket( nSocket );
GotError( __FUNCTION__, "setsockopt", WSAGetLastError() );
return;
}
//获取接受的套接字对端地址
GetAcceptExSockaddrs( &m_ASyncAcceptAddr, 0, sizeof(m_ASyncAcceptAddr[0]) * 2, sizeof(m_ASyncAcceptAddr[0]) * 2,
(sockaddr**)&pLocalAddr, &localSize, (sockaddr**)&pRemoteAddr, &remoteSize );
//更新地址信息
nErr = getpeername( nSocket, (sockaddr*)pRemoteAddr, &remoteSize );
if ( nErr == SOCKET_ERROR )
{
closesocket( nSocket );
GotError( __FUNCTION__, "getpeername", WSAGetLastError() );
return;
}
//将套接字设置为非阻塞
uBlock = 1;
nErr = ioctlsocket( nSocket, FIONBIO, &uBlock );
if ( SOCKET_ERROR == nErr )
{
closesocket( nSocket );
GotError( __FUNCTION__, "ioctlsocket", WSAGetLastError() );
return;
}
//申请用户会话指针
if ( !(pSession = m_pDataProcesser->NewSession( nSocket, *pRemoteAddr )) )
{
closesocket( nSocket );
GotError( __FUNCTION__, "用户队列已经满了。", ERROR_SUCCESS );
return;
}
if ( m_hIOPort != CreateIoCompletionPort( (HANDLE)nSocket, m_hIOPort, (ULONG_PTR)pSession->nVerifyIdx, 0 ) )
{
GotError( __FUNCTION__, "CreateIoCompletionPort", GetLastError() );
closesocket( nSocket );
return;
}
//AdjustSocketSendBufSize( nSocket, 32 * 1024 );
if ( !PostRecv( pSession ) )
{
closesocket( nSocket );
return;
}
}
BOOL CIOCPRunSockProcesser::PostAccept()
{
int nErr;
//建立套接字作为新接受的连接使用
m_NewSocket = socket( AF_INET, SOCK_STREAM, IPPROTO_IP );
if ( m_NewSocket == INVALID_SOCKET )
{
GotError( __FUNCTION__, "socket", WSAGetLastError() );
return FALSE;
}
ZeroMemory( &m_ASyncAcceptOverlapped, sizeof(m_ASyncAcceptOverlapped) );
m_ASyncAcceptOverlapped.btAction = aaAccept;
//异步的Accept
nErr = AcceptEx( m_ListenSocket, m_NewSocket, &m_ASyncAcceptAddr, 0, sizeof(m_ASyncAcceptAddr[0]) * 2,
sizeof(m_ASyncAcceptAddr[0]) * 2, NULL, &m_ASyncAcceptOverlapped.Overlapped );
if ( nErr == SOCKET_ERROR )
{
GotError( __FUNCTION__, "AcceptEx", WSAGetLastError() );
return FALSE;
}
return TRUE;
}
BOOL CIOCPRunSockProcesser::PostRecv(PRUNGATEUSERSESSION pSession)
{
int nErr;
DWORD dwBytesRecved, dwFlags;
while ( TRUE )
{
dwBytesRecved = dwFlags = 0;
pSession->Overlapped.btAction = aaRecv;
ZeroMemory( &pSession->Overlapped.Overlapped, sizeof(pSession->Overlapped.Overlapped) );
pSession->Overlapped.WSABuf.buf = pSession->sRecvBuf;
pSession->Overlapped.WSABuf.len = sizeof(pSession->sRecvBuf) - 1;
nErr = WSARecv( pSession->nSocket, &pSession->Overlapped.WSABuf, 1, &dwBytesRecved, &dwFlags, &pSession->Overlapped.Overlapped, NULL );
if ( !nErr )
{
//连接已断开
if ( !dwBytesRecved )
{
pSession->boRemoteClosed = true;
m_pDataProcesser->PostCloseSession( pSession );
return FALSE;
}
else
{
pSession->Overlapped.WSABuf.buf[dwBytesRecved] = 0;
m_pDataProcesser->AddRecvBuf( pSession, pSession->nVerifyIdx, pSession->Overlapped.WSABuf.buf, dwBytesRecved );
if ( pSession->nSocket == INVALID_SOCKET || pSession->boMarkToClose || pSession->boRemoteClosed )
{
return FALSE;
}
}
}
else
{
nErr = WSAGetLastError();
if ( nErr != WSA_IO_PENDING )
{
m_pDataProcesser->PostCloseSession( pSession );
GotError( __FUNCTION__, "WSARecv", nErr );
return FALSE;
}
break;
}
}
return TRUE;
}
INT CIOCPRunSockProcesser::GetWorkThreadCount()
{
return __max( 1, m_nWorkThreadCount );
}
VOID CIOCPRunSockProcesser::SetWorkThreadCount(INT ThreadCount)
{
if ( m_boStoping && ThreadCount > 0 && ThreadCount < MAX_ASYNCIO_THREAD )
{
m_nWorkThreadCount = ThreadCount;
}
}
BOOL CIOCPRunSockProcesser::Start()
{
if ( !INHERITED::Start() )
return FALSE;
return InitComplationPort() && StartIOCPThreads() && InitAcceptSocket() && PostAccept();
}
VOID CIOCPRunSockProcesser::Stop()
{
INHERITED::Stop();
StopIOCPThreads();
UninitComplationPort();
UninitAcceptSocket();
}
#endif

View File

@@ -0,0 +1,43 @@
#ifndef _IOCP_SOCK_PROCESS_H_
#define _IOCP_SOCK_PROCESS_H_
//最大IO异步处理线程数量
#define MAX_ASYNCIO_THREAD 32
#ifdef WIN32
/* iocp 模型的RunSock */
class CIOCPRunSockProcesser : public CRunSockProcesser
{
typedef CRunSockProcesser INHERITED;
private:
HANDLE m_hIOPort; //完成端口句柄
INT m_nWorkThreadCount; //工作线程数量,仅在Socket处理方式为IOCP时有效
HANDLE m_hIOWorkThreads[MAX_ASYNCIO_THREAD];
SOCKADDRIN m_ASyncAcceptAddr[4];
RUNSOCKOVERLAPPED m_ASyncAcceptOverlapped;
SOCKET m_NewSocket; //用于AcceptEx的接受连接套接字
static VOID ComplationPortWorkThreadRoutine(CIOCPRunSockProcesser *pRunSock);
BOOL InitComplationPort();
VOID UninitComplationPort();
BOOL InitAcceptSocket();
BOOL StartIOCPThreads();
VOID StopIOCPThreads();
VOID NewSession();
BOOL PostAccept();
BOOL PostRecv(PRUNGATEUSERSESSION pSession);
public:
CIOCPRunSockProcesser();
~CIOCPRunSockProcesser();
INT GetWorkThreadCount();
VOID SetWorkThreadCount(INT ThreadCount);
BOOL Start();
VOID Stop();
};
#endif
#endif

View File

@@ -0,0 +1,189 @@
#include "StdAfx.h"
#include "DataProcess.h"
#include "SockProcess.h"
#include "SelectSockProcess.h"
#ifdef _MSC_VER
VOID CSelectRunSockProcesser::SelectThreadRoutine(void * arg)
#else
void * CSelectRunSockProcesser::SelectThreadRoutine(void * arg)
#endif
{
CSelectRunSockProcesser *pRunSock = (CSelectRunSockProcesser*)arg;
PRUNGATEUSERSESSION pFirstSession, pLastSession, pSession;
int nLoop = 0;
pSession = pFirstSession = pRunSock->m_pDataProcesser->GetFirstSession();
pLastSession = pFirstSession + pRunSock->m_pDataProcesser->GetMaxSessionCount();
while ( !pRunSock->m_boStoping )
{
pSession += pRunSock->SelectSessions( pSession, (int)(pLastSession - pSession) );
if ( pSession >= pLastSession )
pSession = pFirstSession;
nLoop++;
if ( nLoop > 32 )
{
Sleep( 1 );
nLoop = 0;
}
}
ExitThread( 0 );
}
#ifdef _MSC_VER
VOID CSelectRunSockProcesser::AcceptThreadRoutine(void *arg)
#else
void * CSelectRunSockProcesser::AcceptThreadRoutine(void * arg)
#endif
{
CSelectRunSockProcesser *pRunSock = (CSelectRunSockProcesser*)arg;
while ( !pRunSock->m_boStoping )
{
pRunSock->NewSession();
}
ExitThread( 0 );
}
CSelectRunSockProcesser::CSelectRunSockProcesser():CRunSockProcesser()
{
m_RunSockType = rsSelect;
m_hSelectThread = NULL;
m_hAcceptThread = NULL;
}
CSelectRunSockProcesser::~CSelectRunSockProcesser()
{
Stop();
}
INT CSelectRunSockProcesser::SelectSessions(PRUNGATEUSERSESSION pSession, INT nMax)
{
PRUNGATEUSERSESSION pSessions[FD_SETSIZE];
fd_set readfds, errfds;
timeval tv;
int nErr, nFdSSCount, nResult;
SOCKET nSocketMax = 0;
FD_ZERO( &readfds );
FD_ZERO( &errfds );
tv.tv_sec = 0;
tv.tv_usec = 200000;
nFdSSCount = 0;
nResult = 0;
if ( nMax > FD_SETSIZE )
nMax = FD_SETSIZE;
while ( nResult < nMax )
{
if ( pSession->webSocketShakeHand && pSession->nSocket != INVALID_SOCKET && !pSession->boMarkToClose && !pSession->boRemoteClosed )
{
FD_SET( pSession->nSocket, &readfds );
pSessions[nFdSSCount] = pSession;
nFdSSCount++;
if(pSession->nSocket > nSocketMax) nSocketMax = pSession->nSocket;
}
pSession++;
nResult++;
}
++nSocketMax;
if ( nFdSSCount > 0 )
{
#ifdef WIN32
nErr = select(0, &readfds, NULL, &errfds, &tv );
#else
nErr = select(nSocketMax, &readfds, NULL, &errfds, &tv );
#endif
if ( nErr > 0 )
{
while ( nFdSSCount > 0 )
{
nFdSSCount--;
pSession = pSessions[nFdSSCount];
if ( FD_ISSET( pSession->nSocket, &errfds ) )
{
pSession->boRemoteClosed = true;
m_pDataProcesser->SendCloseSession( pSession, TRUE, 2001 );
}
else if ( FD_ISSET( pSession->nSocket, &readfds ) )
{
nErr = recv( pSession->nSocket, pSession->sRecvBuf, sizeof(pSession->sRecvBuf)-1, 0 );
if ( nErr > 0 )
{
pSession->sRecvBuf[nErr] = 0;
m_pDataProcesser->AddRecvBuf( pSession, pSession->nVerifyIdx, pSession->sRecvBuf, nErr );
}
else if (nErr == SOCKET_ERROR)
{
pSession->boRemoteClosed = true;
m_pDataProcesser->SendCloseSession( pSession, TRUE, 2002 );
}
}
}
}
else if ( nErr == SOCKET_ERROR )
{
GotError( __FUNCTION__, "select", WSAGetLastError() );
}
}
return nResult;
}
BOOL CSelectRunSockProcesser::StartSelectThreads()
{
#ifdef _MSC_VER
m_hSelectThread = CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE)SelectThreadRoutine, this, 0, NULL );
#else
pthread_create(&m_hSelectThread, NULL, SelectThreadRoutine, this);
#endif
if ( !m_hSelectThread )
{
GotError( __FUNCTION__, "CreateThread", GetLastError() );
return FALSE;
}
#ifdef _MSC_VER
m_hAcceptThread = CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE)AcceptThreadRoutine, this, 0, NULL );
#else
pthread_create(&m_hAcceptThread, NULL, AcceptThreadRoutine, this);
#endif
if ( !m_hAcceptThread )
{
GotError( __FUNCTION__, "CreateThread", GetLastError() );
return FALSE;
}
return TRUE;
}
VOID CSelectRunSockProcesser::StopSelectThreads()
{
CloseThread( m_hAcceptThread );
CloseThread( m_hSelectThread );
}
BOOL CSelectRunSockProcesser::Start()
{
if ( !INHERITED::Start() )
return FALSE;
return InitAcceptSocket() && StartSelectThreads();
}
VOID CSelectRunSockProcesser::Stop()
{
INHERITED::Stop();
UninitAcceptSocket();
StopSelectThreads();
}

View File

@@ -0,0 +1,38 @@
#ifndef _SELECT_SOCK_PROCESS_H_
#define _SELECT_SOCK_PROCESS_H_
/* select 模型的RunSock */
class CSelectRunSockProcesser : public CRunSockProcesser
{
typedef CRunSockProcesser INHERITED;
private:
#ifdef _MSC_VER
HANDLE m_hSelectThread;
HANDLE m_hAcceptThread;
#else
pthread_t m_hSelectThread;
pthread_t m_hAcceptThread;
#endif
#ifdef _MSC_VER
static VOID SelectThreadRoutine(void *pRunSock);
static VOID AcceptThreadRoutine(void *pRunSock);
#else
static void* SelectThreadRoutine(void *pRunSock);
static void* AcceptThreadRoutine(void *pRunSock);
#endif
INT SelectSessions(PRUNGATEUSERSESSION pSession, INT nMax);
BOOL StartSelectThreads();
VOID StopSelectThreads();
public:
CSelectRunSockProcesser();
~CSelectRunSockProcesser();
BOOL Start();
VOID Stop();
};
#endif

View File

@@ -0,0 +1,233 @@
#include "StdAfx.h"
#include "DataProcess.h"
#include "SockProcess.h"
CRunSockProcesser::CRunSockProcesser()
{
m_RunSockType = rsUndefined;
m_boStoping = TRUE;
m_ListenSocket = INVALID_SOCKET;
m_BindAddr.sin_family = AF_INET;
m_BindAddr.sin_addr.s_addr = 0;
m_BindAddr.sin_port = 0;
m_pDataProcesser = NULL;
m_SessionFullTick = 0;
}
CRunSockProcesser::~CRunSockProcesser()
{
Stop();
}
VOID CRunSockProcesser::GotError(LPCSTR sErrorFn, LPCSTR sErrAPI, const INT ErrorCode)
{
OutputMsg( rmError, "CRunSockProcesse::%s Got Error %d on api \"%s\"", sErrorFn, ErrorCode, sErrAPI );
}
BOOL CRunSockProcesser::InitAcceptSocket()
{
m_ListenSocket = socket( AF_INET, SOCK_STREAM, IPPROTO_IP );
if ( m_ListenSocket == INVALID_SOCKET )
{
GotError( __FUNCTION__, "socket", WSAGetLastError() );
return FALSE;
}
#ifdef _MSC_VER
char optval = 1;
#else
int optval = 1;
#endif
if (setsockopt(m_ListenSocket, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)) == SOCKET_ERROR) {
GotError( __FUNCTION__, "setsockopt", WSAGetLastError() );
//assert(false);
return false;
}
if ( SOCKET_ERROR == bind( m_ListenSocket, (struct sockaddr*)&m_BindAddr, sizeof(m_BindAddr) ) )
{
GotError( __FUNCTION__, "socket", WSAGetLastError() );
return FALSE;
}
if ( SOCKET_ERROR == listen( m_ListenSocket, 5 ) )
{
GotError( __FUNCTION__, "listen", WSAGetLastError() );
return FALSE;
}
return TRUE;
}
VOID CRunSockProcesser::UninitAcceptSocket()
{
if ( m_ListenSocket != INVALID_SOCKET )
{
GotError( __FUNCTION__, "close " , WSAGetLastError());
closesocket( m_ListenSocket );
m_ListenSocket = INVALID_SOCKET;
}
}
VOID CRunSockProcesser::NewSession()
{
SOCKET nSocket;
SOCKADDRIN sRemote;
socklen_t nRemoteSize, nErr;
u_long uBlock;
PRUNGATEUSERSESSION pSession;
nRemoteSize = sizeof(sRemote);
//监听
nSocket = accept( m_ListenSocket, (sockaddr*)&sRemote, &nRemoteSize );
if ( nSocket == INVALID_SOCKET )
{
GotError( __FUNCTION__, "accept", WSAGetLastError() );
return;
}
//用户队列满后一段时间内不接受新连接
if ( _getTickCount() < m_SessionFullTick )
{
closesocket( nSocket );
GotError( __FUNCTION__, " _getTickCount() < m_SessionFullTick", WSAGetLastError() );
return;
}
//建立一个session,如果session队列满了,记录时间,在10秒内不能接受新的连接
if ( !(pSession = m_pDataProcesser->NewSession( nSocket, sRemote )) )
{
closesocket( nSocket );
GotError( __FUNCTION__, "用户队列已经满了。", ERROR_SUCCESS );
m_SessionFullTick = _getTickCount() + 10 * 1000;
return;
}
//设置新的socket连接为允许非阻塞模式
uBlock = 1;
nErr = ioctlsocket( nSocket, FIONBIO, &uBlock );
if ( SOCKET_ERROR == nErr )
{
closesocket( nSocket );
GotError( __FUNCTION__, "ioctlsocket", WSAGetLastError() );
return;
}
int bnodelay = 1;
nErr = ::setsockopt(nSocket, IPPROTO_TCP, TCP_NODELAY, (const char *)&bnodelay, sizeof(bnodelay));
if (SOCKET_ERROR == nErr)
{
GotError( __FUNCTION__, "setsockopt", WSAGetLastError() );
return;
}
/*AdjustSocketSendBufSize( nSocket, 32 * 1024 );*/
}
BOOL CRunSockProcesser::AdjustSocketSendBufSize(SOCKET s, INT nSize)
{
int nOldSize, nErr;
socklen_t nSizeLen;
nSizeLen = sizeof(nOldSize);
nErr = getsockopt( s, SOL_SOCKET, SO_SNDBUF, (char*)&nOldSize, &nSizeLen );
if ( nErr != SOCKET_ERROR )
{
if ( nOldSize < nSize )
{
nOldSize = nSize;
if ( setsockopt( s, SOL_SOCKET, SO_SNDBUF, (char*)&nOldSize, nSizeLen ) == SOCKET_ERROR )
{
GotError( __FUNCTION__, "getsockopt", WSAGetLastError() );
return FALSE;
}
}
}
else
{
GotError( __FUNCTION__, "getsockopt", WSAGetLastError() );
return FALSE;
}
return TRUE;
}
VOID CRunSockProcesser::SetBindAddress(LPCSTR sAddress)
{
m_BindAddr.sin_addr.s_addr = inet_addr(sAddress);
}
VOID CRunSockProcesser::SetBindPort(INT nPort)
{
m_BindAddr.sin_port = htons(nPort);
}
LPCSTR CRunSockProcesser::GetBindAddress()
{
return inet_ntoa(m_BindAddr.sin_addr);
}
INT CRunSockProcesser::GetBindPort()
{
return htons(m_BindAddr.sin_port);
}
RUNSOCKTYPE CRunSockProcesser::GetRunSockType()
{
return m_RunSockType;
}
CRunDataProcesser* CRunSockProcesser::GetDataProcesser()
{
return m_pDataProcesser;
}
CRunDataProcesser* CRunSockProcesser::SetDataProcesser(CRunDataProcesser *pDataProcesser)
{
CRunDataProcesser *pOldProcess = m_pDataProcesser;
m_pDataProcesser = pDataProcesser;
return pOldProcess;
}
BOOL CRunSockProcesser::InitBase()
{
#ifdef _MSC_VER
WSADATA WSAData;
int nErr;
nErr = WSAStartup( MAKEWORD(2, 2), &WSAData );
if ( nErr )
{
GotError( __FUNCTION__, "WSAStartup", nErr );
return FALSE;
}
timeBeginPeriod( 1 );
#endif
return TRUE;
}
VOID CRunSockProcesser::UninitBase()
{
#ifdef _MSC_VER
timeEndPeriod( 1 );
WSACleanup();
#endif
}
BOOL CRunSockProcesser::Start()
{
m_boStoping = FALSE;
m_SessionFullTick = 0;
return TRUE;
}
VOID CRunSockProcesser::Stop()
{
m_boStoping = TRUE;
}

View File

@@ -0,0 +1,48 @@
#ifndef _SOCKPROCESS_H_
#define _SOCKPROCESS_H_
typedef enum tagRunSockType
{
rsUndefined = 0,
rsSelect, //select 模型
rsIOCP, //IOCP 模型
}RUNSOCKTYPE;
class CRunDataProcesser;
class CRunSockProcesser
{
protected:
RUNSOCKTYPE m_RunSockType;
BOOL m_boStoping;
SOCKET m_ListenSocket; //监听连接的套接字句柄
SOCKADDRIN m_BindAddr; //服务监听绑定地址
CRunDataProcesser *m_pDataProcesser;
TICKCOUNT m_SessionFullTick;
VOID GotError(LPCSTR sErrorFn, LPCSTR sErrAPI, const INT ErrorCode);
virtual BOOL InitAcceptSocket();
virtual VOID UninitAcceptSocket();
virtual VOID NewSession();
BOOL AdjustSocketSendBufSize(SOCKET s, INT nSize);
public:
CRunSockProcesser();
virtual ~CRunSockProcesser();
VOID SetBindAddress(LPCSTR sAddress);
VOID SetBindPort(INT nPort);
LPCSTR GetBindAddress();
INT GetBindPort();
RUNSOCKTYPE GetRunSockType();
CRunDataProcesser* GetDataProcesser();
CRunDataProcesser* SetDataProcesser(CRunDataProcesser *pDataProcesser);
BOOL InitBase();
VOID UninitBase();
virtual BOOL Start();
virtual VOID Stop();
};
#endif

View File

@@ -0,0 +1,2 @@
//预编译头
#include "StdAfx.h"

View File

@@ -0,0 +1,85 @@
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <stdarg.h>
#ifndef _USE_TRY_CATCH
#define _USE_TRY_CATCH   
#endif
#ifdef WIN32
#include <crtdbg.h>
#include <tchar.h>
#include <Windows.h>
#include <WinSock2.h>
#include <MSWSock.h>
#endif
#include <_ast.h>
#include <_memchk.h>
#include <Tick.h>
#include <Lock.h>
#include <Thread.h>
#include <QueueList.h>
#include "ServerDef.h"
#include "GateProto.h"
#include "CommonDef.h"
#include "ShareUtil.h"
#include "BufferAllocator.h"
#include "AppItnMsg.h"
#include <time.h>
#include <Stream.h>
#include "TimeStat.h"
#include "sha1.h"
#include "base64.h"
#include <CustomSocket.h>
#include "DataPacket.hpp"
#include "SendPackPool.h"
#include "CustomWorkSocket.h"
#include "CustomClientSocket.h"
#include "CustomServerClientSocket.h"
#include "CustomServerSocket.h"
#include "wrand.h"
#include "StackWalker.h"
#include "DefExceptHander.h"
#include "CustomExceptHander.h"
#include "crc.h"
#include "Encrypt.h"
//#include "NetworkDataHandler.h"
#include "GateServerProto.h"
#include "CustomGateClient.h"
//这些是Lua读写配置需要添加的函数
extern "C"
{
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>
}
#include <Stream.h>
#include <wyString.h>
#include <RefClass.hpp>
#include <RefString.hpp>
#include "CustomLuaMyLoad.h"
#include "CustomLuaScript.h"
#include "CustomLuaConfig.h"
#include "LuaToBP.h"
//using namespace wylib;
using namespace wylib::stream;
using namespace jxSrvDef;

View File

@@ -0,0 +1,14 @@
#! /bin/bash
if [ -n "$1" ]; then
BuiltType=$1
else
BuiltType=Release
fi
rm -rf CMakeCache.txt cmake_install.cmake CMakeFiles/
cmake -DCMAKE_BUILD_TYPE=${BuiltType} ./
make -j4
rm -rf CMakeCache.txt CMakeFiles/

304
server/GateServer/main.cpp Normal file
View File

@@ -0,0 +1,304 @@
#include "StdAfx.h"
#include "WinService.h"
#include "DataProcess.h"
#include "SockProcess.h"
#include "SelectSockProcess.h"
#include "IOCPSockProcess.h"
#include "GateServer.h"
#include "GateServerConfig.h"
#include "FileLogger.h"
#include <string.h>
#ifndef WIN32
// #include "client/linux/handler/exception_handler.h"
#endif
#ifndef WIN32
DWORD GetTickCount()
{
struct timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
return (ts.tv_sec*1000 + ts.tv_nsec/1000000);
}
#endif
bool GateEngineRunning = true;
static void signal_handler(int sig_num)
{
if( sig_num == SIGHUP ||
sig_num == SIGINT ||
sig_num == SIGTERM )
{
GateEngineRunning = false;
OutputMsg( rmTip, _T("[SIGNAL] signal(%d) signal_handler... "), sig_num);
}
else
{
OutputMsg( rmError, _T("[SIGNAL] signal(%d) signal_handler... "), sig_num);
}
}
void ServerMain(int argc, char** argv);
VOID ServiceMain(int argc, char** argv);
bool CreateAndStartGateServers(CBaseList<CRunSockProcesser*> &gateList,char *pFileName=NULL);
void DestroyGateServers(CBaseList<CRunSockProcesser*> &gateList);
//服务器是否在运行
bool g_ServerIsRunning =true;
void TestMemory()
{
DWORD dwStart = GetTickCount();
for(int i = 0; i < 1000000; i++) { char *p = (char*)malloc(i%1000000); free(p); }
DWORD dwEnd = GetTickCount();
printf("***********************",dwEnd - dwStart);
printf("100wMemoryTest:%d ms\n",dwEnd - dwStart);
}
#ifdef WIN32
class CGateService : public CWinService
{
public:
CGateService(LPCSTR pServiceName, DWORD dwServiceType = SERVICE_WIN32_OWN_PROCESS):CWinService(pServiceName, dwServiceType){};
int AppMain()
{
CFileLogger flog(_T("GateServer_%s.log"), getCurrentTimeDesc());
CBaseList<CRunSockProcesser*> gateList;
SetCurrentDirectory("../"); //CWinService里会把当前目录改成exe允许的目录所以这里再转一下
if ( CreateAndStartGateServers(gateList) )
{
in_addr ia;
ia.s_addr = RUNGATE_KRN_VERSION;
OutputMsg( rmTip, _T("-------------------------------------------") );
OutputMsg( rmTip, _T("网关服务器启动成功,核心版本号是%s"), inet_ntoa(ia) );
OutputMsg( rmTip, _T("quit命令可以停止服务并退出程序") );
OutputMsg( rmTip, _T("-------------------------------------------") );
while (!m_boServiceExit)
{
Sleep(1000);
}
}
DestroyGateServers(gateList);
Sleep(2000);//休眠一秒等待日志全部刷新到文件
return 0;
}
};
#endif
int main(int argc, char **argv)
{
//TestMemory();
#ifdef WIN32
SetUnhandledExceptionFilter( DefaultUnHandleExceptionFilter );
#endif
(void)signal(SIGHUP, SIG_IGN);
(void)signal(SIGINT, signal_handler);
(void)signal(SIGTERM, signal_handler);
InitDefMsgOut();
CTimeProfMgr::getSingleton().InitMgr();
winitseed((unsigned int)_getTickCount()); //初始化随机数函数
#ifndef _SERVICE
//if (argc == 2 && strncmp("/cmd",argv[1],4)==0)//平时调试用
{
#ifdef WIN32
SetCurrentDirectory("./");
#else
std::string filename(argv[0]);
size_t found = filename.find_last_of("/\\");
filename = filename.substr(0, found);
if( filename[0] == '.' && filename.length()==1 )
filename = "./" ;
SetCurrentDirectory(filename.c_str());
#endif
ServerMain(argc, argv);
}
#else
//else
{
ServiceMain(argc, argv);
}
#endif
UninitDefMsgOut();
#ifdef _MLIB_DUMP_MEMORY_LEAKS_
_CrtDumpMemoryLeaks();
#endif
return 0;
}
#ifdef WIN32
VOID ServiceMain(int argc, char** argv)
{
LPTSTR sCmd = NULL;
if (argc >= 2)
{
sCmd = argv[1];
}
CGateService service("GateService");
service.Run(sCmd);
}
#endif
void ServerMain(int argc, char **argv)
{
CFileLogger flog(_T("../log/GateServer_%s.log"), getCurrentTimeDesc());
CBaseList<CRunSockProcesser*> gateList;
char *pFileName =NULL;
if(argc >=2)
{
pFileName = argv[1];
}else
{
pFileName="GateServerLinux.txt";
}
if ( CreateAndStartGateServers(gateList,pFileName) )
{
TCHAR sCmdBuf[512];
in_addr ia;
ia.s_addr = RUNGATE_KRN_VERSION;
OutputMsg( rmTip, _T("-------------------------------------------") );
OutputMsg( rmTip, _T("网关服务器启动成功,核心版本号是%s"), inet_ntoa(ia) );
OutputMsg( rmTip, _T("spf命令可以查看当前的网关状态") );
OutputMsg( rmTip, _T("quit命令可以停止服务并退出程序") );
OutputMsg( rmTip, _T("-------------------------------------------") );
while (g_ServerIsRunning)
{
#ifdef WIN32
if(_kbhit())
{
_getts(sCmdBuf);
}
else
{
Sleep(100);
continue;
}
if ( strncmp(sCmdBuf, _T("\\q"), 2) == 0
|| strncmp(sCmdBuf, _T("exit"), 4) == 0
|| strncmp(sCmdBuf, _T("quit"), 4) == 0 )
{
OutputMsg( rmTip, _T("正在停止网关服务...") );
break;
}
else if ( strncmp(sCmdBuf, _T("spf"), 3) == 0 ) // 需要刷
{
for (INT_PTR i=0; i< gateList.count(); ++i)
{
CRunDataProcesser::ShowGateStatus(gateList[i]->GetDataProcesser());
}
CTimeProfMgr::getSingleton().dump();
}
else if (strncmp(sCmdBuf, _T("stst"), 4) == 0) // stst 10ms为单位
{
char *pParam = sCmdBuf + 4;
while (*pParam == ' ')
pParam++;
if (pParam)
{
UINT_PTR nInterval = atoi(pParam);
if (nInterval > 0)
{
CRunDataProcesser::s_nSndThreadSleepTime = (unsigned int)nInterval;
OutputMsg(rmNormal, _T("Set SndThreadSleepTime[%d ms] Succ"), nInterval);
}
}
}
else if(strncmp(sCmdBuf, _T("ignore"), 6) == 0)
{
CRunDataProcesser::s_nIgnoreDataPacket = 1;
}
else if(strncmp(sCmdBuf, _T("resume"), 6) == 0)
{
CRunDataProcesser::s_nIgnoreDataPacket = 0;
}
#else
if(!GateEngineRunning) break;
#endif
Sleep(10);
}
}
DestroyGateServers(gateList);
Sleep(2000);//休眠一秒等待日志全部刷新到文件
}
bool CreateAndStartGateServers(CBaseList<CRunSockProcesser*> &gateList,char *pConfig)
{
CGateConfigList configList;
CGateServerConfig configReader;
CRunSockProcesser *pRunSock;
CRunDataProcesser *pRunData;
if ( configReader.loadConfig(configList,pConfig) )
{
INT_PTR i, nCount = configList.count();
PGATECONFIG pConfigList = configList;
for (i=0; i<nCount; ++i)
{
//创建并配置网关后台服务数据处理器
pRunData = new CRunDataProcesser(__max(1024, pConfigList[i].GateServer.nMaxSession));
pRunData->SetSendThreadCount( __max(1,pConfigList[i].GateServer.SendThreadCount) );
pRunData->SetDataProcessType(dp_Default);
pRunData->SetServerHost(pConfigList[i].BackServer.sHost);
pRunData->SetServerPort(pConfigList[i].BackServer.nPort);
pRunData->SetName(pConfigList[i].GateServer.sName);
//创建并配置网关用户服务器处理器
pRunSock = new CSelectRunSockProcesser();
pRunSock->SetBindAddress( pConfigList[i].GateServer.sAddress );
pRunSock->SetBindPort( pConfigList[i].GateServer.nPort );
pRunSock->SetDataProcesser(pRunData);
pRunData->SetRunSockProcesser(pRunSock);
//将网关添加到列表中
gateList.add(pRunSock);
//启动网关
if ( !pRunSock->InitBase() || !pRunData->Startup() || !pRunSock->Start() )
{
OutputMsg(rmError, _T("Start GateServer[%s] Failed"), pConfigList[i].GateServer.sName);
return false;
}
OutputMsg(rmTip, _T("GateServer[%s] Started"), pConfigList[i].GateServer.sName);
}
return true;
}
return false;
}
void DestroyGateServers(CBaseList<CRunSockProcesser*> &gateList)
{
CRunSockProcesser *pRunSock;
CRunDataProcesser *pRunData;
INT_PTR i, nCount = gateList.count();
for (i=0; i<nCount; ++i)
{
//停止网关用户服务器处理器
pRunSock = gateList[i];
pRunSock->Stop();
//停止网关后台服务数据处理器
pRunData = pRunSock->GetDataProcesser();
pRunData->Stop();
//销毁网关对象
pRunSock->SetDataProcesser(NULL);
OutputMsg(rmTip, _T("GateServer[%s] Stoped"), pRunData->GetName());
delete pRunSock;
delete pRunData;
}
gateList.empty();
}

590
server/GateServer/sha1.cpp Normal file
View File

@@ -0,0 +1,590 @@
/*
* sha1.cpp
*
* Copyright (C) 1998, 2009
* Paul E. Jones <paulej@packetizer.com>
* All Rights Reserved.
*
*****************************************************************************
* $Id: sha1.cpp 12 2009-06-22 19:34:25Z paulej $
*****************************************************************************
*
* Description:
* This class implements the Secure Hashing Standard as defined
* in FIPS PUB 180-1 published April 17, 1995.
*
* The Secure Hashing Standard, which uses the Secure Hashing
* Algorithm (SHA), produces a 160-bit message digest for a
* given data stream. In theory, it is highly improbable that
* two messages will produce the same message digest. Therefore,
* this algorithm can serve as a means of providing a "fingerprint"
* for a message.
*
* Portability Issues:
* SHA-1 is defined in terms of 32-bit "words". This code was
* written with the expectation that the processor has at least
* a 32-bit machine word size. If the machine word size is larger,
* the code should still function properly. One caveat to that
* is that the input functions taking characters and character arrays
* assume that only 8 bits of information are stored in each character.
*
* Caveats:
* SHA-1 is designed to work with messages less than 2^64 bits long.
* Although SHA-1 allows a message digest to be generated for
* messages of any number of bits less than 2^64, this implementation
* only works with messages with a length that is a multiple of 8
* bits.
*
*/
#include "sha1.h"
/*
* SHA1
*
* Description:
* This is the constructor for the sha1 class.
*
* Parameters:
* None.
*
* Returns:
* Nothing.
*
* Comments:
*
*/
SHA1::SHA1()
{
Reset();
}
/*
* ~SHA1
*
* Description:
* This is the destructor for the sha1 class
*
* Parameters:
* None.
*
* Returns:
* Nothing.
*
* Comments:
*
*/
SHA1::~SHA1()
{
// The destructor does nothing
}
/*
* Reset
*
* Description:
* This function will initialize the sha1 class member variables
* in preparation for computing a new message digest.
*
* Parameters:
* None.
*
* Returns:
* Nothing.
*
* Comments:
*
*/
void SHA1::Reset()
{
Length_Low = 0;
Length_High = 0;
Message_Block_Index = 0;
H[0] = 0x67452301;
H[1] = 0xEFCDAB89;
H[2] = 0x98BADCFE;
H[3] = 0x10325476;
H[4] = 0xC3D2E1F0;
Computed = false;
Corrupted = false;
}
/*
* Result
*
* Description:
* This function will return the 160-bit message digest into the
* array provided.
*
* Parameters:
* message_digest_array: [out]
* This is an array of five unsigned integers which will be filled
* with the message digest that has been computed.
*
* Returns:
* True if successful, false if it failed.
*
* Comments:
*
*/
bool SHA1::Result(unsigned *message_digest_array)
{
int i; // Counter
if (Corrupted)
{
return false;
}
if (!Computed)
{
PadMessage();
Computed = true;
}
for(i = 0; i < 5; i++)
{
message_digest_array[i] = H[i];
}
return true;
}
/*
* Input
*
* Description:
* This function accepts an array of octets as the next portion of
* the message.
*
* Parameters:
* message_array: [in]
* An array of characters representing the next portion of the
* message.
*
* Returns:
* Nothing.
*
* Comments:
*
*/
void SHA1::Input( const unsigned char *message_array,
unsigned length)
{
if (!length)
{
return;
}
if (Computed || Corrupted)
{
Corrupted = true;
return;
}
while(length-- && !Corrupted)
{
Message_Block[Message_Block_Index++] = (*message_array & 0xFF);
Length_Low += 8;
Length_Low &= 0xFFFFFFFF; // Force it to 32 bits
if (Length_Low == 0)
{
Length_High++;
Length_High &= 0xFFFFFFFF; // Force it to 32 bits
if (Length_High == 0)
{
Corrupted = true; // Message is too long
}
}
if (Message_Block_Index == 64)
{
ProcessMessageBlock();
}
message_array++;
}
}
/*
* Input
*
* Description:
* This function accepts an array of octets as the next portion of
* the message.
*
* Parameters:
* message_array: [in]
* An array of characters representing the next portion of the
* message.
* length: [in]
* The length of the message_array
*
* Returns:
* Nothing.
*
* Comments:
*
*/
void SHA1::Input( const char *message_array,
unsigned length)
{
Input((unsigned char *) message_array, length);
}
/*
* Input
*
* Description:
* This function accepts a single octets as the next message element.
*
* Parameters:
* message_element: [in]
* The next octet in the message.
*
* Returns:
* Nothing.
*
* Comments:
*
*/
void SHA1::Input(unsigned char message_element)
{
Input(&message_element, 1);
}
/*
* Input
*
* Description:
* This function accepts a single octet as the next message element.
*
* Parameters:
* message_element: [in]
* The next octet in the message.
*
* Returns:
* Nothing.
*
* Comments:
*
*/
void SHA1::Input(char message_element)
{
Input((unsigned char *) &message_element, 1);
}
/*
* operator<<
*
* Description:
* This operator makes it convenient to provide character strings to
* the SHA1 object for processing.
*
* Parameters:
* message_array: [in]
* The character array to take as input.
*
* Returns:
* A reference to the SHA1 object.
*
* Comments:
* Each character is assumed to hold 8 bits of information.
*
*/
SHA1& SHA1::operator<<(const char *message_array)
{
const char *p = message_array;
while(*p)
{
Input(*p);
p++;
}
return *this;
}
/*
* operator<<
*
* Description:
* This operator makes it convenient to provide character strings to
* the SHA1 object for processing.
*
* Parameters:
* message_array: [in]
* The character array to take as input.
*
* Returns:
* A reference to the SHA1 object.
*
* Comments:
* Each character is assumed to hold 8 bits of information.
*
*/
SHA1& SHA1::operator<<(const unsigned char *message_array)
{
const unsigned char *p = message_array;
while(*p)
{
Input(*p);
p++;
}
return *this;
}
/*
* operator<<
*
* Description:
* This function provides the next octet in the message.
*
* Parameters:
* message_element: [in]
* The next octet in the message
*
* Returns:
* A reference to the SHA1 object.
*
* Comments:
* The character is assumed to hold 8 bits of information.
*
*/
SHA1& SHA1::operator<<(const char message_element)
{
Input((unsigned char *) &message_element, 1);
return *this;
}
/*
* operator<<
*
* Description:
* This function provides the next octet in the message.
*
* Parameters:
* message_element: [in]
* The next octet in the message
*
* Returns:
* A reference to the SHA1 object.
*
* Comments:
* The character is assumed to hold 8 bits of information.
*
*/
SHA1& SHA1::operator<<(const unsigned char message_element)
{
Input(&message_element, 1);
return *this;
}
/*
* ProcessMessageBlock
*
* Description:
* This function will process the next 512 bits of the message
* stored in the Message_Block array.
*
* Parameters:
* None.
*
* Returns:
* Nothing.
*
* Comments:
* Many of the variable names in this function, especially the single
* character names, were used because those were the names used
* in the publication.
*
*/
void SHA1::ProcessMessageBlock()
{
const unsigned K[] = { // Constants defined for SHA-1
0x5A827999,
0x6ED9EBA1,
0x8F1BBCDC,
0xCA62C1D6
};
int t; // Loop counter
unsigned temp; // Temporary word value
unsigned W[80]; // Word sequence
unsigned A, B, C, D, E; // Word buffers
/*
* Initialize the first 16 words in the array W
*/
for(t = 0; t < 16; t++)
{
W[t] = ((unsigned) Message_Block[t * 4]) << 24;
W[t] |= ((unsigned) Message_Block[t * 4 + 1]) << 16;
W[t] |= ((unsigned) Message_Block[t * 4 + 2]) << 8;
W[t] |= ((unsigned) Message_Block[t * 4 + 3]);
}
for(t = 16; t < 80; t++)
{
W[t] = CircularShift(1,W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]);
}
A = H[0];
B = H[1];
C = H[2];
D = H[3];
E = H[4];
for(t = 0; t < 20; t++)
{
temp = CircularShift(5,A) + ((B & C) | ((~B) & D)) + E + W[t] + K[0];
temp &= 0xFFFFFFFF;
E = D;
D = C;
C = CircularShift(30,B);
B = A;
A = temp;
}
for(t = 20; t < 40; t++)
{
temp = CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[1];
temp &= 0xFFFFFFFF;
E = D;
D = C;
C = CircularShift(30,B);
B = A;
A = temp;
}
for(t = 40; t < 60; t++)
{
temp = CircularShift(5,A) +
((B & C) | (B & D) | (C & D)) + E + W[t] + K[2];
temp &= 0xFFFFFFFF;
E = D;
D = C;
C = CircularShift(30,B);
B = A;
A = temp;
}
for(t = 60; t < 80; t++)
{
temp = CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[3];
temp &= 0xFFFFFFFF;
E = D;
D = C;
C = CircularShift(30,B);
B = A;
A = temp;
}
H[0] = (H[0] + A) & 0xFFFFFFFF;
H[1] = (H[1] + B) & 0xFFFFFFFF;
H[2] = (H[2] + C) & 0xFFFFFFFF;
H[3] = (H[3] + D) & 0xFFFFFFFF;
H[4] = (H[4] + E) & 0xFFFFFFFF;
Message_Block_Index = 0;
}
/*
* PadMessage
*
* Description:
* According to the standard, the message must be padded to an even
* 512 bits. The first padding bit must be a '1'. The last 64 bits
* represent the length of the original message. All bits in between
* should be 0. This function will pad the message according to those
* rules by filling the message_block array accordingly. It will also
* call ProcessMessageBlock() appropriately. When it returns, it
* can be assumed that the message digest has been computed.
*
* Parameters:
* None.
*
* Returns:
* Nothing.
*
* Comments:
*
*/
void SHA1::PadMessage()
{
/*
* Check to see if the current message block is too small to hold
* the initial padding bits and length. If so, we will pad the
* block, process it, and then continue padding into a second block.
*/
if (Message_Block_Index > 55)
{
Message_Block[Message_Block_Index++] = 0x80;
while(Message_Block_Index < 64)
{
Message_Block[Message_Block_Index++] = 0;
}
ProcessMessageBlock();
while(Message_Block_Index < 56)
{
Message_Block[Message_Block_Index++] = 0;
}
}
else
{
Message_Block[Message_Block_Index++] = 0x80;
while(Message_Block_Index < 56)
{
Message_Block[Message_Block_Index++] = 0;
}
}
/*
* Store the message length as the last 8 octets
*/
Message_Block[56] = (Length_High >> 24) & 0xFF;
Message_Block[57] = (Length_High >> 16) & 0xFF;
Message_Block[58] = (Length_High >> 8) & 0xFF;
Message_Block[59] = (Length_High) & 0xFF;
Message_Block[60] = (Length_Low >> 24) & 0xFF;
Message_Block[61] = (Length_Low >> 16) & 0xFF;
Message_Block[62] = (Length_Low >> 8) & 0xFF;
Message_Block[63] = (Length_Low) & 0xFF;
ProcessMessageBlock();
}
/*
* CircularShift
*
* Description:
* This member function will perform a circular shifting operation.
*
* Parameters:
* bits: [in]
* The number of bits to shift (1-31)
* word: [in]
* The value to shift (assumes a 32-bit integer)
*
* Returns:
* The shifted value.
*
* Comments:
*
*/
unsigned SHA1::CircularShift(int bits, unsigned word)
{
return ((word << bits) & 0xFFFFFFFF) | ((word & 0xFFFFFFFF) >> (32-bits));
}

90
server/GateServer/sha1.h Normal file
View File

@@ -0,0 +1,90 @@
/*
* sha1.h
*
* Copyright (C) 1998, 2009
* Paul E. Jones <paulej@packetizer.com>
* All Rights Reserved.
*
*****************************************************************************
* $Id: sha1.h 12 2009-06-22 19:34:25Z paulej $
*****************************************************************************
*
* Description:
* This class implements the Secure Hashing Standard as defined
* in FIPS PUB 180-1 published April 17, 1995.
*
* Many of the variable names in this class, especially the single
* character names, were used because those were the names used
* in the publication.
*
* Please read the file sha1.cpp for more information.
*
*/
#ifndef _SHA1_H_
#define _SHA1_H_
class SHA1
{
public:
SHA1();
virtual ~SHA1();
/*
* Re-initialize the class
*/
void Reset();
/*
* Returns the message digest
*/
bool Result(unsigned *message_digest_array);
/*
* Provide input to SHA1
*/
void Input( const unsigned char *message_array,
unsigned length);
void Input( const char *message_array,
unsigned length);
void Input(unsigned char message_element);
void Input(char message_element);
SHA1& operator<<(const char *message_array);
SHA1& operator<<(const unsigned char *message_array);
SHA1& operator<<(const char message_element);
SHA1& operator<<(const unsigned char message_element);
private:
/*
* Process the next 512 bits of the message
*/
void ProcessMessageBlock();
/*
* Pads the current message block to 512 bits
*/
void PadMessage();
/*
* Performs a circular left shift operation
*/
inline unsigned CircularShift(int bits, unsigned word);
unsigned H[5]; // Message digest buffers
unsigned Length_Low; // Message length in bits
unsigned Length_High; // Message length in bits
unsigned char Message_Block[64]; // 512-bit message blocks
int Message_Block_Index; // Index into message block array
bool Computed; // Is the digest computed?
bool Corrupted; // Is the message digest corruped?
};
#endif // _SHA1_H_