init
This commit is contained in:
17
server/GateServer/.vscode/c_cpp_properties.json
vendored
Normal file
17
server/GateServer/.vscode/c_cpp_properties.json
vendored
Normal 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
46
server/GateServer/.vscode/launch.json
vendored
Normal 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
165
server/GateServer/.vscode/settings.json
vendored
Normal 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"
|
||||
},
|
||||
}
|
||||
66
server/GateServer/CMakeLists.txt
Normal file
66
server/GateServer/CMakeLists.txt
Normal 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)
|
||||
11
server/GateServer/CustomExceptHander.cpp
Normal file
11
server/GateServer/CustomExceptHander.cpp
Normal 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
|
||||
9
server/GateServer/CustomExceptHander.h
Normal file
9
server/GateServer/CustomExceptHander.h
Normal file
@@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
#ifdef WIN32
|
||||
/************************************************************************/
|
||||
/* 自定义SEH异常处理Handler,输出异常类型、异常发生地址等信息,并且进行栈回溯。用于解决
|
||||
某些不是 特别重要的异常发生被捕获后,继续程序的执行,但是可能导致的一些潜在的问题不被发现,
|
||||
导致后面很定位的问题。
|
||||
/************************************************************************/
|
||||
DWORD CustomExceptHandler(const LPEXCEPTION_POINTERS lpPointers);
|
||||
#endif
|
||||
583
server/GateServer/CustomGateClient.cpp
Normal file
583
server/GateServer/CustomGateClient.cpp
Normal 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();
|
||||
}
|
||||
139
server/GateServer/CustomGateClient.h
Normal file
139
server/GateServer/CustomGateClient.h
Normal 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;
|
||||
};
|
||||
2150
server/GateServer/DataProcess.cpp
Normal file
2150
server/GateServer/DataProcess.cpp
Normal file
File diff suppressed because it is too large
Load Diff
207
server/GateServer/DataProcess.h
Normal file
207
server/GateServer/DataProcess.h
Normal 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
|
||||
292
server/GateServer/GateServer.cpp
Normal file
292
server/GateServer/GateServer.cpp
Normal 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;
|
||||
}
|
||||
27
server/GateServer/GateServer.def
Normal file
27
server/GateServer/GateServer.def
Normal 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
|
||||
66
server/GateServer/GateServer.h
Normal file
66
server/GateServer/GateServer.h
Normal 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
|
||||
|
||||
95
server/GateServer/GateServerConfig.cpp
Normal file
95
server/GateServer/GateServerConfig.cpp
Normal 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;
|
||||
}
|
||||
41
server/GateServer/GateServerConfig.h
Normal file
41
server/GateServer/GateServerConfig.h
Normal 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
|
||||
198
server/GateServer/GateServerProto.h
Normal file
198
server/GateServer/GateServerProto.h
Normal 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
|
||||
356
server/GateServer/IOCPSockProcess.cpp
Normal file
356
server/GateServer/IOCPSockProcess.cpp
Normal 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
|
||||
43
server/GateServer/IOCPSockProcess.h
Normal file
43
server/GateServer/IOCPSockProcess.h
Normal 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
|
||||
189
server/GateServer/SelectSockProcess.cpp
Normal file
189
server/GateServer/SelectSockProcess.cpp
Normal 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();
|
||||
}
|
||||
38
server/GateServer/SelectSockProcess.h
Normal file
38
server/GateServer/SelectSockProcess.h
Normal 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
|
||||
|
||||
233
server/GateServer/SockProcess.cpp
Normal file
233
server/GateServer/SockProcess.cpp
Normal 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;
|
||||
}
|
||||
48
server/GateServer/SockProcess.h
Normal file
48
server/GateServer/SockProcess.h
Normal 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
|
||||
2
server/GateServer/StdAfx.cpp
Normal file
2
server/GateServer/StdAfx.cpp
Normal file
@@ -0,0 +1,2 @@
|
||||
//预编译头
|
||||
#include "StdAfx.h"
|
||||
85
server/GateServer/StdAfx.h
Normal file
85
server/GateServer/StdAfx.h
Normal 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;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
14
server/GateServer/build.sh
Normal file
14
server/GateServer/build.sh
Normal 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
304
server/GateServer/main.cpp
Normal 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 10(ms为单位)
|
||||
{
|
||||
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
590
server/GateServer/sha1.cpp
Normal 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
90
server/GateServer/sha1.h
Normal 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_
|
||||
Reference in New Issue
Block a user