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

BIN
server/.DS_Store vendored Normal file

Binary file not shown.

3
server/.gitignore vendored Normal file
View File

@@ -0,0 +1,3 @@
Makefile
**/build/**

18
server/.vscode/c_cpp_properties.json vendored Normal file
View File

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

467
server/.vscode/launch.json vendored Normal file
View File

@@ -0,0 +1,467 @@
{
// 使用 IntelliSense 了解相关属性。
// 悬停以查看现有属性的描述。
// 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "(gdb) 启动AmServer",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/../build/AMServer/amserver_d",
"args": ["${workspaceFolder}/../build/AMServer/AMServerLinux.txt"],
"stopAtEntry": false,
"cwd": "${workspaceFolder}",
"environment": [
{
"name":"LD_PRELOAD",
"value":"/usr/local/lib/faketime/libfaketime.so.1"
},
{
"name":"FAKETIME_TIMESTAMP_FILE",
"value":"${workspaceFolder}/../Server.time"
},
{
"name":"FAKETIME_CACHE_DURATION",
"value":"5"
},
],
"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) 附加AmServer",
"type": "cppdbg",
"request": "attach",
"program": "${workspaceFolder}/../build/AMServer/amserver_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;"
},
{
"name": "(gdb) 启动BackStageServer",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/../build/BackStageServer/backstageserver_d",
"args": ["${workspaceFolder}/../build/BackStageServer/BackStageServerLinux.txt"],
"stopAtEntry": false,
"cwd": "${workspaceFolder}",
"environment": [
{
"name":"LD_PRELOAD",
"value":"/usr/local/lib/faketime/libfaketime.so.1"
},
{
"name":"FAKETIME_TIMESTAMP_FILE",
"value":"${workspaceFolder}/../Server.time"
},
{
"name":"FAKETIME_CACHE_DURATION",
"value":"5"
},
],
"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) 附加BackStageServer",
"type": "cppdbg",
"request": "attach",
"program": "${workspaceFolder}/../build/BackStageServer/backstageserver_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;"
},
{
"name": "(gdb) 启动DBServer",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/../build/DBServer/dbserver_d",
"args": ["${workspaceFolder}/../build/DBServer/DBServerLinux.txt"],
"stopAtEntry": false,
"cwd": "${workspaceFolder}",
"environment": [
{
"name":"LD_PRELOAD",
"value":"/usr/local/lib/faketime/libfaketime.so.1"
},
{
"name":"FAKETIME_TIMESTAMP_FILE",
"value":"${workspaceFolder}/../Server.time"
},
{
"name":"FAKETIME_CACHE_DURATION",
"value":"5"
},
],
"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) 附加DBServer",
"type": "cppdbg",
"request": "attach",
"program": "${workspaceFolder}/../build/DBServer/dbserver_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;"
},
{
"name": "(gdb) 启动GateServer",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/../build/GateServer/gateserver_d",
"args": ["${workspaceFolder}/../build/GateServer/GateServerLinux.txt"],
"stopAtEntry": false,
"cwd": "${workspaceFolder}",
"environment": [
{
"name":"LD_PRELOAD",
"value":"/usr/local/lib/faketime/libfaketime.so.1"
},
{
"name":"FAKETIME_TIMESTAMP_FILE",
"value":"${workspaceFolder}/../Server.time"
},
{
"name":"FAKETIME_CACHE_DURATION",
"value":"5"
},
],
"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) 附加GateServer",
"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;"
},
{
"name": "(gdb) 启动LocalLogServer",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/../build/LocalLogServer/locallogserver_d",
"args": ["${workspaceFolder}/../build/LocalLogServer/LocallogServerLinux.txt"],
"stopAtEntry": false,
"cwd": "${workspaceFolder}",
"environment": [
{
"name":"LD_PRELOAD",
"value":"/usr/local/lib/faketime/libfaketime.so.1"
},
{
"name":"FAKETIME_TIMESTAMP_FILE",
"value":"${workspaceFolder}/../Server.time"
},
{
"name":"FAKETIME_CACHE_DURATION",
"value":"5"
},
],
"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) 附加LocalLogServer",
"type": "cppdbg",
"request": "attach",
"program": "${workspaceFolder}/../build/LocalLogServer/locallogserver_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;"
},
{
"name": "(gdb) 启动LoggerServer",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/../build/LoggerServer/loggerserver_d",
"args": ["${workspaceFolder}/../build/LoggerServer/LoggerServerLinux.txt"],
"stopAtEntry": false,
"cwd": "${workspaceFolder}",
"environment": [
{
"name":"LD_PRELOAD",
"value":"/usr/local/lib/faketime/libfaketime.so.1"
},
{
"name":"FAKETIME_TIMESTAMP_FILE",
"value":"${workspaceFolder}/../Server.time"
},
{
"name":"FAKETIME_CACHE_DURATION",
"value":"5"
},
],
"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) 附加LoggerServer",
"type": "cppdbg",
"request": "attach",
"program": "${workspaceFolder}/../build/LoggerServer/loggerserver_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;"
},
{
"name": "(gdb) 启动LogicServer",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/../build/LogicServer/logicserver_d",
"args": ["${workspaceFolder}/../build/LogicServer/LogicServerLinux.txt"],
"stopAtEntry": false,
"cwd": "${workspaceFolder}",
"environment": [
{
"name":"LD_PRELOAD",
"value":"/usr/local/lib/faketime/libfaketime.so.1"
},
{
"name":"FAKETIME_TIMESTAMP_FILE",
"value":"${workspaceFolder}/../Server.time"
},
{
"name":"FAKETIME_CACHE_DURATION",
"value":"5"
},
],
"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) 附加LogicServer",
"type": "cppdbg",
"request": "attach",
"program": "${workspaceFolder}/../build/LogicServer/logicserver_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;"
},
{
"name": "(gdb) 启动NameServer",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/../build/NameServer/nameserver_d",
"args": ["${workspaceFolder}/../build/NameServer/NameServerLinux.txt"],
"stopAtEntry": false,
"cwd": "${workspaceFolder}",
"environment": [
{
"name":"LD_PRELOAD",
"value":"/usr/local/lib/faketime/libfaketime.so.1"
},
{
"name":"FAKETIME_TIMESTAMP_FILE",
"value":"${workspaceFolder}/../Server.time"
},
{
"name":"FAKETIME_CACHE_DURATION",
"value":"5"
},
],
"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) 附加NameServer",
"type": "cppdbg",
"request": "attach",
"program": "${workspaceFolder}/../build/NameServer/nameserver_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;"
},
{
"name": "(gdb) 启动SessionServer",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/../build/SessionServer/sessionserver_d",
"args": ["${workspaceFolder}/../build/SessionServer/SessionServerLinux.txt"],
"stopAtEntry": false,
"cwd": "${workspaceFolder}",
"environment": [
{
"name":"LD_PRELOAD",
"value":"/usr/local/lib/faketime/libfaketime.so.1"
},
{
"name":"FAKETIME_TIMESTAMP_FILE",
"value":"${workspaceFolder}/../Server.time"
},
{
"name":"FAKETIME_CACHE_DURATION",
"value":"5"
},
],
"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) 附加SessionServer",
"type": "cppdbg",
"request": "attach",
"program": "${workspaceFolder}/../build/SessionServer/sessionserver_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;"
}
]
}

192
server/.vscode/settings.json vendored Normal file
View File

@@ -0,0 +1,192 @@
{
"C_Cpp.default.intelliSenseMode": "gcc-x64",
"C_Cpp.intelliSenseEngineFallback": "Enabled",
"C_Cpp.intelliSenseEngine": "Tag Parser",
"C_Cpp.default.includePath": [
"${default}",
"${workspaceFolder}/common/include/**",
"${workspaceFolder}/common/def/**",
"${workspaceFolder}/DBServer**",
"${workspaceFolder}/GateServer**",
"${workspaceFolder}/LogicServer**"
],
"C_Cpp.autoAddFileAssociations": true,
"cmake.cmakePath": "/usr/local/bin/cmake",
"cmake.buildDirectory": "${workspaceFolder}/../build",
"cmake.configureOnOpen": false,
// 启用跟踪日志到文件和控制台(非常嘈杂)。
"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,
"**/CMakeFiles": true,
//"**/AmServer": true,
// "**/LocalLog": true,
///"**/LoggerServer": true,
//"**/BackStageServer": true,
//"**/Gateway.back": true,
// "**/GateServer":true,
// "**/NameServer": true,
// "**/SessionServer": true
},
// 配置文件路径的 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,
"**/GateServer":true,
"**/NameServer": true,
"**/SessionServer": 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": {
"**/*.code-search": true,
"**/bower_components": true,
"**/CMakeFiles": true,
"**/Makefile": true,
"**/node_modules": true,
"**/robot": true,
"**/GateServer":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",
"slist": "cpp",
"strstream": "cpp",
"cerrno": "cpp"
},
"cmake.configureArgs": [
"-DCMAKE_BUILD_TYPE=Debug"
],
"svn.delete.actionForDeletedFiles": "remove",
}

19
server/.vscode/tasks.json vendored Normal file
View File

@@ -0,0 +1,19 @@
{
"tasks": [
{
"type": "shell",
"label": "gcc build active file",
"command": "/usr/bin/gcc",
"args": [
"-g",
"${file}",
"-o",
"${fileDirname}/${fileBasenameNoExtension}"
],
"options": {
"cwd": "/usr/bin"
}
}
],
"version": "2.0.0"
}

40
server/111.sh Normal file
View File

@@ -0,0 +1,40 @@
#! /bin/bash
# 编译模式
if [ -n "$1" ]; then
BuiltType=$1
else
BuiltType=Release
fi
# 移除上次编译cache
rm -rf CMakeCache.txt cmake_install.cmake CMakeFiles/
#find /home -iname "*CMakeFiles*" -type d -exec rm -rf {} + ;
#find /home -iname "*CMakeCache*" -type f -exec rm -rf {} + ;
#find /home -iname "*cmake_install*" -type f -exec rm -rf {} + ;
#find /home -iname "makefile" -type f -exec rm -rf {} + ;
# 生成lua注册文件
cd $(cd "$(dirname "$0")" && pwd)
srcDIR=`pwd`
cd LogicServer/script/tolua++
./../../../../sdk/tolua++/tolua++ -n server -o serverInterface.cpp serverInterface.scp
#cd $srcDIR
#mkdir temp_BuildAll
#cd temp_BuildAll
# 生成项目并编译
cd $srcDIR
cmake -DCMAKE_BUILD_TYPE=${BuiltType} ./
make -j4
#cmake .. -DCMAKE_BUILD_TYPE=${BuiltType}
#cmake -DCMAKE_BUILD_TYPE=${BuiltType} ./
#make -j4
# 记录版本
#svn log -l 1 > web/server.version

View File

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

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

@@ -0,0 +1,46 @@
{
// 使用 IntelliSense 了解相关属性。
// 悬停以查看现有属性的描述。
// 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "(gdb) 启动",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/../../build/AMServer/amserver_d",
"args": ["${workspaceFolder}/../../build/AMServer/AMServerLinux.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/AMServer/amserver_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/AmServer/.vscode/settings.json vendored Normal file
View File

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

View File

@@ -0,0 +1,660 @@
#include "stdafx.h"
#include "AMProcto.h"
#include "CommonDef.h"
using namespace AMProcto;
using namespace jxSrvDef;
CAMClientSocket::CAMClientSocket(void):
Inherited()
{
memset(m_Spid,0,sizeof(m_Spid));
memset(m_gName,0,sizeof(m_gName));
m_sMsgList.setLock(&m_sMsgListLock);
m_sFreeList.setLock(&m_sFreeListLock);
InitializeCriticalSection( &m_TaskMsgVecLock );
m_Product = NULL;
m_IsRegist = false;
m_sClientName[0] =0;
m_eClientType =InvalidServer;
m_boRegisted =0;
m_nClientSrvIdx =0;
m_pSrv =NULL;
}
CAMClientSocket::CAMClientSocket(CAMServerSocket* pSrv,SOCKET nSocket, SOCKADDR_IN *pClientAddr):
Inherited()
{
m_pSrv = pSrv;
SetClientSocket(nSocket,pClientAddr);
memset(m_Spid,0,sizeof(m_Spid));
memset(m_gName,0,sizeof(m_gName));
m_sMsgList.setLock(&m_sMsgListLock);
m_sFreeList.setLock(&m_sFreeListLock);
InitializeCriticalSection( &m_TaskMsgVecLock );
m_Product = NULL;
m_IsRegist = false;
m_sClientName[0] =0;
m_eClientType =InvalidServer;
m_boRegisted =0;
m_nClientSrvIdx =0;
}
CAMClientSocket::~CAMClientSocket(void)
{
DeleteCriticalSection( &m_TaskMsgVecLock );
DestroyPacketList(m_sMsgList);
DestroyPacketList(m_sFreeList);
}
VOID CAMClientSocket::OnDispatchRecvPacket(const jxSrvDef::INTERSRVCMD nCmd, CDataPacketReader &inPacket)
{
if (!m_pSrv || nCmd ==0)
{
return;
}
//__try
{
AddMessage(nCmd,inPacket);
}
//__except(DefaultExceptHandler(GetExceptionInformation()))
{
}
}
CDataPacket& CAMClientSocket::allocProtoPacket(const jxSrvDef::INTERSRVCMD nCmd)
{
CDataPacket &Packet = allocSendPacket();
PDATAHEADER pPackHdr;
//预留通信数据头空间
Packet.setLength(sizeof(*pPackHdr));
Packet.setPosition(sizeof(*pPackHdr));
pPackHdr = (PDATAHEADER)Packet.getMemoryPtr();
pPackHdr->tag = DEFAULT_TAG_VALUE;
//写入通信消息号
Packet << nCmd;
return Packet;
}
VOID CAMClientSocket::SendKeepAlive()
{
CDataPacket& packet = allocProtoPacket(0);
flushProtoPacket(packet);
}
VOID CAMClientSocket::flushProtoPacket(CDataPacket& packet)
{
PDATAHEADER pPackHdr = (PDATAHEADER)packet.getMemoryPtr();
//计算并向协议头中写入通信数据长度
INT_PTR nDataSize = packet.getLength() - sizeof(*pPackHdr);
if(nDataSize > INT_MAX)
{
WORD wHead= *(WORD*)((char*)packet.getMemoryPtr() + sizeof(*pPackHdr));
OutputMsg(rmError,"严重错误CCustomJXServerClientSocket::flushProtoPacket 数据长度%d过长,head=%d",(int)nDataSize,(int)wHead);
}
pPackHdr->len = nDataSize;
flushSendPacket(packet);
}
VOID CAMClientSocket::ProcessRecvBuffers(PDATABUFFER pDataBuffer)
{
//如果连接已断开则丢弃所有数据
if ( !connected() )
{
Inherited::ProcessRecvBuffers(pDataBuffer);
SwapRecvProcessBuffers();
return;
}
if ( pDataBuffer->nOffset <= 0 )
{
SwapRecvProcessBuffers();
return;
}
//如果客户端尚未注册则处理注册数据包
if ( !m_boRegisted )
{
PSERVER_REGDATA pRegData;
if ( pDataBuffer->nOffset >= sizeof(*pRegData) )
{
pRegData = (PSERVER_REGDATA)pDataBuffer->pBuffer;
if ( !OnValidateRegData(pRegData) )
{
close();
SwapRecvProcessBuffers();
return;
}
m_boRegisted = 1;
m_eClientType =(jxSrvDef::SERVERTYPE) pRegData->ServerType;
m_nClientSrvIdx = pRegData->ServerIndex;
strcpy(m_sClientName, pRegData->ServerName);
pDataBuffer->pPointer += sizeof(*pRegData);
//OnRegDataValidated();
OutputMsg(rmTip, _T("[%s] client ([%s]:[%d]) registe success [%s]"), getServerTypeName(m_eClientType),
GetRemoteHost(), GetRemotePort(), m_sClientName);
}
}
jxSrvDef::INTERSRVCMD nCmd;
INT_PTR dwRemainSize;
PDATAHEADER pPackHdr;
char* pDataEnd = pDataBuffer->pBuffer + pDataBuffer->nOffset;
while ( TRUE )
{
dwRemainSize = (INT_PTR)(pDataEnd - pDataBuffer->pPointer);
//如果缓冲区中的剩余长度小于通信协议头的长度,则交换缓冲并在以后继续进行处理
if ( dwRemainSize < sizeof(*pPackHdr) )
{
SwapRecvProcessBuffers();
break;
}
pPackHdr = (PDATAHEADER)pDataBuffer->pPointer;
//检查包头标志是否有效,如果包头标志无效则需要遍历数据包查找包头
if ( pPackHdr->tag != DEFAULT_TAG_VALUE )
{
char* sCurPtr = pDataBuffer->pPointer;
do
{
pDataBuffer->pPointer++;
pPackHdr = (PDATAHEADER)pDataBuffer->pPointer;
//找到包头标记则终止查找
if ( pPackHdr->tag == DEFAULT_TAG_VALUE )
break;
}
while (pDataBuffer->pPointer < pDataEnd - 1);
//如果无法查找到包头,则保留接收缓冲末尾的最后一个字符并交换接收/处理缓冲以便下次继续连接新接收的数据后重新查找包头
if ( pPackHdr->tag != DEFAULT_TAG_VALUE )
{
SwapRecvProcessBuffers();
//找不到协议头标志,输出错误消息
OutputMsg(rmError, _T("sessionsrv recv invalid server data, proto header can not be found") );
break;
}
//输出找到包头的消息
OutputMsg(rmError, _T("%s recv invalid server data, proto header refound after %d bytes"),
getClientName(), (int)(pDataBuffer->pPointer - sCurPtr));
}
//如果处理接收数据的缓冲中的剩余数据长度不足协议头中的数据长度,则交换缓冲并在下次继续处理
dwRemainSize -= sizeof(*pPackHdr);
if ( pPackHdr->len > dwRemainSize )
{
SwapRecvProcessBuffers();
break;
}
//将缓冲读取指针调整到下一个通信数据包的位置
pDataBuffer->pPointer += sizeof(*pPackHdr) + pPackHdr->len;
if ( pPackHdr->len >= sizeof(nCmd) )
{
//将通信数据段保存在packet中
CDataPacketReader packet(pPackHdr + 1, pPackHdr->len);
//分派数据包处理
packet >> nCmd;
OnDispatchRecvPacket(nCmd, packet);
}
else
{
OutputMsg(rmError, _T("%s recv invalid server packet, packet size to few(%d)"),
getClientName(), pPackHdr->len);
}
}
}
bool CAMClientSocket::OnValidateRegData(const jxSrvDef::PSERVER_REGDATA pRegData)
{
//游戏服和db能够登陆
if ( pRegData && pRegData->GameType == SERVER_REGDATA::GT_JianXiaoJiangHu &&
pRegData->ServerType == SessionServer )
{
return true;
}
else
{
return false;
}
}
VOID CAMClientSocket::OnRun()
{
Inherited::OnRun();
//static const int ReserveSize = 256;
if (m_sMsgList.appendCount() > 0)
m_sMsgList.flush();
while (m_sMsgList.count() > 0)
{
CDataPacket* packet = m_sMsgList[0];
//CDataPacket &tmpPacket = allocProtoPacket(AMProcto::AMC_COMSUME);
//tmpPacket.reserve(ReserveSize);
//tmpPacket.adjustOffset( DecodeBuffer(packet->getOffsetPtr(),tmpPacket.getOffsetPtr(), packet->getAvaliableLength(), ReserveSize-(DWORD)(tmpPacket.getOffsetPtr()-tmpPacket.getMemoryPtr())) );
jxSrvDef::INTERSRVCMD nCmd;
*packet >> nCmd;
//__try
{
HandleAMMessage(nCmd, *packet);
}
//__except(DefaultExceptHandler(GetExceptionInformation()))
{
}
m_sMsgList.remove(0);
//FreePacket(&tmpPacket);
FreePacket(packet);
}
}
void CAMClientSocket::AddMessage(jxSrvDef::INTERSRVCMD nCmd, CDataPacketReader& packet)
{
CDataPacket *cache_pkg = AllocPacket();
if (!cache_pkg)
{
OutputMsg(rmError, _T("AMServer DataCacheError allocPacket failed"));
return;
}
size_t nLen = packet.getAvaliableLength();
//cache_pkg->setLength(nLen + sizeof(WORD));
(*cache_pkg) << (nCmd);
//cache_pkg->writeAtom(WORD(nCmd));
cache_pkg->writeBuf(packet.getOffsetPtr(), nLen);
cache_pkg->setPosition(0);
//const char* pData = cache_pkg->getMemoryPtr();
m_sMsgList.append(cache_pkg);
}
CDataPacket* CAMClientSocket::AllocPacket()
{
if (m_sFreeList.count() > 0)
{
CDataPacket* pkg = m_sFreeList.pop();
pkg->setLength(0);
return pkg;
}
if (m_sFreeList.appendCount() > 0)
m_sFreeList.flush();
if (m_sFreeList.count() <= 0 )
allocSendPacketList(m_sFreeList, 512);
CDataPacket* pkg = m_sFreeList.pop();
pkg->setLength(0);
return pkg;
}
void CAMClientSocket::FreePacket(CDataPacket* packet)
{
m_sFreeList.append(packet);
}
void CAMClientSocket::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();
}
void CAMClientSocket::HandleAMMessage(jxSrvDef::INTERSRVCMD nCmd, CDataPacket &packet)
{
switch (nCmd)
{
case AMC_REGIST_CLIENT:
{
RegistClient(packet);
break;
}
case AMC_QUERY_AMOUNT:
{
QueryAmount(packet);
break;
}
case AMC_COMSUME:
{
Consume(packet);
break;
}
case AMC_TASK_SITUATION:
{
SendTaskSituation(packet);
break;
}
}
}
void CAMClientSocket::SendPaySucceed(int nServerIndex,UINT uUserId,UINT nActorId, UINT uMoney)
{
static const int ReserveSize = 256;
AMMSG msg;
msg.nServerId = (INT)nServerIndex;
msg.nUserId = (unsigned int)uUserId;
msg.nResult = (INT)uMoney;
msg.lOPPtr = (unsigned int)nActorId;
CDataPacket &pack = allocProtoPacket(AMProcto::AMS_PAYSUCCESS);
pack.reserve(ReserveSize);
pack.adjustOffset(EncodeBuffer(&msg, pack.getOffsetPtr(), (DWORD)sizeof(msg), ReserveSize-(DWORD)(pack.getOffsetPtr()-pack.getMemoryPtr()) ));
flushProtoPacket(pack);
OutputMsg( rmTip, "通知[成功充值]成功" );
}
void CAMClientSocket::AskTaskSituation(int nserverid, UINT uUserId, UINT cmdid, int contractid, int step )
{
static const int ReserveSize = 256;
TASKMSG msg;
msg.nServerId = (INT)nserverid;
msg.nUserId = (unsigned int)uUserId;
msg.nCmd = (INT)cmdid;
msg.nContractid = (INT)contractid;
msg.nStep = (INT)step;
CDataPacket &pack = allocProtoPacket(AMProcto::AMS_TASK_SITUATION);
pack.reserve(ReserveSize);
pack.adjustOffset(EncodeBuffer(&msg, pack.getOffsetPtr(), (DWORD)sizeof(msg), ReserveSize-(DWORD)(pack.getOffsetPtr()-pack.getMemoryPtr()) ));
flushProtoPacket(pack);
if(cmdid == 1 )
OutputMsg( rmTip, "finish task :UserID=[%u], ServerID=[%d], CmdID=[%d], ContractID=[%d], Step=[%d]", uUserId, nserverid, cmdid, contractid, step );
else if(cmdid == 2 )
OutputMsg( rmTip, "if finish task, give award : UserID=[%u], ServerID=[%d], CmdID=[%d], ContractID=[%d], Step=[%d]", uUserId, nserverid, cmdid, contractid, step );
else if(cmdid == 3 )
OutputMsg( rmTip, "give award :UserID=[%u], ServerID=[%d], CmdID=[%d], ContractID=[%d], Step=[%d]", uUserId, nserverid, cmdid, contractid, step );
else if(cmdid == 0 )
OutputMsg( rmTip, "get QQvip award :UserID=[%u], ServerID=[%d], CmdID=[%d], ContractID=[%d], Step=[%d]", uUserId, nserverid, cmdid, contractid, step );
}
void CAMClientSocket::AddTaskMsg(SOCKET nsocket, int nserverid, UINT uUserId, UINT cmdid, int contractid, int step )
{
EnterCriticalSection( &m_TaskMsgVecLock );
TASKREQ_Map::iterator it;
it = m_TaskMap.find(uUserId);
if(it == m_TaskMap.end() )
{
TASKREQ_Vec vec;
TASKREQ tmp;
tmp.Serverid = nserverid;
tmp.Socket = (int)nsocket;
tmp.Cmdid = cmdid;
tmp.Contractid = contractid;
tmp.Step = step;
vec.push_back(tmp);
m_TaskMap.insert(TASKREQ_Map::value_type(uUserId, vec));
}
else
{
TASKREQ tmp;
tmp.Serverid = nserverid;
tmp.Socket = (int)nsocket;
tmp.Cmdid = cmdid;
tmp.Contractid = contractid;
tmp.Step = step;
it->second.push_back(tmp);
}
LeaveCriticalSection( &m_TaskMsgVecLock );
OutputMsg( rmTip, "Accept QQTask Msg : UserID=[%u], Socket=[%d], ServerID=[%d], CmdID=[%d], ContractID=[%d], Step=[%d]", uUserId, nsocket, nserverid , cmdid, contractid, step );
}
bool CAMClientSocket::DelTaskMsg(SOCKET nsocket, int nserverid, UINT uUserId, UINT cmdid, int contractid, int step )
{
EnterCriticalSection( &m_TaskMsgVecLock );
bool ret = false;
TASKREQ_Map::iterator it;
it = m_TaskMap.find(uUserId);
if(it == m_TaskMap.end() )
{
ret = false;
}
else
{
TASKREQ tmp;
tmp.Serverid = nserverid;
tmp.Cmdid = cmdid;
tmp.Contractid = contractid;
tmp.Step = step;
for(TASKREQ_Vec::iterator it1 = it->second.begin(); it1 != it->second.end(); )
{
if( *it1 == tmp )
{
it1 = it->second.erase(it1);
ret = true;
break;
}
else
{
it1++;
}
}
}
LeaveCriticalSection( &m_TaskMsgVecLock );
return ret;
}
void CAMClientSocket::RegistClient(CDataPacket &packet)
{
if (m_IsRegist) return;
m_IsRegist = true;
char buff[256];
Decode6BitBuf( packet.getOffsetPtr(), buff, (unsigned int)packet.getAvaliableLength(), sizeof(buff) ); //解开数据
const char *d = "/";
char * p = strtok(buff,d);
strncpy(m_gName, p, strlen(p)); //游戏的编号现在一般用djrm
p=strtok(NULL,d);
strncpy(m_Spid, p, strlen(p)); //游戏的spid
//packet.readString(m_gName,ArrayCount(m_gName));
//m_gName[sizeof(m_gName)-1] =0;
//packet.readString(m_Spid,ArrayCount(m_Spid));
//m_Spid[sizeof(m_Spid)-1] =0;
if (m_pSrv)
{
m_Product = m_pSrv->GetProduct(m_gName,m_Spid);
if( m_Product )
{
OutputMsg( rmTip, "注册成功" );
CDataPacket &pack = allocProtoPacket(AMS_REGIST_CLIENT);
flushProtoPacket(pack);
}
else
OutputMsg( rmTip, "注册失败,接受到的产品名字:[%s]运营商ID[%s]", m_gName, m_Spid );
}
else
OutputMsg( rmTip, "产品客户端创建失败" );
}
void CAMClientSocket::QueryAmount(CDataPacket &packet)
{
AMMSG recv_msg;
const int ReserveSize = 256;
DecodeBuffer(packet.getOffsetPtr(), &recv_msg, (DWORD)packet.getAvaliableLength(), (DWORD)sizeof(recv_msg));
UINT nActorId = 0;
int nResult = GetErrorNo();
if (nResult == 0)
{
UINT uUserId = 0;
uUserId = recv_msg.nUserId ;
nActorId = (UINT)recv_msg.lOPPtr;
nResult = m_Product->QueryAmount(uUserId, nActorId);
}
AMMSG msg;
msg.nUserId = recv_msg.nUserId ;
msg.nServerId = recv_msg.nServerId ;
msg.nResult = (INT)nResult;
msg.lOPPtr = nActorId;
CDataPacket &pack = allocProtoPacket(AMS_QUERY_AMOUNT);
pack.reserve(ReserveSize);
pack.adjustOffset(EncodeBuffer(&msg, pack.getOffsetPtr(), (DWORD)sizeof(msg), ReserveSize-(DWORD)(pack.getOffsetPtr()-pack.getMemoryPtr()) ));
flushProtoPacket(pack);
if (nResult > 0)
{
OutputMsg( rmTip, "元宝数为:[%d], 回复[查询账户数据包]成功, UserID=[%u], actorid=[%u]", (INT)nResult, recv_msg.nUserId,(UINT) recv_msg.lOPPtr);
}
}
void CAMClientSocket::Consume(CDataPacket &packet)
{
char recv_msg[300];
const int ReserveSize = 256;
memset( recv_msg, 0, sizeof(recv_msg) );
DecodeBuffer(packet.getOffsetPtr(), recv_msg, 28, (DWORD)sizeof(recv_msg));
packet.adjustOffset(28);
int nResult = GetErrorNo();
if (nResult == 0)
{
UINT uUserId = 0;
UINT nServerIndex = 0;
UINT nAmount = 0;
UINT nActorId = 0;
char sCharName[128];
memset( sCharName, 0, sizeof(sCharName) );
AMMSG * pMsg = (AMMSG *)recv_msg ;
uUserId = pMsg->nUserId ;
nServerIndex = pMsg->nServerId ;
nAmount = pMsg->nResult ;
nActorId = (UINT)pMsg->lOPPtr;
BYTE nLevel = pMsg->nLevel;
//char * pName = recv_msg + sizeof(AMMSG) ;
//strncpy( sCharName, pName, strlen(pName) );
//sCharName[strlen(sCharName)] = 0 ;
DecodeBuffer(packet.getOffsetPtr(), sCharName, (DWORD)packet.getAvaliableLength(), (DWORD)sizeof(sCharName));
nResult = m_Product->Consume(uUserId,nAmount,sCharName,nServerIndex,nActorId, nLevel);
if(nResult >= 0 )
{
//OutputMsg( rmTip, "提取成功用户ID[%u], 元宝数:[%d], 用户名:[%s], ServerID[%d]", uUserId,nAmount,sCharName,nServerIndex );
OutputMsg( rmTip, _T("Consume succeed, UserID:[%u], YuanBao:[%d], Account:[%s], ServerID:[%d],ActorId:[%u]"), uUserId,nAmount,sCharName,nServerIndex, nActorId);
}
else
{
//OutputMsg( rmTip, "提取失败用户ID[%u], 元宝数:[%d], 用户名:[%s], ServerID[%d]", uUserId,nAmount,sCharName,nServerIndex );
OutputMsg( rmError, _T("Consume failed, UserID:[%u], YuanBao:[%d], Account:[%s], ServerID:[%d],ActorId:[%u]"), uUserId,nAmount,sCharName,nServerIndex,nActorId);
OutputMsg( rmError, _T("Account:[%s], Length of Account:[%d]"), sCharName,strlen(sCharName) );
}
}
AMMSG msg;
AMMSG * pMsg = (AMMSG *)recv_msg ;
msg.nUserId = pMsg->nUserId ;
msg.nServerId = pMsg->nServerId ;
if(nResult >= 0 )
msg.nResult = pMsg->nResult ;
else
msg.nResult = 0;
msg.lOPPtr = pMsg->lOPPtr ;
CDataPacket &pack = allocProtoPacket(AMS_COMSUME);
pack.reserve(ReserveSize);
pack.adjustOffset(EncodeBuffer(&msg, pack.getOffsetPtr(), (DWORD)sizeof(msg), ReserveSize-(DWORD)(pack.getOffsetPtr()-pack.getMemoryPtr()) ));
flushProtoPacket(pack);
}
LPCSTR CAMClientSocket::GetResultCode(int op)
{
switch(op)
{
case 0: return "0"; // 步骤已完成 或 奖励发放成功
case 1: return "1"; // 用户尚未在应用内创建角色
case 2: return "2"; // 用户尚未完成本步骤
case 3: return "3"; // 该步骤奖励已发放过
case 4: return "4"; // 发货失败
}
return "";
}
void CAMClientSocket::SendTaskSituation(CDataPacket &packet)
{
TASKMSG recv_msg;
const int ReserveSize = 256;
DecodeBuffer(packet.getOffsetPtr(), &recv_msg, (DWORD)packet.getAvaliableLength(), (DWORD)sizeof(recv_msg));
int nResult = GetErrorNo();
if (nResult == 0)
{
UINT uUserId = 0;
uUserId = recv_msg.nUserId ;
EnterCriticalSection( &m_TaskMsgVecLock );
TASKREQ_Map::iterator it;
it = m_TaskMap.find(uUserId);
if(it != m_TaskMap.end() )
{
TASKREQ tmp;
tmp.Serverid = recv_msg.nServerId;
tmp.Cmdid = recv_msg.nCmd;
tmp.Contractid = recv_msg.nContractid;
tmp.Step = recv_msg.nStep;
bool flag = true;
for(TASKREQ_Vec::iterator it1 = it->second.begin(); it1 != it->second.end(); )
{
if( *it1 == tmp )
{
if( it1->Socket > 0 )
{
m_pSrv->GetParamParser().SendResponse(it1->Socket, GetResultCode(recv_msg.nResult) );
OutputMsg( rmTip, "UserID=[%u], Socket=[%d], ServerID=[%d], CmdID=[%d], ContractID=[%d], Step=[%d], Result=[%d]", uUserId, it1->Socket, recv_msg.nServerId, recv_msg.nCmd, recv_msg.nContractid, recv_msg.nStep, recv_msg.nResult );
#ifdef WIN32
closesocket(it1->Socket);
#else
::close(it1->Socket);
#endif
it1->Socket = 0;
it1 = it->second.erase(it1);
flag = false;
break;
}
else
{
OutputMsg( rmError, "Socket Error !!! UserID=[%u], ServerID=[%d], CmdID=[%d], ContractID=[%d], Step=[%d], Result=[%d]", uUserId, recv_msg.nServerId, recv_msg.nCmd, recv_msg.nContractid, recv_msg.nStep, recv_msg.nResult );
}
}
else
{
it1++;
}
}
if(flag)
{
OutputMsg( rmWaning, "AM recv unknow msg, UserID=[%u], ServerID=[%d], CmdID=[%d], ContractID=[%d], Step=[%d], Result=[%d]", uUserId, recv_msg.nServerId, recv_msg.nCmd, recv_msg.nContractid, recv_msg.nStep, recv_msg.nResult );
}
}
else
{
OutputMsg( rmWaning, "no UserID=[%d] in AM: ServerID=[%d], CmdID=[%d], ContractID=[%d], Step=[%d], Result=[%d]", uUserId, recv_msg.nServerId, recv_msg.nCmd, recv_msg.nContractid, recv_msg.nStep, recv_msg.nResult );
}
LeaveCriticalSection( &m_TaskMsgVecLock );
}
}
int CAMClientSocket::GetErrorNo()
{
if (!m_IsRegist)
{
OutputMsg( rmError, "未注册");
return ERROR_NOT_REGDIST;
}
if (!m_Product)
{
OutputMsg( rmError, "无法找到对应的产品");
return ERROR_NOTFIND_PRODUCT;
}
return 0;
}

View File

@@ -0,0 +1,122 @@
#pragma once
/*
typedef enum tagAMServerMsg
{
AMC_REGIST = 10000, //注册
AMC_QUERY_AMOUNT = 10001, //查询用户余额
AMC_COMSUME = 10002, //发送用户消费请求
AMS_QUERY_AMOUNT = 20001, //返回用户余额
AMS_COMSUME = 20002, //返回用户消费结果
AMS_PAY_SUCCED = 20003, //返回充值成功
};
*/
typedef struct tagTASKReq
{
int Socket;
int Serverid;
int Cmdid;
int Contractid;
int Step;
bool operator==(const tagTASKReq& a)const
{
if(Serverid == a.Serverid && Cmdid == a.Cmdid && Contractid == a.Contractid && Step == a.Step)
return true;
else
return false;
}
}TASKREQ, *PTASKREQ;
typedef std::vector<TASKREQ> TASKREQ_Vec;
typedef std::map<UINT, TASKREQ_Vec > TASKREQ_Map;
typedef enum tagAMErrorNumber
{
ERROR_NOT_CONNECT_DB = -100, //无法连接数据库
ERROR_QUERY_DB = -101, //查询数据库错误
ERROR_NOT_REGDIST = -102, //未注册
ERROR_NOTFIND_PRODUCT = -103, //无法找到对应的产品
};
class CCustomJXServerClientSocket;
class CAMServerSocket;
class CProduct;
class CAMClientSocket:
protected CCustomServerClientSocket
{
public:
typedef CCustomServerClientSocket Inherited;
CAMClientSocket(void);
CAMClientSocket(CAMServerSocket* pSrv,SOCKET nSocket, SOCKADDR_IN *pClientAddr);
~CAMClientSocket(void);
char * GetSpid() {return m_Spid;}
void SendPaySucceed(int nServerIndex,UINT uUserId,UINT nActorId, UINT uMoney);
void AskTaskSituation(int nserverid, UINT uUserId, UINT cmdid, int contractid, int step );
void AddTaskMsg(SOCKET nsocket, int nserverid, UINT uUserId, UINT cmdid, int contractid, int step );
/* 返回true存在这个msg并删除返回false没有这个msg */
bool DelTaskMsg(SOCKET nsocket, int nserverid, UINT uUserId, UINT cmdid, int contractid, int step );
protected:
virtual VOID OnDispatchRecvPacket(const jxSrvDef::INTERSRVCMD nCmd, CDataPacketReader &inPacket);
virtual bool OnValidateRegData(const jxSrvDef::PSERVER_REGDATA pRegData);
virtual VOID OnRun();
//按通信协议申请一份发送数据包nCmd是通信消息号
//数据包填充完毕后需要调用flushProtoPacket提交到发送队列
CDataPacket& allocProtoPacket(const jxSrvDef::INTERSRVCMD nCmd);
//提交发送数据包到发送缓冲,会自动计算数据长度并向数据包的通信协议头部分写入长度值
VOID flushProtoPacket(CDataPacket& packet);
VOID SendKeepAlive();
/* 覆盖父类的网络数据包处理函数以便实现通信协议的数据包解析 */
VOID ProcessRecvBuffers(PDATABUFFER pDataBuffer);
private:
void AddMessage(jxSrvDef::INTERSRVCMD nCmd, CDataPacketReader& packet);
CDataPacket* AllocPacket();
void FreePacket(CDataPacket* packet);
void DestroyPacketList(CQueueList<CDataPacket*>& pkgList);
void HandleAMMessage(jxSrvDef::INTERSRVCMD nCmd, CDataPacket &packet);
int GetErrorNo();
void RegistClient(CDataPacket &packet);
void QueryAmount(CDataPacket &packet);
void Consume(CDataPacket &packet);
LPCSTR GetResultCode(int op);
void SendResponse(SOCKET nsocket, LPCSTR sContent);
void SendTaskSituation(CDataPacket &packet);
//获取连接的服务器名称
inline LPCSTR getClientName(){ return m_sClientName; }
private:
//char buff[1024];
char m_gName[10]; //游戏英文缩写
char m_Spid[10]; //运营商英文缩写
CQueueList<CDataPacket*> m_sMsgList;
CCSLock m_sMsgListLock;
CQueueList<CDataPacket*> m_sFreeList;
CCSLock m_sFreeListLock;
//CSQLConenction m_Mysql;
CAMServerSocket* m_pSrv;
CProduct * m_Product;
bool m_IsRegist;
unsigned int m_nClientSrvIdx; //客户端的服务器ID
char m_sClientName[64]; //客户端注册的服务器名称
jxSrvDef::SERVERTYPE m_eClientType; //客户端注册的服务器类型
int m_boRegisted; //客户端是否已经注册连接
TASKREQ_Map m_TaskMap;
RTL_CRITICAL_SECTION m_TaskMsgVecLock;
};

View File

@@ -0,0 +1,57 @@
#pragma once
namespace AMProcto
{
#pragma pack(push, 1)
typedef struct tagAMMsg
{
//unsigned short nCmd; //消息码
INT nServerId;//服务器Id
unsigned int nUserId; //UserID
INT nResult; //返回值
INT64 lOPPtr;//操作对象(客户端穿透服务器的数据)
BYTE nLevel; //提取时等级
}AMMSG, *PAMMSG;
#pragma pack(pop)
#pragma pack(push, 1)
typedef struct tagTASKMsg
{
//unsigned short nCmd; //消息码
INT nServerId;//服务器Id
unsigned int nUserId; //UserID
INT nCmd;
INT nContractid;
INT nStep;
/*
nResult
0: 步骤已完成 或 奖励发放成功
1: 用户尚未在应用内创建角色
2用户尚未完成本步骤
3该步骤奖励已发放过
4发货失败
*/
INT nResult; //返回值
INT64 lOPPtr;//操作对象(客户端穿透服务器的数据)
}TASKMSG, *PTASKMSG;
#pragma pack(pop)
enum eAMCmdCode
{
/* 客户端发送 */
AMC_REGIST_CLIENT = 100, //客户端注册
//AMC_KEEP_ALIVE = 101, //客户端发送KeepAlive
AMC_QUERY_AMOUNT = 102, //客户端查询用户余额
AMC_COMSUME = 103, //客户端发送用户消费请求
AMC_TASK_SITUATION = 104, //客户端返回任务状态
/* 服务器回应 */
AMS_REGIST_CLIENT = 30100, //返回客户端注册成功(仅成功时返回)
//AMS_KEEP_ALIVE = 30101, //服务器发送KeepAlive
AMS_QUERY_AMOUNT = 30102, //服务器返回用户余额TAMOPMsgData.nAmount为余额
AMS_COMSUME = 30103, //服务器返回用户消费结果TAMOPMsgData.nAmount为消费结果0表示成功-1表示余额不足其他值表示其他错误
AMS_PAYSUCCESS = 30104, //服务器返回充值成功
AMS_TASK_SITUATION = 30105, //查询任务完成状态
AMS_INVALID_CMD = 65534, //无效的CMD
};
}

View File

@@ -0,0 +1,375 @@
#include "stdafx.h"
CAMServerSocket::CAMServerSocket(char *pszFileName):m_ConfigPath(pszFileName)
{
Config.ReadConfig(pszFileName);
SetServiceName("");
SetServiceHost("0.0.0.0");
SetServicePort(Config.m_nAmport);
Parser.CreateHttpServer("0.0.0.0",Config.m_nHttpport);
for (int i=0;i<Config.GetPlatFormCount();i++)
{
CProduct * pProduct = new CProduct(Config.GetPlatForm(i));
m_Products.add(pProduct);
}
}
CAMServerSocket::~CAMServerSocket(void)
{
for (INT_PTR i=m_Products.count()-1;i>-1;--i)
{
CProduct * pProduct = m_Products[i];
SafeDelete(pProduct);
}
m_Products.clear();
}
CProduct* CAMServerSocket::GetProduct(char* gName,char* spid)
{
for (int i=0;i<m_Products.count();i++)
{
CProduct * pProduct = m_Products[i];
if (strcmp(pProduct->GetGName(),gName) == 0 && strcmp(pProduct->GetSpid(),spid) == 0)
{
return pProduct;
}
}
return NULL;
}
char* CAMServerSocket::GetServerName()
{
return Config.m_sServerName;
}
CCustomServerClientSocket* CAMServerSocket::CreateClientSocket(SOCKET nSocket, PSOCKADDR_IN pAddrIn)
{
if (pAddrIn == NULL)
{
return NULL;
}
OutputMsg( rmTip, "接受客户端连接!<%s>",inet_ntoa(pAddrIn->sin_addr));
CAMClientSocket* pClientSocket = new CAMClientSocket(this,nSocket,pAddrIn);
if(pClientSocket)
{
m_AMClientList.add(pClientSocket);
}
return (CCustomServerClientSocket* )pClientSocket;
}
VOID CAMServerSocket::DestroyClientSocket(CCustomServerClientSocket *pClientSocket)
{
for (INT_PTR i=m_AMClientList.count()-1;i>-1;--i)
{
CCustomServerClientSocket* pSocket = (CCustomServerClientSocket*)m_AMClientList[i];
if (pSocket && pSocket == pClientSocket)
{
m_AMClientList.lock();
m_AMClientList.remove(i);
m_AMClientList.unlock();
break;
}
}
}
bool CAMServerSocket::CheckAuthorizationIP(long long * ipList, int size, char * ip )
{
//char *pStr = (char*)malloc(strlen(strIP)+3);
//_asncpytA(pStr,",");
//strcat(pStr,strIP);
//strcat(pStr,",");
//bool bResult = strstr(pStr,IP) != NULL;
//if (pStr)
//{
// free(pStr);
//}
//return bResult;
long long ipNum = inet_addr( ip ) ;
for( int i=0 ; i<size; ++i )
{
if( ipNum == ipList[i] )
return true ;
}
return false ;
}
CAMClientSocket* CAMServerSocket::GetSpidClientPro(char* spid)
{
for (int i=0;i<m_AMClientList.count();i++)
{
CAMClientSocket* pClient = m_AMClientList[i];
if (pClient && strcmp(pClient->GetSpid(),spid) == 0)
{
return pClient;
}
}
return NULL;
}
void CAMServerSocket::RefreshProduct()
{
Config.ReadConfig(m_ConfigPath.c_str());
for (int i=0; i < Config.GetPlatFormCount(); i++)
{
PlatForm* pPlatForm = Config.GetPlatForm(i);
CProduct * pProduct = GetProduct(pPlatForm->code,pPlatForm->spid);
if (!pProduct)
{
CProduct * pProduct = new CProduct(Config.GetPlatForm(i));
m_Products.add(pProduct);
OutputMsg( rmTip, "新增了platform[%s]",pPlatForm->spid);
}
else
{
pProduct->SetConfig(pPlatForm);
}
}
}
void CAMServerSocket::OutPutContractIdMap()
{
//CONTRACT_ID_MAP::iterator it;
//for( int i=1; i<6; ++i ) // 最多4个任务id
//{
// it = m_ContractIdMap.find(i);
// if( it != m_ContractIdMap.end() )
// {
// OutputMsg( rmTip, "ContractId=[%d], ContractStr=[%s]", it->first, it->second.c_str() );
// }
// else
// break;
//}
}
void CAMServerSocket::OutPutAllClientSocket()
{
}
#ifdef WIN32
//转换文字编码为UTF-8
size_t convertToUTF8(const char* lpMsg, const size_t nMsgLen, char *pBuffer, const size_t BufferLen)
{
WCHAR sWCBuf[4096];
DWORD cch = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, lpMsg, (int)nMsgLen, sWCBuf, ArrayCount(sWCBuf)-1);
if ( cch <= 0 )
cch = MultiByteToWideChar(CP_ACP, MB_ERR_INVALID_CHARS, lpMsg, (int)nMsgLen, sWCBuf, ArrayCount(sWCBuf)-1);
if ( cch > 0 )
{
cch = (DWORD)WideCharToMultiByte(CP_UTF8, 0, sWCBuf, cch, pBuffer, (int)(BufferLen-1), NULL, NULL);
if ( cch > 0 )
{
pBuffer[cch] = 0;
return cch;
}
}
return 0;
}
#endif
VOID CAMServerSocket::HandleHttpCommand(char *sDocument)
{
int nType = 0 ;
CProduct* pProduct =NULL;
// sDocument解析后会被销毁
if (!Parser.DocumentParser(sDocument))
{
Parser.SendResponse("Get Http Param Parser Error");
OutputMsg( rmError, "Get Http Param Parser Error");
goto ResultCode;
}
pProduct = GetProduct(Parser.m_GameName,Parser.m_Spid);
if (!pProduct)
{
Parser.SendResponse("Cannot Find Product");
OutputMsg( rmError, "Cannot Find Product");
goto ResultCode;
}
if (!CheckAuthorizationIP(pProduct->GetIPList(), pProduct->GetIPListSize(), Parser.GetClientIP() ))
{
Parser.SendResponse("UnAuthorized IP");
OutputMsg( rmError, "UnAuthorized IP");
goto ResultCode;
}
nType = 0 ;
if(strcmp(Parser.m_Interface,"pay") == 0)
nType = 1 ;
else if(strcmp(Parser.m_Interface,"awd") == 0)
nType = 2 ;
else if(strcmp(Parser.m_Interface,"pay2") == 0)
nType = 3 ;
//else if(strcmp(Parser.m_Interface,"market") == 0)
// nType = 4 ;
if ( nType == 0 )
{
Parser.SendResponse(Parser.m_Interface);
OutputMsg( rmError, "Invalid interface : [%s]", Parser.m_Interface);
goto ResultCode;
}
if( nType == 1 ||
nType == 2 ||
nType == 3 )
{
const char * opid = Parser.GetParamCharValue("opid");
const char * account = Parser.GetParamCharValue("account");
UINT money = Parser.GetParamIntValue("money");
if (money == 0)
{
Parser.SendResponse("Invalid Money Value");
OutputMsg( rmError, "Invalid Money Value");
goto ResultCode;
}
UINT server = Parser.GetParamIntValue("server");
UINT actorid = Parser.GetParamUIntValue("actorid");
int level = Parser.GetParamIntValue("level");
const char * channel = Parser.GetParamCharValue("channel");
const char * sign = Parser.GetParamCharValue("sign");
const char * actorname = Parser.GetParamCharValue("actorname");
double rmb = Parser.GetParamDoubleValue("ram");
char signCheck[200];
memset(signCheck,0,sizeof(signCheck));
if( nType == 1 || nType == 3 )
sprintf(signCheck,"opid=%s&account=%s&actorid=%u&money=%u&server=%u&key=%s",opid,account, actorid,money,server,pProduct->GetPayKey() );
else if( nType == 2 )
sprintf(signCheck,"opid=%s&account=%s&actorid=%u&money=%u&server=%u&key=%s",opid,account, actorid,money,server,pProduct->GetAwdKey() );
//char md5string[33];
//_asncpytA(md5string,MD5(signCheck).toString().data());
unsigned char md5string[64];
MD5_CTX ctx;
//使用 MD5加密玩家的密码
MD5Init(&ctx);
MD5Update(&ctx,(unsigned char *)signCheck, (unsigned int)strlen(signCheck) );
MD5Final(md5string,&ctx);
md5string[32]=0;
if (strcmp((char*)md5string,sign) != 0)
{
//if( nType == 2 )
//{
// char awdSign[200];
// memset(awdSign,0,sizeof(awdSign));
// sprintf(awdSign,"opid=%s&account=%s&money=%u&server=%u&key=%s",opid,account,money,server,pProduct->GetPayKey() );
// unsigned char md5str[64];
// MD5_CTX ctx;
// //使用 MD5加密玩家的密码
// MD5Init(&ctx);
// MD5Update(&ctx,(unsigned char *)awdSign, (unsigned int)strlen(awdSign) );
// MD5Final(md5str,&ctx);
// md5str[32]=0;
// if (strcmp((char*)md5str,sign) != 0)
// {
// Parser.SendResponse("Check Sign fail");
// OutputMsg( rmError, "Check Sign fail, the error sign:[%s], the upload opid=%s, account=%s, money=%u, server=%u, key=%s", sign, opid,account,money,server,pProduct->GetAwdKey() );
// goto ResultCode;
// }
//}
//else
//{
Parser.SendResponse("Check Sign fail");
if( nType == 2 )
OutputMsg( rmError, "Check Sign fail, the error sign:[%s], the upload opid=%s, account=%s, money=%u, server=%u, key=%s", sign, opid,account,money,server,pProduct->GetAwdKey() );
else
OutputMsg( rmError, "Check Sign fail, the error sign:[%s], the upload opid=%s, account=%s, money=%u, server=%u, key=%s", sign, opid,account,money,server,pProduct->GetPayKey() );
goto ResultCode;
//}
}
UINT UserId = 0;
OutputMsg( rmTip, _T("[%s] want to recharge [%u] YuanBao or HongLi"), account, money);
//char sMsgBuf[512];
//convertToUTF8(account, ArrayCount(sMsgBuf), sMsgBuf, ArrayCount(sMsgBuf));
//actorid 目前由后台php判断其合法性
int Result = pProduct->Pay(opid,account,money,rmb,server,nType,UserId,actorid,actorname,level,channel);
LPCSTR sResponse = "";
switch (Result)
{
case ERROR_NOT_CONNECT_DB:
{
sResponse = "Cannot Connect DB";
break;
}
case ERROR_QUERY_DB:
{
sResponse = "Query DB Error";
break;
}
case ERROR_NOT_REGDIST:
{
sResponse = "UnRegistered";
break;
}
case ERROR_NOTFIND_PRODUCT:
{
sResponse = "Cannot Find Product";
break;
}
case 0:
{
sResponse = "OK";// 0表示成功
break;
}
case 1:
{
sResponse = "UNE"; // 1表示无此账号
break;
}
case 2:
{
sResponse = "FA";// 2表示余额不足
break;
}
case 3:
{
sResponse = "DOI";// 3表示订单号重复
break;
}
default: sResponse = "UEE";// 异常出错
}
Parser.SendResponse(sResponse);
if( strncmp(sResponse,"OK", 2) == 0 )
{
if(nType == 1 || nType == 3 )
//OutputMsg( rmTip, _T("充值成功: %s充值了%u元宝"), account, money);
OutputMsg( rmTip, _T("recharge succeed, [%s] recharge [%u] YuanBao, UserID=[%u]"), account, money, UserId);
else
//OutputMsg( rmTip, _T("成功,发放%s红利%u"), account, money);
OutputMsg( rmTip, _T("a grant of HongLi succeed, [%s] get [%u] HongLi, UserID=[%u]"), account, money, UserId);
}
else
{
if(nType == 1 || nType == 3 )
//OutputMsg( rmError, _T("[%s]充值失败,错误:[%s]"), account, sResponse);
OutputMsg( rmError, _T("[%s] recharge failed, errmsg: [%s], UserID=[%u]"), account, sResponse, UserId);
else
//OutputMsg( rmError, _T("%s发放红利失败错误[%s]"), account, sResponse);
OutputMsg( rmError, _T("a grant of HongLi for [%s] failed , errmsg: [%s], UserID=[%u]"), account, sResponse, UserId );
}
if (Result == 0)
{
CAMClientSocket* pClient = GetSpidClientPro(Parser.m_Spid);
if (pClient)
{
money = pProduct->QueryAmount(UserId, actorid);
pClient->SendPaySucceed(server,UserId, actorid, money);
}
}
}
ResultCode:
Parser.CloseHttpConnet();
}
VOID CAMServerSocket::SingleRun()
{
ServerInherited::SingleRun();
char* sDocument = Parser.HttpCommandGet();
if (strlen(sDocument) > 0)
{
OutputMsg( rmTip, _T("%s"), HttpUtility::URLDecode(sDocument).c_str() );
HandleHttpCommand(sDocument);
}
}

View File

@@ -0,0 +1,45 @@
#pragma once
class CCustomServerSocket;
class CSQLConenction;
class CSrvConfig;
class CAMClientSocket;
class CProduct;
using namespace wylib::sync::lock;
using namespace wylib::container;
//typedef std::map<UINT, string > CONTRACT_ID_MAP;
class CAMServerSocket:
public CCustomServerSocket
{
public:
typedef CCustomServerSocket ServerInherited ;
CAMServerSocket(char *pszFileName);
~CAMServerSocket(void);
CProduct* GetProduct(char* gName,char* spid);
HttpParamParser& GetParamParser(){ return Parser; };
void OutPutContractIdMap();
void RefreshProduct();
void OutPutAllClientSocket();
char* GetServerName();
protected:
virtual CCustomServerClientSocket* CreateClientSocket(SOCKET nSocket, PSOCKADDR_IN pAddrIn);
virtual VOID DestroyClientSocket(CCustomServerClientSocket *pClientSocket);
VOID SingleRun();
VOID HandleHttpCommand(char *sDocument);
private:
bool CheckAuthorizationIP(long long * ipList, int size, char * ip );
CAMClientSocket* GetSpidClientPro(char* spid);
CQueueList<CAMClientSocket*> m_AMClientList; //客户端列表
CBaseList<CProduct*> m_Products; //产品列表
CSrvConfig Config; //配置文件
HttpParamParser Parser; //HTTPServer
string m_ConfigPath;
//CONTRACT_ID_MAP m_ContractIdMap;
};

View File

@@ -0,0 +1,71 @@
cmake_minimum_required(VERSION 2.6)
project(amserver)
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( CMAKE_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../sdk) # include 文件夹
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_INCLUDE_DIR}/public
${CMAKE_INCLUDE_DIR}/system
${CMAKE_INCLUDE_DIR}/utils
${CMAKE_INCLUDE_DIR}/commonLib/include
${CMAKE_INCLUDE_DIR}/commonLib/def
${CMAKE_INCLUDE_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 amserver_d )
else()
set( EXE_NAME amserver_r )
endif()
SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/../../build/AMServer)
add_executable(${EXE_NAME} ${sources1} ${sources2} ${sources3} )
include(../common/cmake/libs.cmake)

View File

@@ -0,0 +1,253 @@
#include "stdafx.h"
#define MAX_PARAM_COUNT 20
#define BUFSIZE 1024
static char sName[64];
void HttpParamParser::CreateHttpServer(char* sAddr,int nPort)
{
m_ServerSocket = socket(AF_INET,SOCK_STREAM,0);
m_AddrServer.sin_addr.s_addr = inet_addr(sAddr);
m_AddrServer.sin_family = AF_INET;
m_AddrServer.sin_port = htons(nPort);
bind(m_ServerSocket,(SOCKADDR*)&m_AddrServer,sizeof(SOCKADDR));
listen(m_ServerSocket,10);
FD_ZERO(&m_fdSocket);
FD_SET(m_ServerSocket,&m_fdSocket);
}
char* HttpParamParser::HttpCommandGet()
{
struct timeval timeout={0,200000}; //超时时间200豪秒
fd_set fdRead = m_fdSocket;
#ifdef WIN32
int nRet = select(NULL,&fdRead,NULL,NULL,&timeout);
#else
int nRet = select(m_ServerSocket+1,&fdRead,NULL,NULL,&timeout);
#endif
if (nRet <= 0)
{
return "";
}
if(FD_ISSET(m_ServerSocket,&fdRead))
{
int len=sizeof(SOCKADDR);
#ifdef WIN32
m_ClientSocket = accept(m_ServerSocket,(SOCKADDR*)(&m_AddrClient),&len);
#else
m_ClientSocket = accept(m_ServerSocket,(SOCKADDR*)(&m_AddrClient),(socklen_t*)&len);
#endif
BOOL bReuseaddr=FALSE;
setsockopt(m_ClientSocket, SOL_SOCKET ,SO_REUSEADDR,(const char*)&bReuseaddr,sizeof(BOOL));
m_ClientIP = inet_ntoa(m_AddrClient.sin_addr);
char * recvBuf = (char *)malloc(BUFSIZE*sizeof(char));
memset(recvBuf, 0, BUFSIZE);
recv(m_ClientSocket,recvBuf,BUFSIZE,0);
return recvBuf;
}
return "";
}
void HttpParamParser::CloseHttpConnet()
{
closesocket(m_ClientSocket);
}
void HttpParamParser::SendResponse(LPCSTR sContent)
{
char sendBuf[1024];
memset(sendBuf, 0, 1024);
strcat(sendBuf, "HTTP/1.1 200\r\n");
strcat(sendBuf, "Server: AMServer\r\n");
strcat(sendBuf, "Content-Type:text/html;charset=utf8\r\n\r\n");
strcat(sendBuf, sContent);
size_t len = strlen(sendBuf);
send(m_ClientSocket,sendBuf,(int)len,(int)0);
}
void HttpParamParser::SendResponse(SOCKET nsocket, LPCSTR sContent)
{
char sendBuf[1024];
memset(sendBuf, 0, 1024);
strcat(sendBuf, "HTTP/1.1 200\r\n");
strcat(sendBuf, "Server: AMServer\r\n");
strcat(sendBuf, "Content-Type:text/html;charset=utf8\r\n\r\n");
strcat(sendBuf, sContent);
size_t len = strlen(sendBuf);
::send(nsocket, sendBuf, (int)len, 0);
/*
int cnt = 0;
int succ = 0;
while( succ < len )
{
cnt++;
if( cnt > 3 )
return ;
int ret = ::send(nsocket, sendBuf+succ, len-succ, 0);
if( ret <= 0 )
{
#ifdef WIN32
int nError = WSAGetLastError();
if( nError == WSAETIMEDOUT || nError == WSAEWOULDBLOCK ) continue;
OutputMsg( rmError, _T("send error = [%d]"), nError );
return ;
#else
int nError = GetLastError();
if( nError == ETIMEDOUT || nError == EAGAIN || nError == 0 ) continue;
OutputMsg( rmError, _T("send error = [%d] msg = [%s]"), nError, strerror(nError) );
return ;
#endif
}
succ += ret;
}
*/
}
bool HttpParamParser::DocumentParser(char * sDocument)
{
EnterCriticalSection( &m_ParseLock );
if (strlen(sDocument) == 0) return false;
char * pStr = strtok(sDocument," ");
char * s = strtok(NULL," ");
const char *d = "/?&";
char *p;
p = strtok(s,d);
int iCount = 0;
int nIndex = 0;
while(p)
{
switch (iCount)
{
case 0:
{
_asncpytA(m_GameName,p); // djrm
break;
}
case 1:
{
_asncpytA(m_Spid,p); // 37w
break;
}
case 2:
{
_asncpytA(m_Interface,p); // pay
break;
}
}
if (iCount > 2)
{
size_t value_len = 0 ;
size_t name_len = 0;
memset(sName,0,sizeof(sName));
char* sValue = strstr(p, "=");
if (sValue && strlen(sValue)> 1)
{
strncpy(sName,p,sValue-p);
sValue++;
name_len = strlen(sName);
name_len = (name_len>63)?63:name_len ;
if (name_len >= 1)
{
strncpy(Params[nIndex].sName,sName,name_len);
Params[nIndex].sName[name_len] = '\0' ;
value_len = strlen(sValue) ;
value_len = (value_len>255)?255:value_len ;
strncpy(Params[nIndex].sValue,sValue,value_len);
Params[nIndex].sValue[value_len] = '\0' ;
nIndex++;
}
}
if (nIndex >= MAX_PARAM_NUM) break;
}
iCount++;
p=strtok(NULL,d);
}
for (int i=0;i<iCount;i++)
{
if(strcmp(Params[i].sName,"account") == 0 || strcmp(Params[i].sName,"channel") == 0 ||strcmp(Params[i].sName,"actorname") == 0)
{
string str = HttpUtility::URLDecode(Params[i].sValue);
str.copy(Params[i].sValue, str.length(), 0);
Params[i].sValue[str.length()] = 0;
}
}
free(sDocument) ;
LeaveCriticalSection( &m_ParseLock );
return true;
}
int StrToInt(char* str)
{
size_t len = strlen(str) ;
int result = 0 ;
for(int i=0; i<len; i++)
{
result = result * 10 ;
result += (int)(str[i]-'0') ;
}
return result ;
}
unsigned int HttpParamParser::GetParamUIntValue(char* sName)
{
for (int i=0;i<MAX_PARAM_NUM;i++)
{
if (strcmp(Params[i].sName,sName) == 0)
{
return (unsigned int)_atoi64(Params[i].sValue);
}
}
return 0;
}
int HttpParamParser::GetParamIntValue(char* sName)
{
for (int i=0;i<MAX_PARAM_NUM;i++)
{
if (strcmp(Params[i].sName,sName) == 0)
{
return atoi(Params[i].sValue);
}
}
return 0;
}
const char* HttpParamParser::GetParamCharValue(char* sName)
{
for (int i=0;i<MAX_PARAM_NUM;i++)
{
if (strcmp(Params[i].sName,sName) == 0)
{
//if(strcmp(Params[i].sName,"account") == 0)
//{
// return HttpUtility::URLDecode(Params[i].sValue).c_str();
//}
//else
return Params[i].sValue;
}
}
return "";
}
double HttpParamParser::GetParamDoubleValue(char* sName)
{
for (int i=0;i<MAX_PARAM_NUM;i++)
{
if (strcmp(Params[i].sName,sName) == 0)
{
double dValue = 0;
_stscanf(Params[i].sValue, _T("%lf"), &dValue) ;
int iTemp = (int)(dValue * 10);
dValue = double(iTemp) / 10 ;
return dValue;
}
}
return 0;
}

View File

@@ -0,0 +1,60 @@
#pragma once
/*
HTTP参数分析类
*/
class CAMServerSocket;
typedef struct tagHttpParam
{
char sName[64]; //参数名称
char sValue[256]; //参数值
tagHttpParam()
{
memset(this, 0, sizeof(*this));
}
}HTTPPARAM;
const int MAX_PARAM_NUM = 20;
class HttpParamParser
{
public:
HttpParamParser(void)
{
memset(m_GameName,0,sizeof(m_GameName));
memset(m_Spid,0,sizeof(m_Spid));
memset(m_Interface,0,sizeof(m_Interface));
InitializeCriticalSection( &m_ParseLock );
};
~HttpParamParser(void){DeleteCriticalSection( &m_ParseLock );};
public:
bool DocumentParser(char * sDocument);
unsigned int GetParamUIntValue(char* sName);
int GetParamIntValue(char* sName);
const char* GetParamCharValue(char* sName);
double GetParamDoubleValue(char* sName);
void CreateHttpServer(char* sAddr,int nPort);
char* HttpCommandGet();
void CloseHttpConnet();
void SendResponse(LPCSTR sContent);
void SendResponse(SOCKET nsocket, LPCSTR sContent);
char m_GameName[20]; //游戏英文缩写
char m_Spid[20]; //运营商英文缩写
char m_Interface[20]; //接口名称
inline char * GetClientIP() { return m_ClientIP;}
inline SOCKET GetServerSocket() { return m_ServerSocket; }
inline SOCKET GetClientSocket() { return m_ClientSocket; }
private:
HTTPPARAM Params[MAX_PARAM_NUM]; //参数
SOCKET m_ServerSocket;
SOCKET m_ClientSocket;
fd_set m_fdSocket;
SOCKADDR_IN m_AddrClient;
SOCKADDR_IN m_AddrServer;
RTL_CRITICAL_SECTION m_ParseLock;
char* m_ClientIP;
};

174
server/AmServer/Product.cpp Normal file
View File

@@ -0,0 +1,174 @@
#include "stdafx.h"
CProduct::CProduct(PlatForm* config)
{
SetConfig(config);
if (!SetDBConnection())
{
OutputMsg( rmError, _T("连接MYSQL数据库(%s:%d)失败"),config->db,config->port);
bAMEngineStartSucceed = false;
}
else
{
OutputMsg( rmTip, _T("连接MYSQL数据库(%s:%d)成功"),config->db,config->port);
}
}
void CProduct::SetConfig(PlatForm* config)
{
m_Config = config;
_asncpy(m_spid,m_Config->spid);
_asncpy(m_code,m_Config->code);
}
BOOL CProduct::CheckConnection()
{
SYSTEMTIME m_CurSysTime;
GetLocalTime(&m_CurSysTime);
CMiniDateTime CurMiniDateTime;
CurMiniDateTime = CurMiniDateTime.encode(m_CurSysTime);
BOOL boConnected = m_Mysql.Connected();
if (!boConnected || CurMiniDateTime.tv - m_ConnectMiniDateTime.tv > 60*60)
{
m_Mysql.Disconnect();
boConnected = m_Mysql.Connect();
if( boConnected )
{
if( mysql_set_character_set(m_Mysql.GetMySql(),m_Config->bianma) )
OutputMsg( rmError, _T("设置utf8编码出错 !!!") );
}
}
return boConnected;
}
BOOL CProduct::SetDBConnection()
{
m_Mysql.SetServerHost(m_Config->host);
m_Mysql.SetServerPort(m_Config->port);
m_Mysql.SetDataBaseName(m_Config->db);
m_Mysql.SetUserName(m_Config->user);
m_Mysql.SetPassWord(m_Config->pass);
//多个客户端连接,数据库操作类要加锁
//m_Mysql.SetMultiThread(TRUE);
m_Mysql.SetConnectionFlags(CLIENT_FOUND_ROWS | CLIENT_MULTI_RESULTS);
BOOL boConnected = m_Mysql.Connect();
if (boConnected)
{
if( mysql_set_character_set(m_Mysql.GetMySql(),m_Config->bianma) )
OutputMsg( rmError, _T("设置utf8编码出错 !!!") );
OutputMsg(rmTip, _T("mysql connection character set: %s"), mysql_character_set_name(m_Mysql.GetMySql()));
SYSTEMTIME m_CurSysTime;
GetLocalTime(&m_CurSysTime);
m_ConnectMiniDateTime = m_ConnectMiniDateTime.encode(m_CurSysTime);
}
return boConnected;
}
int CProduct::GetContractID(const char * sContractID )
{
size_t len = strlen(sContractID);
if( len <= 0 ) return 0;
for(int i=0; i<m_Config->taskcount; ++i)
{
if(strncmp(m_Config->constractid[i], sContractID, len) == 0 )
{
return (i+1);
}
}
return 0;
}
int CProduct::Pay( const char* sOPID,const char* sAccount,UINT nMoney,double dRmb,UINT ServerIndex,UINT nType,UINT &uUserId,UINT nActorId, const char * actorname, int level, const char * channel)
{
if (!CheckConnection())
{
return ERROR_NOT_CONNECT_DB;
}
int nResult = ERROR_QUERY_DB;
m_UserDBLock.Lock();
int nErrorId = m_Mysql.Query(sPay_SQL, sOPID,sAccount,nMoney,dRmb,ServerIndex,m_Config->spid,nType, nActorId, actorname, level,channel);
if (!nErrorId)
{
MYSQL_ROW pRow = m_Mysql.CurrentRow();
if (pRow)
{
sscanf(pRow[0], "%d", &nResult);
if( pRow[1] )
sscanf(pRow[1], "%u", &uUserId);
}
m_Mysql.ResetQuery();
}
m_UserDBLock.Unlock();
return nResult;
}
int CProduct::QueryAmount(UINT uUserId, UINT& nActorId)
{
if (!CheckConnection())
{
return ERROR_NOT_CONNECT_DB;
}
int nResult = ERROR_QUERY_DB;
m_UserDBLock.Lock();
int nErrorId = m_Mysql.Query(sQuery_SQL, uUserId, 0, nActorId);
if (!nErrorId)
{
MYSQL_ROW pRow = m_Mysql.CurrentRow();
if (pRow)
{
//查角色或账号元宝nActorId > 0,则为角色元宝nActorId=0则为账号元宝
sscanf(pRow[0], "%d", &nResult);
sscanf(pRow[1], "%d", &nActorId);
}
m_Mysql.ResetQuery();
}
else
{
OutputMsg( rmError,sError_Query_SQL, uUserId, 0 );
}
m_UserDBLock.Unlock();
return nResult;
}
int CProduct::Consume(UINT uUserId,UINT nAmount,char* sCharName,UINT nServerId, UINT nActorId, BYTE nLevel)
{
if (!CheckConnection())
{
return ERROR_NOT_CONNECT_DB;
}
int nResult = ERROR_QUERY_DB;
m_UserDBLock.Lock();
int nErrorId = m_Mysql.Query(sConsume_SQL, uUserId, nAmount, nActorId,sCharName,nServerId, nLevel);
if (!nErrorId)
{
MYSQL_ROW pRow = m_Mysql.CurrentRow();
if (pRow)
{
int nTmp = -1;
sscanf(pRow[0], "%d", &nTmp);
//int nRowCount= m_Mysql.GetFieldCount();
//for(int i=0; i< nRowCount; i++)
//{
// OutputMsg( rmTip, "param [%d =%d]", i ,atoi(pRow[i])) ;
//}
if (nTmp == 0)
{
sscanf(pRow[1], "%d", &nResult);
}
else if(nTmp == -1 )
{
OutputMsg( rmTip, "余额不足" ) ;
}
}
m_Mysql.ResetQuery();
}
else
{
OutputMsg( rmError,_T(sError_Consume_SQL), uUserId, nAmount,sCharName,nServerId );
}
m_UserDBLock.Unlock();
return nResult;
}

39
server/AmServer/Product.h Normal file
View File

@@ -0,0 +1,39 @@
#pragma once
class CProduct
{
public:
CProduct(PlatForm * config);
~CProduct(void){}
int Pay(const char* sOPID, const char* sAccount,UINT nMoney,double dRmb,UINT ServerIndex,UINT nType,UINT &uUserId,UINT nActorId, const char * actorname, int level, const char* channel);
int QueryAmount(UINT uUserId, UINT& nActorId);
int Consume(UINT uUserId,UINT nAmount,char* sCharName,UINT nServerId, UINT nActorId, BYTE nLevel);
void SetConfig(PlatForm* config);
inline char* GetGName() { return m_code;}
inline char* GetSpid() { return m_spid;}
inline LPCSTR GetAuthorizationIP() { return m_Config->db;}
inline char* GetPayKey() { return m_Config->paykey;}
inline char* GetAwdKey() { return m_Config->awdkey;}
inline int GetIPListSize() { return m_Config->hostcount;}
inline long long * GetIPList() { return m_Config->hosts;}
int GetContractID(const char * sContractID );
private:
BOOL CheckConnection();
BOOL SetDBConnection();
CSQLConenction m_Mysql;
CMiniDateTime m_ConnectMiniDateTime;
CCSLock m_UserDBLock;
char m_spid[8];
char m_code[8];
PlatForm * m_Config;
};
static LPCTSTR sPay_SQL = "call UserPayment(\"%s\", \"%s\", %d, %f, %d, \"%s\", %d, %u, \"%s\", %d, \"%s\")";
static LPCTSTR sQuery_SQL = "call QueryAmount(%u,%u,%u)";
static LPCTSTR sConsume_SQL = "call Consume(%u,%u,%u,\"%s\", %u,%d)";
static LPCTSTR sError_Pay_SQL = "Error happen when call UserPayment(\"%s\", \"%s\", %d, %f, %d, \"%s\", %d)";
static LPCTSTR sError_Query_SQL = "Error happen when call QueryAmount(%u,%u)";
static LPCTSTR sError_Consume_SQL = "Error happen when call Consume(%u,%u,\"%s\", %u)";

View File

@@ -0,0 +1,262 @@
#include "stdafx.h"
#include "SrvConfig.h"
using namespace wylib::stream;
CSrvConfig::~CSrvConfig(void)
{
m_platforms.empty();
}
bool CSrvConfig::ReadConfig(const char *pszFileName)
{
//try
//{
// CMemoryStream ms;
// ms.loadFromFile("AMServer.txt");
// setScript((LPCSTR)ms.getMemory());
// if ( openGlobalTable("AMServer"))
// {
// getFieldStringBuffer(("ServiceName"), m_ServiceName,sizeof(m_ServiceName));
// if ( openFieldTable("Products"))
// {
// if (enumTableFirst())
// {
// do
// {
// PRODUCTCONF Product;
// getFieldStringBuffer(("Name"), Product.sName,sizeof(Product.sName));
// getFieldStringBuffer(("Spid"), Product.sSpid,sizeof(Product.sSpid));
// getFieldStringBuffer(("Host"), Product.sHost,sizeof(Product.sHost));
// Product.nPort = getFieldInt("Port");
// getFieldStringBuffer(("DBName"), Product.sDBName,sizeof(Product.sDBName));
// getFieldStringBuffer(("DBUser"), Product.sDBUser,sizeof(Product.sDBUser));
// char szTemp[100];
// getFieldStringBuffer(("DBPass"), szTemp,sizeof(szTemp));
// DecryptPassword(Product.sDBPass,sizeof(Product.sDBPass),szTemp,"123456abc123456a");
// memset(szTemp,0,sizeof(szTemp));
// getFieldStringBuffer(("PayKey"), szTemp,sizeof(szTemp));
// DecryptPassword(Product.sPayKey,sizeof(Product.sPayKey),szTemp,"123456abc123456a");
// Product.sAuthorizationIP = getFieldString("AuthorizationIP");
// m_ProductList.add(Product);
//
// } while (enumTableNext());
// }
// closeTable();//DB
// }
// if ( openFieldTable(("Server")))
// {
// if ( openFieldTable(("HttpServer")))
// {
// getFieldStringBuffer(("BindAddress"), m_HttpServerConf.sAddr,sizeof(m_HttpServerConf.sAddr));
// m_HttpServerConf.nPort = getFieldInt("Port");
// closeTable();
// }
// if ( openFieldTable(("AmountServer")))
// {
// getFieldStringBuffer(("BindAddress"), m_AmountServerConf.sAddr,sizeof(m_AmountServerConf.sAddr));
// m_AmountServerConf.nPort = getFieldInt("Port");
// closeTable();
// }
// closeTable();//DB
// }
// closeTable();//关闭Config
// }
//}
//catch(RefString &s)
//{
// OutputMsg( rmNormal, s.rawStr() );
//}
//catch(...)
//{
// OutputMsg( rmNormal, _T("unexpected error on load config") );
//}
OutputMsg(rmTip,"load file from %s",pszFileName);
bool result = false;
wylib::stream::CMemoryStream ms;
try
{
//加载配置文件
if ( ms.loadFromFile(pszFileName) <= 0 )
{
showErrorFormat(_T("unabled to load config from %s"), pszFileName);
bAMEngineStartSucceed = false;
return false;
}
setScript((LPCSTR)ms.getMemory());
//读取配置文件
if ( !openGlobalTable("amconfig") )
{
OutputMsg(rmWaning,"No table amconfig found in config");
bAMEngineStartSucceed = false;
throw ;
}
int nValue = getFieldInt("httpport");
m_nHttpport = nValue; //设置http端口
nValue = getFieldInt("amport");
m_nAmport = nValue ; //设置am端口
strncpy(m_sServerName,getFieldString("servername",""),sizeof(m_sServerName));
if (!openFieldTable("platform"))
{
OutputMsg(rmWaning,"No table platform found in config");
bAMEngineStartSucceed = false;
throw ;
}
m_platforms.clear();
size_t nCount = lua_objlen(m_pLua,-1);
m_platforms.reserve(nCount); //保留这么多个数
if (enumTableFirst())
{
int i=0;
do
{
PlatForm config;
strncpy(config.spid,getFieldString("spid",""),sizeof(config.spid));
strncpy(config.code,getFieldString("code",""),sizeof(config.code));
strncpy(config.db,getFieldString("db",""),sizeof(config.db));
strncpy(config.bianma,getFieldString("bianma","latin1"),sizeof(config.bianma));
strncpy(config.host,getFieldString("host",""),sizeof(config.host));
char szTemp[128] ;
char keykey[17] ;
char passkey[17] ;
keykey[0]='z',keykey[1]='*',keykey[6]='@',keykey[2]='i',keykey[7]='c',keykey[12]='%',keykey[3]='v',keykey[14]='1',
keykey[11]='5',keykey[13]='9',keykey[8]='c',keykey[9]='3',keykey[15]='3',keykey[4]='l',keykey[5]='@',keykey[10]='6',keykey[16]=0 ;
passkey[0]='u',passkey[1]='a',passkey[6]='z',passkey[2]='9',passkey[7]='3',passkey[12]='%',passkey[3]='k',passkey[14]='@',
passkey[11]='&',passkey[13]='4',passkey[8]='g',passkey[9]='v',passkey[15]='8',passkey[4]='2',passkey[5]='@',passkey[10]='!',passkey[16]=0;
getFieldStringBuffer(("user"), config.user,sizeof(config.user));
//DecryptPassword(config.user,sizeof(config.user),szTemp,passkey);
//memset(szTemp,0,sizeof(szTemp));
//EncryptPassword(szTemp, sizeof(szTemp), "cqmaster", passkey);
//DecryptPassword(szTemp,sizeof(szTemp),tmp,passkey);
memset(szTemp,0,sizeof(szTemp));
getFieldStringBuffer(("pass"), config.pass,sizeof(szTemp));
//DecryptPassword(config.pass,sizeof(config.pass),szTemp,passkey);
memset(szTemp,0,sizeof(szTemp));
getFieldStringBuffer(("paykey"), szTemp,sizeof(szTemp));
DecryptPassword(config.paykey,sizeof(config.paykey),szTemp,keykey);
memset(szTemp,0,sizeof(szTemp));
getFieldStringBuffer(("awdkey"), szTemp,sizeof(szTemp));
DecryptPassword(config.awdkey,sizeof(config.awdkey),szTemp,keykey);
memset(szTemp,0,sizeof(szTemp));
getFieldStringBuffer(("awdkey"), szTemp,sizeof(szTemp));
DecryptPassword(config.awdkey,sizeof(config.awdkey),szTemp,keykey);
//memset(szTemp,0,sizeof(szTemp));
//char tmp[128];
//memset(tmp,0,sizeof(tmp));
//EncryptPassword(tmp, sizeof(tmp), "1101994183T320140912113752", keykey);
//DecryptPassword(szTemp,sizeof(szTemp),tmp,keykey);
//memset(tmp,0,sizeof(tmp));
//EncryptPassword(tmp, sizeof(tmp), "1101994183T320140912193716", keykey);
//DecryptPassword(szTemp,sizeof(szTemp),tmp,keykey);
//strncpy(config.pass,getFieldString("pass",""),sizeof(config.pass));
//strncpy(config.paykey,getFieldString("paykey",""),sizeof(config.paykey));
//strncpy(config.awdkey,getFieldString("awdkey",""),sizeof(config.awdkey));
config.codeid = getFieldInt("codeid");
config.port = getFieldInt("port");
if (openFieldTable("hosts"))
{
int j=0;
if (enumTableFirst())
{
do
{
long long nHost = inet_addr (getFieldString(NULL) );
bool flag = true ;
for( int k=0; k<j; ++k )
{
if( nHost == config.hosts[k] )
{
flag = false ;
break ;
}
}
if(j < MAX_HOST_COUNT && flag )
{
config.hosts[j]= nHost;
j++;
}
if( j >= MAX_HOST_COUNT )
break ;
} while (enumTableNext());
}
config.hostcount = j;
closeTable();
}
if (feildTableExists("contractid") && openFieldTable("contractid"))
{
int j=0;
if (enumTableFirst())
{
do
{
memset(szTemp,0,sizeof(szTemp));
strcpy(szTemp, getFieldString(NULL));
DecryptPassword(config.constractid[j],sizeof(config.constractid[j]),szTemp,keykey);
j++;
if( j >= MAX_TAST_COUNT )
break ;
} while (enumTableNext());
}
config.taskcount = j;
closeTable();
}
else
{
for(int j=0; j<MAX_TAST_COUNT; ++j)
{
config.constractid[j][0] = 0;
}
config.taskcount = 0;
}
m_platforms.add(config);
i++;
} while (enumTableNext());
}
closeTable();
closeTable();
}
catch (RefString& s)
{
OutputMsg( rmError, (LPCTSTR)s );
}
catch (...)
{
OutputMsg( rmError, _T("unexpected error on load config") );
}
return result;
}
void CSrvConfig::ShowError(const LPCTSTR sError)
{
m_sLastErrDesc = sError;
RefString sErr;
sErr = _T("[Configuration Error]");
sErr += sError;
//集中处理错误为了简单起见此处直接抛出异常。异常会在readConfig中被捕获从而立刻跳出对配置的循环读取。
throw sErr;
}
PlatForm * CSrvConfig::GetPlatForm(int nIndex)
{
if (nIndex >= 0 && nIndex < m_platforms.count())
{
return &m_platforms[nIndex];
}
return NULL;
}

View File

@@ -0,0 +1,85 @@
#ifndef _SRV_CONFIG_H_
#define _SRV_CONFIG_H_
////服务器端口地址等相关配置
//typedef struct tagServerConf
//{
// char sAddr[20];
// int nPort;
// tagServerConf()
// {
// memset(this, 0, sizeof(*this));
// }
//} SERVERCONF,*PSERVERCONF;
//
//typedef struct tagProductConf{
// char sName[20];
// char sSpid[20];
// char sHost[20];
// int nPort;
// char sDBName[100];
// char sDBUser[100];
// char sDBPass[100];
// char sPayKey[100];
// LPCSTR sAuthorizationIP;
// tagProductConf()
// {
// memset(this, 0, sizeof(*this));
// }
//}PRODUCTCONF,*PPRODUCTCONF;
const static int MAX_HOST_COUNT =32; ///允许的ip列表最多32个
const static int MAX_TAST_COUNT = 4;
//平台的信息
struct PlatForm
{
char spid[8]; //平台的spid
char code[8]; //游戏的充值代码
char db[32]; //数据库名字
char bianma[12]; //连接mysql编码
char host[128]; //数据库的ip
char user[128]; //加密用户名
char pass[128]; //加密密码
char paykey[128]; //充值key
char awdkey[128]; //红利key
long long hosts[MAX_HOST_COUNT]; //允许的ip列表最多32个
int codeid; //游戏的代码
int port; //数据库的端口
int hostcount; //实际ip的数目
int taskcount; //任务个数
char constractid[MAX_TAST_COUNT][128]; //任务集市id
PlatForm()
{
memset(this,0,sizeof(*this)); //可以清0的
}
};
class CSrvConfig:
public CCustomLuaConfig
{
public:
CSrvConfig(void)
{
//memset(m_ServiceName,0,sizeof(m_ServiceName));
};
~CSrvConfig(void);
public:
bool ReadConfig(const char *pszFileName);
inline INT_PTR GetPlatFormCount() { return m_platforms.count();}
PlatForm * GetPlatForm(int nIndex);
//char m_ServiceName[20];
//SERVERCONF m_HttpServerConf;
//SERVERCONF m_AmountServerConf;
int m_nHttpport; //绑定的http回调的端口
int m_nAmport; //连接地址
char m_sServerName[128]; //服务器名称
protected:
void ShowError(const LPCTSTR sError);
private:
//CBaseList<PRODUCTCONF> m_ProductList;
CBaseList<PlatForm> m_platforms; //平台的列表,初始化的时候使用
};
#endif

14
server/AmServer/build.sh Normal file
View File

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

209
server/AmServer/main.cpp Normal file
View File

@@ -0,0 +1,209 @@
// AMServer.cpp : Defines the entry point for the console application.
//
#include <iostream>
#include <fstream>
#include "stdafx.h"
#include "utf8_output.h"
#ifdef WIN32
#include <dbghelp.h>
#include <mbctype.h>
#include <conio.h>
#endif
#include "PathThreadLocale.h"
#include <string>
#include <vector>
#include <signal.h>
#include <iostream>
using namespace std;
#define BUFSIZE 1024
extern const TCHAR szExceptionDumpFile[] = _T("./AMServer.dmp");
#define DBEGN_KN_VERION MAKEFOURCC(17, 3, 28, 1)
bool AMEngineRunning = true ;
bool bAMEngineStartSucceed = true;
#ifndef WIN32
void changemode(int dir)
{
static struct termios oldt, newt;
if ( dir == 1 )
{
tcgetattr( STDIN_FILENO, &oldt);
newt = oldt;
newt.c_lflag &= ~( ICANON | ECHO );
tcsetattr( STDIN_FILENO, TCSANOW, &newt);
}
else
tcsetattr( STDIN_FILENO, TCSANOW, &oldt);
}
int _kbhit(void)
{
struct termios oldt, newt;
int ch;
int oldf;
tcgetattr(STDIN_FILENO, &oldt);
newt = oldt;
newt.c_lflag &= ~(ICANON | ECHO);
tcsetattr(STDIN_FILENO, TCSANOW, &newt);
oldf = fcntl(STDIN_FILENO, F_GETFL, 0);
fcntl(STDIN_FILENO, F_SETFL, oldf | O_NONBLOCK);
ch = getchar();
tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
fcntl(STDIN_FILENO, F_SETFL, oldf);
if(ch != EOF)
{
ungetc(ch, stdin);
return 1;
}
return 0;
}
static void signal_handler(int sig_num)
{
if( sig_num == SIGHUP ||
sig_num == SIGINT ||
sig_num == SIGTERM )
{
OutputMsg( rmTip, _T("正在退出...") );
AMEngineRunning = false;
}
}
#endif
void ServerCreate(int argc, char ** argv)
{
#ifdef WIN32
SetUnhandledExceptionFilter( DefaultUnHandleExceptionFilter );
#else
(void)signal(SIGHUP, SIG_IGN);
(void)signal(SIGINT, signal_handler);
(void)signal(SIGTERM, signal_handler);
#endif
InitDefMsgOut();
#ifdef WIN32
CCustomWorkSocket::InitSocketLib();
_setmbcp(_MB_CP_SBCS);
//★关键★ 设置"C"locale视所有字符均作为单字节字符以便同时支持UTF8以及MBCS
InstallThreadLocalePath("C");
SetCurrentDirectory("./");
#else
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
char *pBuff = (char*)malloc(256);
in_addr ia;
ia.s_addr = DBEGN_KN_VERION;
strcpy(pBuff,_T("AM充值服务"));
strcat(pBuff,"-V");
strcat(pBuff,inet_ntoa(ia));
SetConsoleTitle(pBuff);
free(pBuff);
//OutputMsg( rmTip, _T("AM充值服务-V%s"), inet_ntoa(ia1) );
}
void ServerDestroy()
{
#ifdef WIN32
CCustomWorkSocket::UnintSocketLib();
#endif
UninitDefMsgOut();
}
int main(int argc, char** argv)
{
ServerCreate( argc, argv );
if (!FDOP::IsDirectory(_T("log")))
{
FDOP::DeepCreateDirectory(_T("log"));
}
CFileLogger flog(_T("./log/AMServer_%s.log.txt"), getCurrentTimeDesc());
#ifdef WIN32
//flog.SetNeedOutput(true);
#else
if (argc >=2)
{
// flog.SetNeedOutput(true);
}
else
{
// flog.SetNeedOutput(false);
}
#endif
char *pFileName =NULL;
if(argc >=2)
{
pFileName = argv[1];
}else
{
pFileName="AMServerLinux.txt";
}
OutputMsg( rmTip, _T("正在启动AM充值服务……") );
CAMServerSocket* pAMSrv = new CAMServerSocket(pFileName);
if( ! bAMEngineStartSucceed )
{
OutputMsg( rmError, _T("启动AM充值服务失败……") );
return -1 ;
}
if (pAMSrv->Startup())
{
OutputMsg( rmTip, _T("启动AM充值服务成功!") );
char cmd[100];
#ifndef WIN32
changemode(1);
#endif
while( AMEngineRunning )
{
if(_kbhit())
{
std::cin >> (cmd);
}
else
{
Sleep(500);
continue;
}
//_getts(cmd);
if (strcmp(cmd,_T("exit")) == 0 || strcmp(cmd, _T("quit")) == 0)
{
OutputMsg( rmTip, _T("正在退出...") );
break;
}
else if( strcmp(cmd,_T("contractid")) == 0 )
{
pAMSrv->OutPutContractIdMap();
}
}
#ifndef WIN32
changemode(0);
#endif
}
else //启动服务失败
{
OutputMsg( rmError, _T("启动AM充值服务失败") );
Sleep(3000);
}
pAMSrv->Stop();
SafeDelete(pAMSrv);
ServerDestroy();
return 0;
}

View File

@@ -0,0 +1,71 @@
// stdafx.cpp : source file that includes just the standard includes
// AMServer.pch will be the pre-compiled header
// stdafx.obj will contain the pre-compiled type information
#include "stdafx.h"
namespace HttpUtility
{
typedef unsigned char BYTE;
BYTE toHex(const BYTE &x)
{
return x > 9 ? x -10 + 'A': x + '0';
}
BYTE fromHex(const BYTE &x)
{
return isdigit(x) ? x-'0' : x-'A'+10;
}
string URLEncode(const string &sIn)
{
string sOut;
for( size_t ix = 0; ix < sIn.size(); ix++ )
{
BYTE buf[4];
memset( buf, 0, 4 );
if( isalnum( (BYTE)sIn[ix] ) )
{
buf[0] = sIn[ix];
}
else
{
buf[0] = '%';
buf[1] = toHex( (BYTE)sIn[ix] >> 4 );
buf[2] = toHex( (BYTE)sIn[ix] % 16);
}
sOut += (char *)buf;
}
return sOut;
};
string URLDecode(const string &sIn)
{
string sOut;
for( size_t ix = 0; ix < sIn.size(); ix++ )
{
BYTE ch = 0;
if(sIn[ix]=='%')
{
ch = (fromHex(sIn[ix+1])<<4);
ch |= fromHex(sIn[ix+2]);
ix += 2;
}
else if(sIn[ix] == '+')
{
ch = ' ';
}
else
{
ch = sIn[ix];
}
sOut += (char)ch;
}
return sOut;
}
}
// TODO: reference any additional headers you need in STDAFX.H
// and not in this file

94
server/AmServer/stdafx.h Normal file
View File

@@ -0,0 +1,94 @@
// stdafx.h : include file for standard system include files,
// or project specific include files that are used frequently, but
// are changed infrequently
//
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <map>
#ifdef WIN32
#include <crtdbg.h>
#include <tchar.h>
#include <Windows.h>
#endif
#include "_osdef.h"
#include "_ast.h"
#include <_memchk.h>
#include <Thread.h>
#include <CustomSocket.h>
#include <Lock.h>
#include <Tick.h>
#include <RefString.hpp>
#include <Stream.h>
#include <wrand.h>
#include <bzhash.h>
#include <vector>
#include <string>
using namespace std;
extern "C"
{
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>
}
#include <stdlib.h>
#include <_ast.h>
#include <_memchk.h>
#include <Tick.h>
#include <Lock.h>
#include <Stream.h>
#include <QueueList.h>
#include "ShareUtil.h"
#include "BufferAllocator.h"
#include "ObjectAllocator.hpp"
#include "SingleObjectAllocator.hpp"
#include "AppItnMsg.h"
#include <RefClass.hpp>
#include <RefString.hpp>
#include "EDPass.h"
#include <CustomSocket.h>
#include "DataPacket.hpp"
#include "DataPacketReader.hpp"
#include "SendPackPool.h"
#include "CustomWorkSocket.h"
#include "CustomServerSocket.h"
#include "CustomServerClientSocket.h"
#include "ServerDef.h"
#include "CustomJXServerClientSocket.h"
#include "SQL.h"
#include "CustomLuaScript.h"
#include "CustomLuaConfig.h"
#include "DefExceptHander.h"
#include "FileLogger.h"
#include "MiniDateTime.h"
#include "HttpParamParser.h"
#include "SrvConfig.h"
#include "AMClientSocket.h"
#include "AMServerSocket.h"
#include "Product.h"
#include "md5.h"
#include "EDCode.h"
#include "FDOP.h"
namespace HttpUtility
{
typedef unsigned char BYTE;
BYTE toHex(const BYTE &x);
BYTE fromHex(const BYTE &x);
string URLEncode(const string &sIn);
string URLDecode(const string &sIn);
}
extern bool bAMEngineStartSucceed ;
// TODO: reference additional headers your program requires here

View File

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

View File

@@ -0,0 +1,46 @@
{
// 使用 IntelliSense 了解相关属性。
// 悬停以查看现有属性的描述。
// 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "(gdb) 启动",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/../../build/BackStageServer/backstageserver_d",
"args": ["${workspaceFolder}/../../build/BackStageServer/BackStageServerLinux.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/BackStageServer/backstageserver_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;"
}
]
}

View File

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

View File

@@ -0,0 +1,293 @@
#include "stdafx.h"
using namespace jxSrvDef;
int CBackClientSocket::g_nSpid = 0;
CBackClientSocket::CBackClientSocket(void)
{
m_nextCreateTtableTick = 0;
m_nServerIndex = 0;
m_nSpid = 0;
}
CBackClientSocket::CBackClientSocket(CBackServerSocket* pSrv,SOCKET nSocket, SOCKADDR_IN *pClientAddr)
{
this->m_pBackServer = pSrv;
this->m_pSQLConnection = pSrv->GetSqlConnection();
this->SetClientSocket(nSocket,pClientAddr);
m_nextCreateTtableTick = 0;
m_nServerIndex = 0;
m_nSpid = 0;
}
CBackClientSocket::~CBackClientSocket(void)
{
OutputMsg(rmNormal,_T("log client[%s] Destroy"),getClientName());
for(int i = 0; i < m_dataList.count(); i++)
{
CDataPacket* dp = m_dataList[i];
dp->setPosition(0);
flushSendPacket(*dp);
}
m_dataList.clear();
for(int i = 0; i < m_freeDataList.count(); i++)
{
CDataPacket* dp = m_freeDataList[i];
dp->setPosition(0);
flushSendPacket(*dp);
}
m_freeDataList.clear();
}
bool CBackClientSocket::OnValidateRegData(const jxSrvDef::PSERVER_REGDATA pRegData)
{
//游戏服和db能够登陆
if ( pRegData && pRegData->GameType == SERVER_REGDATA::GT_JianXiaoJiangHu &&
( pRegData->ServerType == GameServer || pRegData->ServerType == DBServer
|| pRegData->ServerType == SessionServer) )
{
return true;
}
else
{
return false;
}
}
VOID CBackClientSocket::OnRun()
{
Inherited::OnRun();
jxSrvDef::INTERSRVCMD nCmd =0;
TICKCOUNT nStartTick = _getTickCount(); //获取当前的时间tick
while(m_dataList.count() >0)
{
CDataPacket* pDataPatck = m_dataList[0];
CDataPacketReader inPacket(pDataPatck->getMemoryPtr(),pDataPatck->getPosition());
inPacket >> nCmd ;
#ifdef WIN32
__try
#endif
{
switch(nCmd)
{
case REV_LOGICSERVERINFO: //收到逻辑服的信息
{
RevLogicInfo(inPacket);
}
break;
case SEND_COMMAND_RESULT :
{
RevCommandResult(inPacket);
break;
}
case SEND_NOTICE_MGR:
{
UpdateNotice(inPacket);
break;
}
case SEND_LOGICSPID:
{
int nSpid = 0;
inPacket >> nSpid;
if(nSpid > 0)
{
m_nSpid = nSpid;
}
break;
}
default:
break;
}
}
#ifdef WIN32
__except(DefaultExceptHandler(GetExceptionInformation()))
#endif
{
//m_pSQLConnection->ResetQuery();
}
m_freeDataList.add(pDataPatck);
m_dataList.remove(0); // 删除此消息
//如果执行的时间大于200毫秒则退出执行
TICKCOUNT nCurrentTick = _getTickCount() ;
if(nCurrentTick - nStartTick > 200)
{
break;
}
}
}
int CBackClientSocket::GetSpid()
{
if(m_nSpid > 0)
{
return m_nSpid;
}
return g_nSpid;
}
VOID CBackClientSocket::OnDispatchRecvPacket(const jxSrvDef::INTERSRVCMD nCmd, CDataPacketReader &inPacket)
{
if (!m_pBackServer || nCmd ==0)
{
return;
}
#ifdef WIN32
__try
#endif
{
//如果数据不够每次都申请512个数据包
if(m_freeDataList.count() <=0 )
{
allocSendPacketList(m_freeDataList, 512);
}
CDataPacket* pDataPatck = m_freeDataList.pop();//得到一个空闲的Datapacket
pDataPatck->setPosition(0);
//TRACE("free m_TempData:%d\n",(int)(m_TempData));
//复制到内存块中
(*pDataPatck) << nCmd;
pDataPatck->writeBuf(inPacket.getOffsetPtr(),inPacket.getLength());
m_dataList.add(pDataPatck);
//OutputMsg(rmTip,"OnDispatchRecvPacket thread id=%d,ncmd=%d",(int)GetCurrentThread(),(int)nCmd);
//每次都申请一批数据包
/*
*/
}
#ifdef WIN32
__except(DefaultExceptHandler(GetExceptionInformation()))
#endif
{
}
}
void CBackClientSocket::RevLogicInfo(CDataPacketReader &inPacket)
{
int nServerIndex = 0;
inPacket >> nServerIndex;
char sreInfo[512];
inPacket.readString(sreInfo,ArrayCount(sreInfo));
m_nServerIndex = nServerIndex;
/*
int nError = m_pSQLConnection->Exec(szSQLSP_DelServerInfo,nServerIndex);
if(!nError)
{
m_pSQLConnection->ResetQuery();
}
nError = m_pSQLConnection->Exec(szSQLSP_AddServerInfo,nServerIndex,sreInfo?sreInfo:"");
if(!nError)
{
m_pSQLConnection->ResetQuery();
}
*/
}
void CBackClientSocket::GetNoticeMsg()
{
CDataPacket &pdata = allocProtoPacket(GET_NOTICE_MGR); //分配一个 网络包
pdata << (int)m_nServerIndex;
flushProtoPacket(pdata);
}
void CBackClientSocket::SendCommandToLogic(int nServerIndex,int nOperIndex,char* sCommand,char* sName,int nId)
{
CDataPacket &pdata = allocProtoPacket(SEND_COMMAND); //分配一个 网络包
pdata << (int)nServerIndex;
pdata << (int)nOperIndex;
pdata << (int)nId;
pdata.writeString(sName?sName:"");
pdata.writeString(sCommand?sCommand:"");
flushProtoPacket(pdata);
}
void CBackClientSocket::RevCommandResult(CDataPacketReader &inPacket)
{
int nServerIndex = 0;
inPacket >> nServerIndex;
int nCmd = 0;
inPacket >> nCmd;
int nResult = 0;
inPacket >> nResult;
int nId = 0;
inPacket >> nId;
char strName[32];
inPacket.readString(strName,ArrayCount(strName));
char strCommand[1024];
inPacket.readString(strCommand,ArrayCount(strCommand));
char escapeCommand[1024];
mysql_escape_string(escapeCommand,strCommand, (unsigned long)strlen(strCommand));
int nError =m_pSQLConnection->Exec(szSQLSP_AddCommandHistory,nId,nServerIndex,nCmd,escapeCommand?escapeCommand:"",nResult,strName?strName:"",GetSpid());
if (!nError)
{
m_pSQLConnection->ResetQuery();
}
char sResult[32] = {0};
sprintf(sResult,"%d,%d,%d",nResult,m_nServerIndex,nCmd);
m_pBackServer->GetHttpServer().SendResponse(sResult, nId,GetSpid(), nServerIndex);
}
void CBackClientSocket::UpdateNotice(CDataPacketReader &inPacket)
{
int nServerIndex = 0;
inPacket >> nServerIndex;
int operindex = 0;
inPacket >> operindex;
int nCount = 0;
inPacket >> nCount;
int nError =m_pSQLConnection->Exec(szSQLSP_DelServerNotice,nServerIndex,GetSpid());
if (!nError)
{
m_pSQLConnection->ResetQuery();
}
for(int i=0;i<nCount;i++)
{
char strMsg[1024],escapeMsg[1024];
int nPos,nId,nMins;
unsigned int nStartTime,nEndTime;
inPacket >> nId >> nStartTime >> nEndTime >> nMins >> nPos;
inPacket.readString(strMsg,ArrayCount(strMsg));
mysql_escape_string(escapeMsg,strMsg,(unsigned long)strlen(strMsg));
nError =m_pSQLConnection->Exec(szSQLSP_AddServerNotice,nId,nServerIndex,operindex,escapeMsg?escapeMsg:"",GetSpid(),nStartTime,nEndTime,nMins,nPos);
if (!nError)
{
m_pSQLConnection->ResetQuery();
}
}
}
VOID CBackClientSocket::OnDisconnected()
{
if(m_pBackServer)
{
m_pBackServer->DelClient(this);
}
}

View File

@@ -0,0 +1,90 @@
#ifndef _LOGGER_CLIENT_SOCKET_H_
#define _LOGGER_CLIENT_SOCKET_H_
class CCustomJXServerClientSocket;
class CBackServerSocket;
//class CNetworkDataHandler;
//发送命令出去
#define SEND_COMMAND 1 //发送操作码给逻辑服
#define GET_NOTICE_MGR 2 //请求公告
//收到命令
#define REV_LOGICSERVERINFO 1 //收到逻辑服的信息
#define SEND_COMMAND_RESULT 2 //收到服务器发送来的关于命令是否执行的包!
#define SEND_NOTICE_MGR 3 //收到公告
#define SEND_LOGICSPID 4 //收到逻辑服spid
class CBackClientSocket:
public CCustomJXServerClientSocket
{
public:
const static int CREATE_LOCALTABLE_INTERVAL = 86400000; //1天调用一次
CBackClientSocket(void);
CBackClientSocket(CBackServerSocket* pSrv,SOCKET nSocket, SOCKADDR_IN *pClientAddr);
~CBackClientSocket(void);
//继承基类的方法,处理收到的数据包
//virtual VOID ProcessRecvBuffers(PDATABUFFER pDataBuffer);
/*** 子类需覆盖的函数集 ***/
/* 处理单个通信数据包
* nCmd 通信消息命令
* inPacket 已经读取出通信命令的数据包,数据包的读取位置指向命令数据后的内容
*/
virtual VOID OnDispatchRecvPacket(const jxSrvDef::INTERSRVCMD nCmd, CDataPacketReader &inPacket);
/* 验证客户端注册数据是否有效
*@return 返回true表示注册数据有效并返回false则关闭连接
*/
virtual bool OnValidateRegData(const jxSrvDef::PSERVER_REGDATA pRegData);
//获取服务器id
int GetnServerIndex() {return m_nServerIndex;}
//发送命令给逻辑服
//nServerIndex 服务器id
// nOperIndex 操作码
// sCommand 操作命令
void SendCommandToLogic(int nServerIndex,int nOperIndex,char* sCommand,char* sName,int nId);
//请求公告信息
void GetNoticeMsg();
//收到逻辑服的信息
void RevLogicInfo(CDataPacketReader &inPacket);
//收到刷命令的结果
void RevCommandResult(CDataPacketReader &inPacket);
//插入公告
void UpdateNotice(CDataPacketReader &inPacket);
int GetSpid();
public:
static int g_nSpid;
private:
/*
* 处理逻辑包
* pDataBuff:为真正需要处理的数据包,这里只处理日志类型的数据包,每次处理一个数据包;nLen:数据的长度
* 返回实际处理的字节数事实上pDataBuff的大小会比数据包大,返回0表示出错没处理
*/
int ProcessData(void* pDataBuff,int nLen);
protected:
virtual VOID OnRun();
VOID OnDisconnected();
private:
//把数据包传递给这个类保存到数据库
CBackServerSocket* m_pBackServer;
CSQLConenction* m_pSQLConnection; //数据库连接对象
TICKCOUNT m_nextCreateTtableTick; //上一次的调用的tickCount
CBaseList<CDataPacket* > m_dataList; //待处理的数据列表
CBaseList<CDataPacket* > m_freeDataList; //空闲的数据列表
int m_nServerIndex;
int m_nSpid;
};
#endif

View File

@@ -0,0 +1,269 @@
#include "stdafx.h"
static char sName[64];
CBackHttpServer::CBackHttpServer(void)
{
InitializeCriticalSection(&m_HttpServerLock);
ClearParams();
m_fdSetCount = 0;
}
CBackHttpServer::~CBackHttpServer(void)
{
DeleteCriticalSection(&m_HttpServerLock);
}
void CBackHttpServer::DoHttpServerCreate(char* sAddr,int nPort)
{
m_ServerSocket = socket(AF_INET,SOCK_STREAM,0);
m_AddrServer.sin_addr.s_addr = inet_addr(sAddr);
m_AddrServer.sin_family = AF_INET;
m_AddrServer.sin_port = htons(nPort);
int tmp =1;
setsockopt(m_ServerSocket,SOL_SOCKET,SO_REUSEADDR,&tmp, sizeof(tmp));
if (bind(m_ServerSocket,(SOCKADDR*)&m_AddrServer,sizeof(SOCKADDR)) == -1)
{
OutputMsg(rmError,"bind Error Port:%d",nPort);
}
if (listen(m_ServerSocket,1024) == -1)
{
OutputMsg(rmError,"listen Error Port:%d",nPort);
}
CreateSocketInfo(m_ServerSocket);
OutputMsg(rmTip,_T("HTTPSERVER启动完成"));
}
BOOL CBackHttpServer::CreateSocketInfo(SOCKET s)
{
if (m_fdSetCount >= FD_SETSIZE)
{
return false;
}
SocketInfo info;
info.socket = s;
m_SocketInfoArr[m_fdSetCount++] = info;
return true;
}
void CBackHttpServer::RemoveSocketInfoBySocket(SOCKET s)
{
for (int i = 0; i < m_fdSetCount; i++)
{
if (m_SocketInfoArr[i].socket == s)
{
RemoveSocketInfo(i);
return;
}
}
}
void CBackHttpServer::RemoveSocketInfo(int index)
{
if (index < 0 || index >= FD_SETSIZE || index >= m_fdSetCount)
{
return;
}
closesocket(m_SocketInfoArr[index].socket);
for (int i = index; i < m_fdSetCount; i++)
{
m_SocketInfoArr[i] = m_SocketInfoArr[i+1];
}
m_fdSetCount--;
}
void CBackHttpServer::AddToSocketInfo(SocketInfo& sInfo,int nId, int nSpid, int nServerIndex)
{
sInfo.id = nId;
sInfo.spid = nSpid;
sInfo.serverindex = nServerIndex;
}
void CBackHttpServer::HttpGetData()
{
struct timeval timeout={0,0};
FD_ZERO(&m_fdSocket);
SOCKET maxFds = 0;
for (int i =0; i < m_fdSetCount; i++)
{
SocketInfo& info = m_SocketInfoArr[i];
FD_SET(info.socket,&m_fdSocket);
if (info.socket > maxFds)
{
maxFds = info.socket;
}
}
#ifdef WIN32
int nRet = select(NULL,&m_fdSocket,NULL,NULL,&timeout);
#else
int nRet = select(maxFds+1,&m_fdSocket,NULL,NULL,&timeout);
#endif
if (nRet <= 0)
{
return ;
}
for (int i =0; i < m_fdSetCount; i++)
{
SocketInfo& info = m_SocketInfoArr[i];
if (FD_ISSET(info.socket,&m_fdSocket))
{
if(info.socket == m_ServerSocket)
{
int len=sizeof(SOCKADDR);
#ifdef WIN32
m_ClientSocket = accept(m_ServerSocket,(SOCKADDR*)(&m_AddrClient),&len);
#else
m_ClientSocket = accept(m_ServerSocket,(SOCKADDR*)(&m_AddrClient),(socklen_t*)&len);
#endif
if (m_ClientSocket == INVALID_SOCKET)
{
continue;
}
BOOL bReuseaddr=FALSE;
setsockopt(m_ClientSocket, SOL_SOCKET ,SO_REUSEADDR,(const char*)&bReuseaddr,sizeof(BOOL));
if (!CreateSocketInfo(m_ClientSocket))
{
SendResponse(m_ClientSocket,"CreateSocketInfo Error");
OutputMsg(rmError,"CreateSocketInfo Error");
return ;
}
}
else
{
memset(info.data, 0, BUFSIZE);
int recvSize = recv(info.socket,info.data,BUFSIZE,0);
if (recvSize == 0 || recvSize == INVALID_SOCKET)
{
RemoveSocketInfoBySocket(info.socket);
continue;
}
}
}
}
}
bool CBackHttpServer::DocumentParser(char * sDocument)
{
EnterCriticalSection( &m_HttpServerLock );
if (strlen(sDocument) == 0)
{
LeaveCriticalSection( &m_HttpServerLock );
return false;
}
char * pStr = strtok(sDocument," ");
char * s = strtok(NULL," ");
if (pStr == NULL || s == NULL)
{
LeaveCriticalSection( &m_HttpServerLock );
return false;
}
const char *d = "?&";
char *p;
p = strstr(s,"?");
p = strtok(p,d);
int iCount = 0;
int nIndex = 0;
while (p)
{
size_t value_len = 0 ;
size_t name_len = 0;
memset(sName,0,sizeof(sName));
char* sValue = strstr(p, "=");
if (sValue && strlen(sValue)> 1)
{
strncpy(sName,p,sValue-p);
sValue++;
name_len = strlen(sName);
name_len = (name_len>MAXPARAMNAMELENGTH-1)?MAXPARAMNAMELENGTH-1:name_len ;
if (name_len >= 1)
{
strncpy(m_Params[nIndex].sName,sName,name_len);
m_Params[nIndex].sName[name_len] = '\0' ;
value_len = strlen(sValue) ;
value_len = (value_len>MAXPARAMVALUELENGTH-1)?MAXPARAMVALUELENGTH-1:value_len ;
strncpy(m_Params[nIndex].sValue,sValue,value_len);
m_Params[nIndex].sValue[value_len] = '\0' ;
nIndex++;
}
}
if (nIndex >= MAX_PARAM_NUM)
{
break;
}
iCount++;
p=strtok(NULL,d);
}
for (int i=0;i<iCount;i++)
{
if((strcmp(m_Params[i].sName,"user") == 0) || (strcmp(m_Params[i].sName,"command") == 0))
{
string str = BackHttpUtility::URLDecode(m_Params[i].sValue);
str.copy(m_Params[i].sValue, str.length(), 0);
m_Params[i].sValue[str.length()] = 0;
//break;
}
}
memset(sDocument,0,BUFSIZE);
LeaveCriticalSection( &m_HttpServerLock );
return true;
}
void CBackHttpServer::SendResponse(SOCKET socket, LPCSTR sResult)
{
char sendBuf[1024];
memset(sendBuf, 0, 1024);
strcat(sendBuf, "HTTP/1.1 200\r\n");
strcat(sendBuf, "Server: BackStageServer\r\n");
strcat(sendBuf, "Content-Type:text/html;charset=utf8\r\n\r\n");
strcat(sendBuf, sResult);
size_t len = strlen(sendBuf);
send(socket,sendBuf,(int)len,(int)0);
RemoveSocketInfoBySocket(socket);
}
void CBackHttpServer::SendResponse(LPCSTR sResult,int nId, int nSpid, int nServerindex)
{
for(int i=0; i <m_fdSetCount; i++)
{
SocketInfo& info = m_SocketInfoArr[i];
if (info.id == nId && info.spid == nSpid && (info.serverindex ==0 || info.serverindex == nServerindex))
{
SendResponse(info.socket, sResult);
break;
}
}
OutputMsg(rmTip,"Result:%s Id:%d Spid:%d",sResult, nId, nSpid);
}
LPCTSTR CBackHttpServer::GetParamCharValue(char* sName)
{
for (int i=0;i<MAX_PARAM_NUM;i++)
{
if (strcmp(m_Params[i].sName,sName) == 0)
{
return m_Params[i].sValue;
}
}
return "";
}
int CBackHttpServer::GetParamIntValue(char* sName)
{
for (int i=0;i<MAX_PARAM_NUM;i++)
{
if (strcmp(m_Params[i].sName,sName) == 0)
{
return atoi(m_Params[i].sValue);
}
}
return 0;
}
SOCKET CBackHttpServer::GetClientSocket()
{
return m_ClientSocket;
}

View File

@@ -0,0 +1,127 @@
#pragma once
#define BUFSIZE 2048
#define MAX_PARAM_NUM 20
#define MAXPARAMNAMELENGTH 32
#define MAXPARAMVALUELENGTH 2048
typedef struct tagHttpParam
{
char sName[MAXPARAMNAMELENGTH]; //参数名称
char sValue[MAXPARAMVALUELENGTH]; //参数值
tagHttpParam()
{
memset(this, 0, sizeof(*this));
}
}HTTPPARAM;
typedef struct tagSocketInfo
{
SOCKET socket;
int id;
int spid;
int serverindex;
char data[BUFSIZE];
tagSocketInfo ()
{
memset(this,0,sizeof(*this));
}
}SocketInfo;
class CBackHttpServer
{
public:
CBackHttpServer(void);
~CBackHttpServer(void);
void ClearParams()
{
memset(m_Params,0,sizeof(m_Params));
}
public:
//************************************
// Method: DoHttpServerCreate 创建http服务器
// FullName: CBackHttpServer::DoHttpServerCreate
// Access: public
// Returns: void
// Qualifier:
// Parameter: char * sAddr 绑定地址
// Parameter: int nPort 绑定端口
//************************************
void DoHttpServerCreate(char* sAddr,int nPort);
//************************************
// Method: HttpGetData 获取serversocket接收到的数据
// FullName: CBackHttpServer::HttpGetData
// Access: public
// Returns: void
// Qualifier:
//************************************
void HttpGetData();
//************************************
// Method: DocumentParser 解析http信息
// FullName: CBackHttpServer::DocumentParser
// Access: public
// Returns: bool
// Qualifier:
// Parameter: char * sDocument 数据
//************************************
bool DocumentParser(char * sDocument);
//************************************
// Method: SendResponse 返回server信息给php
// FullName: CBackHttpServer::SendResponse
// Access: public
// Returns: void
// Qualifier:
// Parameter: LPCSTR sContent 结果字符串
// Parameter: int nId 后台指令id
// Parameter: int nSpid spid
// Parameter: int nServerindex 服务器id
//************************************
void SendResponse(LPCSTR sResult,int nId =0, int nSpid = 0, int nServerindex = 0);
void SendResponse(SOCKET socket, LPCSTR sResult);
//************************************
// Method: GetParamCharValue 获取字符串参数值
// FullName: CBackHttpServer::GetParamCharValue
// Access: public
// Returns: LPCTSTR
// Qualifier:
// Parameter: char * sName 参数名
//************************************
LPCTSTR GetParamCharValue(char* sName);
//************************************
// Method: GetParamIntValue 获取整型参数值
// FullName: CBackHttpServer::GetParamIntValue
// Access: public
// Returns: int
// Qualifier:
// Parameter: char * sName 参数名
//************************************
int GetParamIntValue(char* sName);
//************************************
// Method: GetClientSocket 获取客户端socket
// FullName: CBackHttpServer::GetClientSocket
// Access: public
// Returns: SOCKET
// Qualifier:
//************************************
SOCKET GetClientSocket();
void AddToSocketInfo(SocketInfo& sInfo,int nId, int nSpid, int nServerIndex);
private:
BOOL CreateSocketInfo(SOCKET s) ;
void RemoveSocketInfo(int index);
void RemoveSocketInfoBySocket(SOCKET s);
private:
SOCKET m_ServerSocket; //httpServerSocket
SOCKET m_ClientSocket; //httpClientSocket
fd_set m_fdSocket; //socket 元素
SOCKADDR_IN m_AddrClient; //client地址
SOCKADDR_IN m_AddrServer; //server地址
RTL_CRITICAL_SECTION m_HttpServerLock; //httpServer锁
char* m_ClientIP; //连接clientip
HTTPPARAM m_Params[MAX_PARAM_NUM]; //参数
public:
SocketInfo m_SocketInfoArr[FD_SETSIZE];
int m_fdSetCount;
};

View File

@@ -0,0 +1,64 @@
#include "stdafx.h"
namespace BackHttpUtility
{
typedef unsigned char BYTE;
BYTE toHex(const BYTE &x)
{
return x > 9 ? x -10 + 'A': x + '0';
}
BYTE fromHex(const BYTE &x)
{
return isdigit(x) ? x-'0' : x-'A'+10;
}
string URLEncode(const string &sIn)
{
string sOut;
for( size_t ix = 0; ix < sIn.size(); ix++ )
{
BYTE buf[4];
memset( buf, 0, 4 );
if( isalnum( (BYTE)sIn[ix] ) )
{
buf[0] = sIn[ix];
}
else
{
buf[0] = '%';
buf[1] = toHex( (BYTE)sIn[ix] >> 4 );
buf[2] = toHex( (BYTE)sIn[ix] % 16);
}
sOut += (char *)buf;
}
return sOut;
};
string URLDecode(const string &sIn)
{
string sOut;
for( size_t ix = 0; ix < sIn.size(); ix++ )
{
BYTE ch = 0;
if(sIn[ix]=='%')
{
ch = (fromHex(sIn[ix+1])<<4);
ch |= fromHex(sIn[ix+2]);
ix += 2;
}
else if(sIn[ix] == '+')
{
ch = ' ';
}
else
{
ch = sIn[ix];
}
sOut += (char)ch;
}
return sOut;
}
}

View File

@@ -0,0 +1,14 @@

namespace BackHttpUtility
{
typedef unsigned char BYTE;
BYTE toHex(const BYTE &x);
BYTE fromHex(const BYTE &x);
string URLEncode(const string &sIn);
string URLDecode(const string &sIn);
}

View File

@@ -0,0 +1,248 @@
#include "stdafx.h"
CBackServerSocket::CBackServerSocket(char *pszFileName)
{
Config.ReadConfig(pszFileName);
SetServiceName(Config.SrvConf.szServiceName);
SetServiceHost(Config.SrvConf.szAddr);
SetServicePort(Config.SrvConf.nPort);
SetDbConnection();
m_boCreateTableStoped = TRUE;
m_nextGetNoticeTick = 0;
m_HttpServer.DoHttpServerCreate("0.0.0.0",Config.SrvConf.nHttpPort);
}
CBackServerSocket::~CBackServerSocket(void)
{
}
CCustomServerClientSocket* CBackServerSocket::CreateClientSocket(SOCKET nSocket, PSOCKADDR_IN pAddrIn)
{
if (pAddrIn == NULL)
{
return NULL;
}
OutputMsg( rmTip, "接受客户端连接!" );
CBackClientSocket* pClientSocket = new CBackClientSocket(this,nSocket,pAddrIn);
if(pClientSocket)
{
m_BackClientList.lock();
m_BackClientList.add(pClientSocket);
m_BackClientList.unlock();
}
else
{
OutputMsg(rmError,"连接初始化失败");
}
return pClientSocket;
}
BOOL CBackServerSocket::ExecSql(const char* szSql)
{
return TRUE;
}
VOID CBackServerSocket::SetDbConnection()
{
Db.SetServerHost(Config.DbConf.szHost);
Db.SetServerPort(Config.DbConf.nPort);
Db.SetDataBaseName(Config.DbConf.szDbName);
Db.SetUserName(Config.DbConf.szUser);
//这个要解密
Db.SetPassWord(Config.DbConf.szPassWord);
//多个客户端连接,数据库操作类要加锁
//Db.SetMultiThread(TRUE);
Db.SetConnectionFlags(CLIENT_FOUND_ROWS | CLIENT_MULTI_RESULTS);
BOOL boConnected = Db.Connect();
if (boConnected)
{
OutputMsg( rmTip, _T("连接数据库成功"));
if (Config.DbConf.nUseUtf8 )
{
if (mysql_set_character_set(Db.GetMySql(),"utf8"))
{
OutputMsg( rmError, _T("设置utf8编码出错 !!!") );
}
}
OutputMsg(rmTip, _T("mysql connection character set: %s"), mysql_character_set_name(Db.GetMySql()));
CreateTables();
}
else
{
OutputMsg( rmError, _T("连接数据库失败"));
}
}
void CBackServerSocket::DelClient(CBackClientSocket* pClient)
{
CBackClientSocket *tmpClient;
m_BackClientList.lock();
for ( INT_PTR i=m_BackClientList.count() - 1; i>-1; --i )
{
tmpClient = (CBackClientSocket*)m_BackClientList[i];
if(tmpClient && tmpClient == pClient)
{
m_BackClientList.remove(i);
break;
}
}
m_BackClientList.unlock();
}
void CBackServerSocket::CreateTables()
{
if (Db.Exec(m_szCommandHistory) != 0)
{
//失败
OutputMsg(rmError,_T("建表失败sql:%s"),m_szCommandHistory);
}
else
{
Db.ResetQuery();
}
if (Db.Exec(szSQLSP_DropNoticTable) != 0)
{
OutputMsg(rmError,_T("建表失败sql:%s"),szSQLSP_DropNoticTable);
}
else
{
Db.ResetQuery();
}
if (Db.Exec(m_szCreateNotice) != 0)
{
//失败
OutputMsg(rmError,_T("建表失败sql:%s"),m_szCreateNotice);
}
else
{
Db.ResetQuery();
}
}
//每次调用
VOID CBackServerSocket::SingleRun()
{
ServerInherited::SingleRun();
TICKCOUNT tcNow = _getTickCount();
if(m_nextGetNoticeTick <= 0)
{
m_nextGetNoticeTick = tcNow + 20 * 60 * 1000;
}
//30分钟
if(tcNow>m_nextGetNoticeTick)
{
CBackClientSocket *pClient;
m_BackClientList.lock();
for(int i=0;i<m_BackClientList.count();i++)
{
pClient = (CBackClientSocket*)m_BackClientList[i];
if(pClient)
{
pClient->GetNoticeMsg();
}
}
m_BackClientList.unlock();
m_nextGetNoticeTick=tcNow+60 * 60 * 1000;
}
m_HttpServer.HttpGetData();
for (int i = m_HttpServer.m_fdSetCount-1; i >0; i--)
{
SocketInfo& sInfo = m_HttpServer.m_SocketInfoArr[i];
if (strlen(sInfo.data)>0)
{
OutputMsg(rmTip, _T("%s"), BackHttpUtility::URLDecode(sInfo.data).c_str());
m_HttpServer.ClearParams();
HandleHttpCommand(sInfo);
}
}
}
void CBackServerSocket::HandleHttpCommand(SocketInfo& socketInfo)
{
if (!m_HttpServer.DocumentParser(socketInfo.data))
{
memset(socketInfo.data,0, BUFSIZE);
m_HttpServer.SendResponse(socketInfo.socket, "Get Http Param Parser Error");
OutputMsg( rmError, "Get Http Param Parser Error");
return;
}
int nOperIndex = m_HttpServer.GetParamIntValue("operid");
LPCTSTR sUserName = m_HttpServer.GetParamCharValue("user");
if (!sUserName || nOperIndex < 0)
{
m_HttpServer.SendResponse(socketInfo.socket,"Http Param Error");
OutputMsg( rmError, "Http Param Error");
return;
}
int nServerIndex = m_HttpServer.GetParamIntValue("server_num");
int nSpid = m_HttpServer.GetParamIntValue("spid");
int nId = m_HttpServer.GetParamIntValue("auto_id");
LPCTSTR sCommand = m_HttpServer.GetParamCharValue("command");
CBackClientSocket *pClient;
bool bFindServer = false;
if(nOperIndex > 0 && nServerIndex == 0)
{
m_BackClientList.lock();
OutputMsg(rmTip, _T("发送命令%d到全服,spid:%d"), nOperIndex, nSpid);
for(int i=0;i<m_BackClientList.count();i++)
{
pClient = (CBackClientSocket*)m_BackClientList[i];
if(pClient && pClient->GetSpid() == nSpid)
{
pClient->SendCommandToLogic(nServerIndex,nOperIndex,(char*)sCommand,(char*)sUserName,nId);
m_HttpServer.AddToSocketInfo(socketInfo, nId, nSpid, nServerIndex);
bFindServer = true;
}
}
m_BackClientList.unlock();
}
else if(nOperIndex > 0 && nServerIndex > 0)
{
m_BackClientList.lock();
for(int i=0;i<m_BackClientList.count();i++)
{
pClient = (CBackClientSocket*)m_BackClientList[i];
if(pClient )
{
int nIndex = pClient->GetnServerIndex();
int nidd = pClient->GetSpid();
if ( nIndex == nServerIndex && nidd == nSpid)
{
OutputMsg(rmTip, _T("发送命令%d到%d,spid:%d"), nOperIndex, nServerIndex, nSpid);
pClient->SendCommandToLogic(nServerIndex,nOperIndex,(char*)sCommand,(char*)sUserName,nId);
m_HttpServer.AddToSocketInfo(socketInfo, nId, nSpid, nServerIndex);
bFindServer = true;
break;
}
}
}
m_BackClientList.unlock();
}
if (!bFindServer)
{
m_HttpServer.SendResponse(socketInfo.socket, "Cannot Find Server");
OutputMsg(rmError,"Cannot Find Server spid:%d,serverindex:%d",nSpid,nServerIndex);
}
}

View File

@@ -0,0 +1,114 @@
#pragma once
class CCustomServerSocket;
class CSQLConenction;
class CSrvConfig;
class CBackServerSocket:
public CCustomServerSocket
{
public:
typedef CCustomServerSocket ServerInherited ;
//重载父类的函数
virtual CCustomServerClientSocket* CreateClientSocket(SOCKET nSocket, PSOCKADDR_IN pAddrIn);
inline CSQLConenction* GetSqlConnection() { return &Db;}
//删除服务器
void DelClient(CBackClientSocket* pClient);
public://构造函数和析构函数
CBackServerSocket(char *pszFileName);
~CBackServerSocket(void);
CBackHttpServer& GetHttpServer(){ return m_HttpServer; };
protected:
//启动创建表
VOID CreateTables();
//每次调用
VOID SingleRun();
private:
//设置数据库的相关参数
VOID SetDbConnection();
/*
* 执行插入数据库操作,注意:如果执行出错,需要记录到文件日志里
* szSql:sql语句
*/
BOOL ExecSql(const char* szSql);
void HandleHttpCommand(SocketInfo& socketInfo);
public:
CSrvConfig Config;
protected:
CSQLConenction Db;
volatile LONG m_boCreateTableStoped; //是否停止工作线程
HANDLE m_hCTThread;
TICKCOUNT m_nextGetNoticeTick; //每30分钟请求公告
CQueueList<CBackClientSocket*> m_BackClientList; //客户端列表
CBackHttpServer m_HttpServer;
//上一次的调用的tickCount
typedef struct tagCommand
{
int id;
int serverindex;
int operindex;
char strcom[512];
char username[32];
char time[24];
}COMMAND,*PCOMMAND;
vector<COMMAND> vcCommandCopy;
};
//--后台操作历史命令表
static LPCSTR m_szCommandHistory = "create table if not exists `commandhistory` ( "
"`id` int(10) not null," //命令的序号id是自增的
"`serverindex` int(10) default null," //要发送到的服务器id 如果是发所有服务器写0就可以
"`operindex` int(10) default null," //操作码
"`strcom` varchar(1024) default null," //命令类容
"`nstate` int(10) default null," //状态
"`username` varchar(32) default null," //用户名称
"`logdate` datetime NOT NULL," //操作时间
"`reser1` int(10) default null" //预留
") engine=myisam default charset=utf8;";
static LPCSTR m_szCreateNotice = "create table if not exists `notice` ( "
"`id` int(10) not null ," //公告id
"`serverindex` int(10) default null," //服务器id
"`operindex` int(10) default null," //操作码
"`strmsg` varchar(1024) default null," //公告类容
"`reser` int(10) default null," //sid
"`starttime` int(10) default 0," //开始时间戳
"`endtime` int(10) default 0," //结束时间戳
"`mins` int(10) default 0," //时间间隔(分钟)
"`pos` int(10) default 0" //位置
") engine=myisam default charset=utf8;";
static LPCSTR szSQLSP_LoadCommand = "select id,serverindex,operindex,strcom ,username ,logdate,reser1 from command"; //查询命令表
static LPCSTR szSQLSP_LoadCommandAll = _T("select id,serverindex,operindex,strcom,username,logdate from command"); //查询命令表
static LPCSTR szSQLSP_AddCommandHistory="insert into commandhistory(id,serverindex,operindex,strcom,nstate,username,reser1,logdate) values(%d,%d,%d,\"%s\",%d,\"%s\",%d,now())";//插入数据到历史表
//static LPCSTR szSQLSP_UpdateCommandHistory="update commandhistory set nstate = &d where id = %d";//更新历史表
static LPCSTR szSQLSP_GetHistory=_T("select serverindex,operindex,strcom ,username,logdate from commandhistory where id=%d");
static LPCSTR szSQLSP_AddCommandCopy="insert into commandcopy(id, serverindex,operindex,strcom,nstate,username,logdate) values(%d,%d,%d,\"%s\",0,\"%s\",\"%s\")";//插入数据到copy表中
static LPCSTR szSQLSP_DelServerInfo = "delete from serverstate where serverindex=%d"; //删除服务器的信息
static LPCSTR szSQLSP_AddServerInfo = "insert into serverstate(serverindex,strstate) values(%d,\"%s\")"; //插入服务器的信息
static LPCSTR szSQLSP_DropNoticTable = "drop table if exists notice"; //删除公告类容
static LPCSTR szSQLSP_DelServerNotice = "delete from notice where serverindex=%d and reser=%d"; //删除公告类容
static LPCSTR szSQLSP_AddServerNotice = "insert into notice(id,serverindex,operindex,strmsg,reser,starttime,endtime,mins,pos) values(%d,%d,%d,\"%s\",%d,%u,%u,%d,%d)"; //插入公告类容

View File

@@ -0,0 +1,86 @@
cmake_minimum_required(VERSION 2.6)
project(backstageserver)
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( CMAKE_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../sdk) # include 文件夹
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}
#)
include_directories(
${CMAKE_INCLUDE_DIR}/public
${CMAKE_INCLUDE_DIR}/system
${CMAKE_INCLUDE_DIR}/utils
# ${CMAKE_CURRENT_SOURCE_DIR}/src/wylib/include
${CMAKE_INCLUDE_DIR}/lua-5.1/src
${CMAKE_INCLUDE_DIR}/tolua++/src
${CMAKE_INCLUDE_DIR}/mysql-5.2/include
${CMAKE_INCLUDE_DIR}/breakpad/
${CMAKE_INCLUDE_DIR}/commonLib/include
${CMAKE_INCLUDE_DIR}/commonLib/def
${CMAKE_INCLUDE_DIR}/srvlib/include
${CMAKE_INCLUDE_DIR}
${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 backstageserver_d )
else()
set( EXE_NAME backstageserver_r )
endif()
SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/../../Exec/BackStageServer)
add_executable(${EXE_NAME} ${sources1} ${sources2} ${sources3} )
#include(../common/cmake/libs.cmake)
include(../../sdk/cmake/libs.cmake)#ccc

View File

@@ -0,0 +1,78 @@
#include "stdafx.h"
#include "SrvConfig.h"
using namespace wylib::stream;
CSrvConfig::CSrvConfig(void)
{
}
CSrvConfig::~CSrvConfig(void)
{
}
void CSrvConfig::ReadConfig(const char *pszFileName)
{
#ifdef WIN32
try
#endif
{
OutputMsg(rmTip,"load file from %s",pszFileName);
CMemoryStream ms;
ms.loadFromFile(pszFileName);
setScript((LPCSTR)ms.getMemory());
if ( openGlobalTable("BackServer"))
{
int nDfaout = 0;
nSpid = getFieldInt("spguid");
CBackClientSocket::g_nSpid = nSpid;
if ( openFieldTable("SQL"))
{
getFieldStringBuffer(("Host"), DbConf.szHost,sizeof(DbConf.szHost));
DbConf.nPort = getFieldInt("Port");
getFieldStringBuffer(("DBName"), DbConf.szDbName,sizeof(DbConf.szDbName));
getFieldStringBuffer(("DBUser"), DbConf.szUser,sizeof(DbConf.szUser));
char szTemp[100];
//getFieldStringBuffer(("DBPass"), szTemp,sizeof(szTemp));
//DecryptPassword(DbConf.szPassWord,sizeof(DbConf.szPassWord),szTemp,"123456abc123456a");
getFieldStringBuffer(("DBPass"), DbConf.szPassWord, sizeof(DbConf.szPassWord));
DbConf.nUseUtf8 = getFieldInt("utf8",&nDfaout);
closeTable();
}
if ( openFieldTable(("Server")))
{
getFieldStringBuffer(("BindAddress"), SrvConf.szAddr,sizeof(SrvConf.szAddr));
SrvConf.nPort = getFieldInt("Port");
getFieldStringBuffer(("ServiceName"), SrvConf.szServiceName,sizeof(SrvConf.szServiceName));
SrvConf.nHttpPort = getFieldInt("HttpPort");
closeTable();//DB
}
closeTable();//关闭Config
}
}
#ifdef WIN32
catch(RefString &s)
{
OutputMsg( rmNormal, s.rawStr() );
}
catch(...)
{
OutputMsg( rmNormal, _T("unexpected error on load config") );
}
#endif
}
void CSrvConfig::ShowError(const LPCTSTR sError)
{
m_sLastErrDesc = sError;
RefString sErr;
sErr = _T("[Configuration Error]");
sErr += sError;
//集中处理错误为了简单起见此处直接抛出异常。异常会在readConfig中被捕获从而立刻跳出对配置的循环读取。
throw sErr;
}

View File

@@ -0,0 +1,45 @@
#ifndef _SRV_CONFIG_H_
#define _SRV_CONFIG_H_
//服务器端口地址等相关配置
typedef struct SrvConf
{
char szAddr[20];
int nPort;
char szServiceName[20];
int nHttpPort;
} SRVCONF,*PSRVCONF;
typedef struct DbConf{
char szHost[100];
int nPort;
char szDbName[100];
char szUser[100];
char szPassWord[100];
char szKey[100];//用于解密的key16位
int nUseUtf8;
}DBCONF,*PDBCONF;
class CSrvConfig:
public CCustomLuaConfig
{
public:
/*
* 只读取同目录下的指定配置文件
*/
void ReadConfig(const char *pszFileName);
public:
CSrvConfig(void);
~CSrvConfig(void);
public:
SRVCONF SrvConf;
DBCONF DbConf;
int nSpid;
int nServerIndex;
protected:
void ShowError(const LPCTSTR sError);
};
#endif

View File

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

View File

@@ -0,0 +1,165 @@
#include "stdafx.h"
#ifdef WIN32
#include <dbghelp.h>
#include <mbctype.h>
#endif
#include "utf8_output.h"
//#include "WinService.h"
#include "PathThreadLocale.h"
#include <string>
#include <vector>
using namespace std;
const char szExceptionDumpFile[] = ".\\BackServer.dmp";
VOID ServiceMain(int argc, char** argv);
VOID ServerMain(int argc, char** argv);
#define DBEGN_KN_VERION MAKEFOURCC(17, 3, 24, 1)
#ifdef WIN32
class CLogService : public CWinService
{
public:
CLogService(LPCSTR pServiceName, DWORD dwServiceType = SERVICE_WIN32_OWN_PROCESS):CWinService(pServiceName, dwServiceType){};
int AppMain()
{
// 创建 套接字服务类
SetCurrentDirectory("../"); //CWinService里会把当前目录改成exe允许的目录所以这里再转一下
CFileLogger flog(_T("BackServer%s.log"), getCurrentTimeDesc());
CBackServerSocket* pLoggerSrv = new CBackServerSocket();
OutputMsg( rmTip, _T("正在启动网关服务……") );
if (pLoggerSrv->Startup())
{
OutputMsg( rmTip, _T("启动网关服务成功!") );
while (!m_boServiceExit)
{
Sleep(1000);
}
}
else //启动服务失败
{
OutputMsg( rmTip, _T("启动服务失败!") );
}
pLoggerSrv->Stop();
SafeDelete(pLoggerSrv);
return 0;
}
};
#endif
int main(int argc, char** argv)
{
#ifdef WIN32
SetUnhandledExceptionFilter( DefaultUnHandleExceptionFilter );
#endif
int nRetCode = 0;
InitDefMsgOut();
CoInitialize(NULL);
CCustomWorkSocket::InitSocketLib();
_setmbcp(_MB_CP_SBCS);
#ifdef WIN32
InstallThreadLocalePath("C");
#endif
#ifndef _SERVICE
#ifdef WIN32
SetCurrentDirectory("../");
#else
string filename(argv[1]);
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
ServiceMain(argc, argv);
#endif
CCustomWorkSocket::UnintSocketLib();
CoUninitialize();
UninitDefMsgOut();
#ifdef _MLIB_DUMP_MEMORY_LEAKS_
_CrtDumpMemoryLeaks();
#endif
return nRetCode;
}
#ifdef WIN32
VOID ServiceMain(int argc, char** argv)
{
LPTSTR sCmd = NULL;
if (argc >= 2)
{
sCmd = argv[1];
}
CLogService service("BackService");
service.Run(sCmd);
}
#endif
VOID ServerMain(int argc, char** argv)
{
// 创建 套接字服务类
if (!FDOP::IsDirectory(_T("log")))
{
FDOP::DeepCreateDirectory(_T("log"));
}
CFileLogger flog(_T("./log/BackStageServer_%s.log"), getCurrentTimeDesc());
char *pFileName =NULL;
if(argc >=2)
{
pFileName = argv[1];
}else
{
pFileName="BackStageServerLinux.txt";
}
CBackServerSocket* pBackServer = new CBackServerSocket(pFileName);
char *pBuff = (char*)malloc(256);
in_addr ia;
ia.s_addr = DBEGN_KN_VERION;
//strcpy(pBuff,_T("xhwl-后台"));
strcpy( pBuff,pBackServer->Config.SrvConf.szServiceName );
strcat(pBuff,"-V");
strcat(pBuff,inet_ntoa(ia));
SetConsoleTitle(pBuff);
free(pBuff);
// 启动服务
OutputMsg( rmTip, _T("正在启动后台服务……") );
if (pBackServer->Startup())
{
OutputMsg( rmTip, _T("启动后台服务成功!") );
while(TRUE)
{
char cmd[10];
scanf("%s",cmd);
if (strcmp(cmd,_T("exit")) == 0 || strcmp(cmd, _T("quit")) == 0)
{
break;
}
else if(_tcsncicmp(cmd,"dmp",3) ==0 )
{
DebugBreak();
}
Sleep(1000);
}
}
else //启动服务失败
{
OutputMsg( rmTip, _T("启动服务失败!") );
}
pBackServer->Stop();
SafeDelete(pBackServer);
}

View File

@@ -0,0 +1,9 @@
// stdafx.cpp : 只包括标准包含文件的源文件
// LoggerServer.pch 将作为预编译头
// stdafx.obj 将包含预编译类型信息
#include "stdafx.h"
// TODO: 在 STDAFX.H 中
// 引用任何所需的附加头文件,而不是在此文件中引用

View File

@@ -0,0 +1,67 @@
#pragma once
#include <stdio.h>
#include <stdlib.h>
#ifdef WIN32
#include <crtdbg.h>
#include <tchar.h>
#include <Windows.h>
#endif
#include <string>
#include <_ast.h>
#include <_memchk.h>
#include <Thread.h>
#include <CustomSocket.h>
#include <Lock.h>
#include <Tick.h>
#include <RefString.hpp>
#include <Stream.h>
#include <wrand.h>
#include <bzhash.h>
#include <vector>
using namespace std;
extern "C"
{
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>
}
#include <stdlib.h>
#include <_ast.h>
#include <_memchk.h>
#include <Tick.h>
#include <Lock.h>
#include <Stream.h>
#include <QueueList.h>
#include "ShareUtil.h"
#include "BufferAllocator.h"
#include "ObjectAllocator.hpp"
#include "SingleObjectAllocator.hpp"
#include "AppItnMsg.h"
#include <RefClass.hpp>
#include <RefString.hpp>
//#include "EDPass.h"
#include <CustomSocket.h>
#include "DataPacket.hpp"
#include "DataPacketReader.hpp"
#include "SendPackPool.h"
#include "CustomWorkSocket.h"
#include "CustomServerSocket.h"
#include "CustomServerClientSocket.h"
#include "ServerDef.h"
#include "CustomJXServerClientSocket.h"
#include "SQL.h"
#include "CustomLuaScript.h"
#include "CustomLuaConfig.h"
#include "BackHttpUtility.h"
#include "BackHttpServer.h"
#include "SrvConfig.h"
#include "BackClientSocket.h"
#include "BackServerSocket.h"
#include "FileLogger.h"
#include "LogType.h"
#include "DefExceptHander.h"
#include "FDOP.h"

78
server/CMakeLists.txt Normal file
View File

@@ -0,0 +1,78 @@
cmake_minimum_required (VERSION 2.8.1)
# Avoid warnings in higher versions
if("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" GREATER 2.6)
CMAKE_POLICY(VERSION 2.8)
endif()
MESSAGE(STATUS "Creating Project MMOServer; Running cmake version ${CMAKE_VERSION}")
# 项目名
PROJECT(MMOServer)
# 当前路径
set( Root_Dir ${PROJECT_SOURCE_DIR} )
#is or not shared type
if( BUILD_SHARED_LIBS )
SET ( LIBS_TYPE SHARED)
else()
SET ( LIBS_TYPE STATIC)
endif()
if ( ${CMAKE_BUILD_TYPE} STREQUAL "Release" )
set( _DEBUG 0 )
else ()
set( _DEBUG 1 )
endif()
message( "main ---- ROOT_PATH 1******************************-> ${ROOT_PATH}" )
message( "main ---- ROOT_PATH 1******************************-> ${ROOT_PATH}/../sdk/commonLib" )
set( ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR} )
# 子路径
#add_subdirectory(srvlib)
if(NOT SDK_DIR)
set( SDK_DIR ${CMAKE_SOURCE_DIR}/../sdk)
endif()
if( IS_DIRECTORY ${SDK_DIR} )
# 第二个cassdk.out参数用于指定外部文件夹在输出文件夹中的位置
add_subdirectory( ${SDK_DIR}/srvlib ../B/srvlib.out)
add_subdirectory( ${SDK_DIR}/commonLib ../B/commonLib.out)
else()
message(FATAL_ERROR "INVALID FOLDER 'SDK_DIR'=${SDK_DIR}" )
endif()
#add_subdirectory(${ROOT_PATH}/../sdk/commonLib)
add_subdirectory(LogicServer ../B/LogicServer.out)
add_subdirectory(DBServer ../B/DBServer.out)
add_subdirectory(LocalLogServer ../B/LocalLogServer.out)
add_subdirectory(LoggerServer ../B/LoggerServer.out)
add_subdirectory(NameServer ../B/NameServer.out)
add_subdirectory(BackStageServer ../B/BackStageServer.out)
add_subdirectory(SessionServer ../B/SessionServer.out)
add_subdirectory(robot ../B/robot.out)
set( ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR} )
if ( _DEBUG )
# message( status "ROOT_PATH ******************************-> ${ROOT_PATH}/../Exec/cp_d.sh" )
# set(SCRIPT_SETUP_SAMPLE "${ROOT_PATH}/../Exec/cp_d.sh")
else()
# message( status "ROOT_PATH -------------------------------> ${ROOT_PATH}/../Exec/cp.sh" )
# set(SCRIPT_SETUP_SAMPLE "${ROOT_PATH}/../Exec/cp.sh")
endif()
# execute_process(
# COMMAND ${SCRIPT_SETUP_SAMPLE}
# WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
# )
# message( status "ROOT_PATH -------------------------------> ${ROOT_PATH}/../Exec/ln.sh" )
# set(SCRIPT_SETUP_SAMPLE "${ROOT_PATH}/../Exec/ln.sh")
# execute_process(
# COMMAND ${SCRIPT_SETUP_SAMPLE}
# WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
# )

BIN
server/DBServer/.DS_Store vendored Normal file

Binary file not shown.

View File

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

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

@@ -0,0 +1,46 @@
{
// 使用 IntelliSense 了解相关属性。
// 悬停以查看现有属性的描述。
// 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "(gdb) 启动",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/../../build/DBServer/dbserver_d",
"args": ["${workspaceFolder}/../../build/DBServer/DBServerLinux.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/DBServer/dbserver_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/DBServer/.vscode/settings.json vendored Normal file
View File

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

View File

@@ -0,0 +1,247 @@
#include "StdAfx.h"
#include "../LogicDef.h"
#include "ActivityDb.h"
#include <vector>
void CLogicDBReqestHandler::LoadActivityList(CDataPacketReader &inPacket)
{
DECLARE_TIME_PROF("CLogicDBReqestHandler::LoadActivityList");
const int max_guild = 100;
int nRawServerId = 0, nLoginServerId = 0;
inPacket >> nRawServerId >> nLoginServerId;
CDataPacket& tmp = allocProtoPacket(dcLoadActivityList);
tmp << nRawServerId << nLoginServerId;
CDataPacket* out = &tmp;
//数据库连接是否就绪
if ( !m_pSQLConnection->Connected() )
{
(*out) << (BYTE)reDbErr;
}
else
{
//向数据库查询活动数据
int nError = m_pSQLConnection->Query(szSQLSP_LoadActivityData);
if ( !nError )
{
(*out) << (BYTE)reSucc;
MYSQL_ROW pRow = m_pSQLConnection->CurrentRow();
int nCount = m_pSQLConnection->GetRowCount();
INT_PTR pos = out->getPosition();
(*out) << (int)0;
nCount = 0;
GlobalActivityData activitydata;
while (pRow)
{
nCount++;
sscanf(pRow[0], "%u", &activitydata.nId);
sscanf(pRow[1], "%u", &activitydata.nActivityType);
sscanf(pRow[2], "%u", &activitydata.nTimeType);
unsigned int startTime,endTime;
sscanf(pRow[3], "%u", &startTime);
sscanf(pRow[4], "%u", &endTime);
activitydata.nStartTime = startTime;
activitydata.nEndTime = endTime;
out->writeBuf(&activitydata,sizeof(activitydata));
pRow = m_pSQLConnection->NextRow();
}
int* pCount = (int*)out->getPositionPtr(pos);
*pCount = nCount;
m_pSQLConnection->ResetQuery();
}
else
{
(*out) << (BYTE)reDbErr;
}
}
flushProtoPacket((*out));
}
void CLogicDBReqestHandler::SaveActivityList(CDataPacketReader &inPacket)
{
DECLARE_TIME_PROF("CLogicDBReqestHandler::SaveActivityList");
int nRawServerId = 0, nLoginServerId = 0;
inPacket >> nRawServerId >> nLoginServerId;
//数据库连接是否就绪
if ( !m_pSQLConnection->Connected() )
{
return;
}
else
{
int nErrorCode = m_pSQLConnection->Exec(szSQLSP_DeleteActivityData);
if (!nErrorCode)
{
m_pSQLConnection->ResetQuery();
}
char buff[1024];
strcpy(m_pHugeSQLBuffer, szSQLSP_SaveActivityData); //表头放这里
int nCount = 0;
inPacket >> nCount;
GlobalActivityData activitydata;
for(int i = 0; i < nCount; ++i)
{
inPacket.readBuf(&activitydata,sizeof(activitydata));
OutputMsg(rmTip,"[Global Activity] 活动存储(%d)活动Type=%d, 活动ID=%d !", i, activitydata.nActivityType, activitydata.nId);
strcat(m_pHugeSQLBuffer, " (");
sprintf(buff, "%u,%u,%u,%u,%u", activitydata.nId, activitydata.nActivityType, activitydata.nTimeType, (unsigned int)activitydata.nStartTime, (unsigned int)activitydata.nEndTime);
strcat(m_pHugeSQLBuffer, buff);
strcat(m_pHugeSQLBuffer, " )");
if(i < nCount-1)
{
strcat(m_pHugeSQLBuffer,",");
}
}
nErrorCode = m_pSQLConnection->Exec(m_pHugeSQLBuffer);
if(!nErrorCode)
{
m_pSQLConnection->ResetQuery();
}
}
}
void CLogicDBReqestHandler::LoadActorActivity(CDataPacketReader &inPacket, unsigned int nActorID, int nRawServerId, int nLoginServerId)
{
CDataPacket& out = allocProtoPacket(dcLoadPersonActivity);
out << nRawServerId << nLoginServerId;
out << nActorID;
static std::vector<PersonStopedActivity> arrStopActivity;
arrStopActivity.clear();
//数据库连接是否就绪
if ( !m_pSQLConnection->Connected() )
{
out << (BYTE)reDbErr;
}
else
{
int nError = m_pSQLConnection->Query(szSQLSP_LoadActorActivityData, nActorID);
if ( !nError )
{
out << (BYTE)reSucc;
MYSQL_ROW pRow = m_pSQLConnection->CurrentRow();
int nCount = m_pSQLConnection->GetRowCount();
INT_PTR pos = out.getPosition();
out << (int)0;
nCount = 0;
PersonActivtyData activitydata;
PersonStopedActivity stopdata;
while (pRow)
{
sscanf(pRow[0], "%u", &activitydata.nId);
sscanf(pRow[1], "%u", &activitydata.nActivityType);
int nExpiredTime;
sscanf(pRow[2], "%d", &nExpiredTime);
activitydata.nExpiredTime = (unsigned int)nExpiredTime;
if (nExpiredTime == -1)//活动已结束
{
stopdata.nId = activitydata.nId;
stopdata.nActivityType = activitydata.nActivityType;
arrStopActivity.push_back(stopdata);
}
else
{
nCount++;
out.writeBuf(&activitydata,sizeof(activitydata));
}
pRow = m_pSQLConnection->NextRow();
}
int* pCount = (int*)out.getPositionPtr(pos);
*pCount = nCount;
m_pSQLConnection->ResetQuery();
// 把结束的活动丢入
nCount = (int)arrStopActivity.size();
out << nCount;
for (int i = 0; i < nCount; i++)
{
out.writeBuf(&arrStopActivity[i],sizeof(stopdata));
}
}
else
{
out << (BYTE)reDbErr;
}
}
flushProtoPacket(out);
}
void CLogicDBReqestHandler::SaveActorActivity(CDataPacketReader &inPacket, unsigned int nActorID, int nRawServerId, int nLoginServerId)
{
DECLARE_TIME_PROF("CLogicDBReqestHandler::SaveActorActivity");
//数据库连接是否就绪
if ( !m_pSQLConnection->Connected() )
{
return;
}
else
{
char buff[1024];
strcpy(m_pHugeSQLBuffer, szSQLSP_SaveActorActivityData); //表头放这里
PersonActivtyData activitydata;
PersonStopedActivity stopdata;
bool hasActivity = false;
// 保存运行中的
int nCount = 0;
inPacket >> nCount;
for(int i = 0; i < nCount; ++i)
{
inPacket.readBuf(&activitydata,sizeof(activitydata));
strcat(m_pHugeSQLBuffer, " (");
sprintf(buff, "%u,%u,%u,%u", nActorID, activitydata.nId, activitydata.nActivityType, (unsigned int)activitydata.nExpiredTime);
strcat(m_pHugeSQLBuffer, buff);
strcat(m_pHugeSQLBuffer, " )");
if(i < nCount-1)
{
strcat(m_pHugeSQLBuffer,",");
}
hasActivity = true;
}
// printf("%s\n",m_pHugeSQLBuffer);
// 保存结束的
nCount = 0;
if (inPacket.getAvaliableLength() > 4)
inPacket >> nCount;
unsigned int temp = (unsigned int)-1;
int nId = 0;
int nActivityType = 0;
for(int i = 0; i < nCount; ++i)
{
inPacket >> nId ; //id
inPacket >> nActivityType; //type
// inPacket.readBuf(&stopdata,sizeof(stopdata));
if(hasActivity)
strcat(m_pHugeSQLBuffer, ",");
strcat(m_pHugeSQLBuffer, "(");
sprintf(buff, "%u,%u,%u,%d", nActorID, nId, nActivityType, -1);
strcat(m_pHugeSQLBuffer, buff);
strcat(m_pHugeSQLBuffer, " )");
// if(i < nCount-1)
// {
// strcat(m_pHugeSQLBuffer,",");
// }
hasActivity = true;
}
// printf("%s\n",m_pHugeSQLBuffer);
if (hasActivity)
{
int nErrorCode = m_pSQLConnection->Exec(m_pHugeSQLBuffer);
if(!nErrorCode)
{
m_pSQLConnection->ResetQuery();
}
}
}
}

View File

@@ -0,0 +1,110 @@
#include "StdAfx.h"
#include "../LogicDef.h"
#include "BossData.h"
#include <vector>
void CLogicDBReqestHandler::LoadBossList(CDataPacketReader &inPacket)
{
DECLARE_TIME_PROF("CLogicDBReqestHandler::LoadBossList");
const int max_guild = 100;
int nRawServerId = 0, nLoginServerId = 0;
inPacket >> nRawServerId >> nLoginServerId;
CDataPacket& tmp = allocProtoPacket(dcLoadBossInfo);
tmp << nRawServerId << nLoginServerId;
CDataPacket* out = &tmp;
//数据库连接是否就绪
if ( !m_pSQLConnection->Connected() )
{
(*out) << (BYTE)reDbErr;
}
else
{
//向数据库查询活动数据
int nError = m_pSQLConnection->Query(szSQLSP_LoadBossData);
if ( !nError )
{
(*out) << (BYTE)reSucc;
MYSQL_ROW pRow = m_pSQLConnection->CurrentRow();
int nCount = m_pSQLConnection->GetRowCount();
INT_PTR pos = out->getPosition();
(*out) << (int)0;
nCount = 0;
GLOBALBOSSINFO bossData;
while (pRow)
{
nCount++;
sscanf(pRow[0], "%d", &bossData.nBossId);
sscanf(pRow[1], "%d", &bossData.nReferTime);
sscanf(pRow[2], "%d", &bossData.nDeath);
sscanf(pRow[3], "%d", &bossData.nBossLv);
out->writeBuf(&bossData,sizeof(bossData));
pRow = m_pSQLConnection->NextRow();
}
int* pCount = (int*)out->getPositionPtr(pos);
*pCount = nCount;
m_pSQLConnection->ResetQuery();
}
else
{
(*out) << (BYTE)reDbErr;
}
}
flushProtoPacket((*out));
}
void CLogicDBReqestHandler::SaveBossList(CDataPacketReader &inPacket)
{
DECLARE_TIME_PROF("CLogicDBReqestHandler::SaveBossList");
int nRawServerId = 0, nLoginServerId = 0;
inPacket >> nRawServerId >> nLoginServerId;
//数据库连接是否就绪
if ( !m_pSQLConnection->Connected() )
{
return;
}
else
{
int nErrorCode = m_pSQLConnection->Exec(szSQLSP_DeleteBossData);
if (!nErrorCode)
{
m_pSQLConnection->ResetQuery();
}
char buff[1024];
strcpy(m_pHugeSQLBuffer, szSQLSP_SaveBossData); //表头放这里
int nCount = 0;
inPacket >> nCount;
GLOBALBOSSINFO boss;
for(int i = 0; i < nCount; ++i)
{
inPacket.readBuf(&boss,sizeof(boss));
strcat(m_pHugeSQLBuffer, " (");
sprintf(buff, "%u,%u,%u,%u,%u", boss.nBossId, boss.nReferTime, boss.nDeath, boss.nBossLv);
strcat(m_pHugeSQLBuffer, buff);
strcat(m_pHugeSQLBuffer, " )");
if(i < nCount-1)
{
strcat(m_pHugeSQLBuffer,",");
}
}
nErrorCode = m_pSQLConnection->Exec(m_pHugeSQLBuffer);
if(!nErrorCode)
{
m_pSQLConnection->ResetQuery();
}
}
}
void CLogicDBReqestHandler::LoadActorBossList(CDataPacketReader &inPacket, unsigned int nActorID, int nRawServerId, int nLoginServerId)
{
}
void CLogicDBReqestHandler::SaveActorBossList(CDataPacketReader &inPacket, unsigned int nActorID, int nRawServerId, int nLoginServerId)
{
DECLARE_TIME_PROF("CLogicDBReqestHandler::SaveActorBossList");
}

View File

@@ -0,0 +1,96 @@
cmake_minimum_required(VERSION 2.6)
project(DBServer)
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}")
#set(CMAKE_BUILD_TYPE "Debug")
if( NOT CMAKE_BUILD_TYPE )
set(CMAKE_BUILD_TYPE "Release")
endif()
add_definitions(-D_GNU_SOURCE -D_REENTRANT)
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( CMAKE_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../sdk) # include 文件夹
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 -lrt -D_DEBUG")
set(CMAKE_CXX_FLAGS_RELEASE "$ENV{CXXFLAGS} -O0 -w -ggdb -g2 -fPIC -z muldefs -lrt")
#include_directories(
# ${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}/../srvlib/include
# ${CMAKE_CURRENT_SOURCE_DIR}/../../common/cpp/libs/src/wylib/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}/../LogicServer/property
# ${CMAKE_CURRENT_SOURCE_DIR}
#)
message( status "DBServer ---- ROOT_PATH 1******************************-> ${ROOT_PATH}" )
message( status "DBServer ---- ROOT_PATH 2******************************-> ${CMAKE_INCLUDE_DIR}" )
message( status "DBServer ---- ROOT_PATH 3******************************-> ${CMAKE_INCLUDE_DIR}/commonLib/include" )
message( status "DBServer ---- ROOT_PATH 3******************************-> ${CMAKE_INCLUDE_DIR}/commonLib/def" )
include_directories(
${CMAKE_INCLUDE_DIR}/public
${CMAKE_INCLUDE_DIR}/system
${CMAKE_INCLUDE_DIR}/utils
${CMAKE_INCLUDE_DIR}/srvlib/include
# ${CMAKE_CURRENT_SOURCE_DIR}/src/wylib/include
${CMAKE_INCLUDE_DIR}/lua-5.1/src
${CMAKE_INCLUDE_DIR}/tolua++/src
${CMAKE_INCLUDE_DIR}/mysql-5.2/include
${CMAKE_INCLUDE_DIR}/breakpad/
${CMAKE_INCLUDE_DIR}/commonLib/include
${CMAKE_INCLUDE_DIR}/commonLib/def
${CMAKE_INCLUDE_DIR}/system
${CMAKE_INCLUDE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/../LogicServer/property
${CMAKE_CURRENT_SOURCE_DIR}
)
file(GLOB sources1 *.cpp */*.cpp)
if ( ${CMAKE_BUILD_TYPE} STREQUAL "Release" )
set( _DEBUG 0 )
else ()
set( _DEBUG 1 )
endif()
if ( _DEBUG )
#add_executable(dbserver_d ${sources})
set( EXE_NAME dbserver_d )
else()
#add_executable(dbserver_r ${sources})
set( EXE_NAME dbserver_r )
endif()
SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/../../Exec/DBServer)
add_executable(${EXE_NAME} ${sources1})
include(../../sdk/cmake/libs.cmake)#ccc
#include(../common/cmake/libs.cmake)

View File

@@ -0,0 +1,2 @@
lua.exe ChangeDBServerVersion.lua
:: pause

View File

@@ -0,0 +1,24 @@
local fileName = 'main.cpp'
local file = io.open(fileName, 'r')
local strSrc = file:read('*a')
file:close()
local strVersionPattern = '#define%s+DBEGN_KN_VERION%s+MAKEFOURCC%s*%(%s*%d+%s*,%s*%d+%s*,%s*%d+%s*,%s*%d+%s*%)'
local strVersion = strSrc:match(strVersionPattern)
-- print(strVersion)
local y, m, d, t = strVersion:match( '%(%s*(%d+)%s*,%s*(%d+)%s*,%s*(%d+)%s*,%s*(%d+)%s*%)')
-- print(y, m, d, t )
local nowM, nowD,nowY = string.match(os.date(), '(%d+)/(%d+)/(%d+)')
-- print(nowY, nowM, nowD)
if y == nowY and m == nowM and d == nowD then
t = tonumber(t) + 1
else
t = 1
end
local strNewVersion = strVersion:gsub('%(%s*%d+%s*,%s*%d+%s*,%s*%d+%s*,%s*%d+%s*%)', string.format('(%s, %s, %s, %d)', nowY, nowM, nowD, t))
-- print(strNewVersion)
strSrc = strSrc:gsub(strVersionPattern, strNewVersion)
-- print(strSrc)
-- print(nowY, nowM, nowD, t)
file = io.open(fileName, 'w')
file:write(strSrc)
file:close()

View File

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

View File

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

View File

@@ -0,0 +1,283 @@
#include "StdAfx.h"
using namespace jxSrvDef;
using namespace jxInterSrvComm;
CDBCenterClient::CDBCenterClient(CDBServer *pDBEngine)
{
m_pDBEngine = pDBEngine;
SetClientName(_T("DBCenter服务器"));
m_vFreeList.setLock(&m_vFreeListLock);
}
CDBCenterClient::~CDBCenterClient()
{
m_vFreeList.flush();
for (INT_PTR i = 0; i < m_vFreeList.count(); i++)
{
CDataPacket* dp = m_vFreeList[i];
dp->setPosition(0);
flushSendPacket(*dp);
}
m_vFreeList.clear();
}
CDataPacket& CDBCenterClient::AllocDataPacket(const jxSrvDef::INTERSRVCMD nCmd)
{
return allocProtoPacket(nCmd);
}
void CDBCenterClient::FlushDataPacket(CDataPacket &packet)
{
return flushProtoPacket(packet);
}
void CDBCenterClient::Init()
{
//m_pGateMgr = m_pDBEngine->getGateManager();
//m_pSQLConn = m_pGateMgr->GetSQLConnectionPtr();
CDBDataServer *pDataServer = m_pDBEngine->getDataServer();
m_pSQLConn = pDataServer->GetSQLConnection();
m_sDataHandler.Start(this, m_pSQLConn);
m_loginHandler.Init(m_pSQLConn, pDataServer);
}
void CDBCenterClient::Stop()
{
m_sDataHandler.Stop();
}
VOID CDBCenterClient::DispatchInternalMessage(UINT uMsg, UINT64 uParam1, UINT64 uParam2, UINT64 uParam3, UINT64 uParam4)
{
//Inherited::DispatchInternalMessage(uMsg, uParam1, uParam2, uParam3);
switch (uMsg)
{
case DBC_INTERNAL_UPDATECLIENTLIST:
UpdateLogicClientList((INT_PTR)uParam1, (int *)uParam2);
break;
default:
break;
}
}
void CDBCenterClient::PostUpdateLogicClientList(const CBaseList<int> &serverIdList)
{
int nCount = (int)serverIdList.count();
int *data = NULL;
if (nCount > 0)
{
data = (int *)m_Allocator.AllocBuffer(sizeof(int) * nCount);
int *pIter = data;
CopyMemory(pIter, (int *)serverIdList, sizeof(int)*nCount);
}
PostInternalMessage(DBC_INTERNAL_UPDATECLIENTLIST, nCount, (UINT_PTR)data, 0);
}
void CDBCenterClient::UpdateLogicClientList(INT_PTR nCount, int *idList)
{
if (connected())
{
CDataPacket &packet = AllocDataPacket(DB2DC_UpdateLogicClientList);
packet << (int)nCount;
//OutputMsg(rmTip, _T("%s 更新连接的逻辑服务器客户端列表,数量为:%d"), __FUNCTION__, (int)nCount);
if (nCount > 0)
{
packet.writeBuf(idList, sizeof(int) * nCount);
}
FlushDataPacket(packet);
}
if (nCount > 0)
{
m_Allocator.FreeBuffer(idList);
}
}
VOID CDBCenterClient::OnDispatchRecvPacket(const jxSrvDef::INTERSRVCMD nCmd, CDataPacketReader &inPacket)
{
if (nCmd < 0)
{
OutputMsg(rmWaning, _T("%s recv unknown msg[id=%d]"), __FUNCTION__, (int)nCmd);
return;
}
if(nCmd == DBCenterHeartBeat )
{
return;
}
//是登陆的消息包,要最优先处理,让玩家迅速能够拿到角色列表
if(nCmd >= dcGetActorList && nCmd < dcLoginMsgMax)
{
//CDataPacket& out = allocProtoPacket(nCmd);
m_loginHandler.OnRecvLoginMsg(nCmd,inPacket,this); //处理登陆消息,不做缓存,立刻处理
//flushProtoPacket(out);
return;
}
else
{
m_sDataHandler.AddMessage(nCmd, inPacket);
}
/*
switch (nCmd)
{
case DBCenterHeartBeat:
break;
case DBCenterGateRequest:
HandleDBGateRequest(inPacket);
break;
case DBCenterLogicRequest:
HandleLogicRequest(inPacket);
break;
default:
OutputMsg(rmError, _T("%s recv unknown recv unknown msg[id=%d]"), __FUNCTION__, (int)nCmd);
break;
}
*/
}
void CDBCenterClient::HandleDBGateRequest(CDataPacketReader &inPacket)
{
INTERSRVCMD nCmd;
inPacket >> nCmd;
switch (nCmd)
{
case DbServerProto::DC2DB_QueryActorList:
OnRecvQueryActorList(inPacket);
break;
case DbServerProto::DC2DB_EnterGame:
OnRecvEnterGame(inPacket);
break;
default:
break;
}
OutputMsg(rmTip, _T("%s recv dbgate msg(id=%d)"), __FUNCTION__, nCmd);
}
void CDBCenterClient::OnRecvEnterGame(CDataPacketReader &inPacket)
{
int nAccountId, nLoginServerId, nRawServerId;
unsigned int nActorId = 0;
ACCOUNT szAccountName;
char szIP[32] = {0};
__int64 nIP;
inPacket >> nAccountId >> nLoginServerId >> nRawServerId >> nActorId >> nIP;
inPacket.readString(szAccountName, ArrayCount(szAccountName));
inPacket.readString(szIP, ArrayCount(szIP));
int nError;
CDataPacket &packet = AllocDataPacket(DbServerProto::DB2DC_EnterGameAck);
packet << nAccountId << nActorId;
if (!m_pSQLConn->Connected())
{
OutputMsg(rmError, _T("%s 数据库连接没就绪!"), __FUNCTION__);
nError = ERR_SQL;
}
else
{
nError = m_gateDBReqHandler.StartEnterGame(nLoginServerId,
nRawServerId,
nAccountId,
nActorId,
szAccountName,
nIP);
if (nError)
nError = ERR_NOUSER;
}
if (!nError)
{
/*
char szActorId[32];
sprintf_s(szActorId, sizeof(szActorId), "%d", nActorId);
m_pDBEngine->getLogClient()->SendLoginLog(ltEntryGame,
nAccountId,
szAccountName,
szIP,
szActorId);
*/
}
char szGateIP[128];
INT_PTR nGatePort;
if ( !m_pDBEngine->SelectGameServerRoute(nLoginServerId, szGateIP, ArrayCount(szGateIP), &nGatePort))
{
OutputMsg( rmError, _T("%s 无匹配的路由数据, ServerId=%d!"), __FUNCTION__, nLoginServerId);
nError = ERR_NOGATE;
}
// Response Ack Msg: AccountId | ActorId | ErrorCode(char) | RouteIP(string) | RoutePort(int)
packet << (char)nError;
if (!nError)
{
packet.writeString(szGateIP);
packet << (int)nGatePort;
}
FlushDataPacket(packet);
}
void CDBCenterClient::OnRecvQueryActorList(CDataPacketReader &inPacket)
{
unsigned int nAccountId;
int nServerIndex;
inPacket >> nAccountId >> nServerIndex;
CDataPacket &packet = AllocDataPacket(DbServerProto::DB2DC_QueryActorListAck);
packet << (WORD)QUERYACTORLISTRESP_CMD << nAccountId;
m_gateDBReqHandler.GetActorList(nAccountId, nServerIndex,packet);
FlushDataPacket(packet);
}
void CDBCenterClient::HandleLogicRequest(CDataPacketReader &inPacket)
{
WORD nCmd = -1;
inPacket >> nCmd;
m_sDataHandler.AddMessage(nCmd, inPacket);
}
SERVERTYPE CDBCenterClient::getLocalServerType()
{
return DBServer;
}
int CDBCenterClient::getLocalServerIndex()
{
return m_pDBEngine->getServerIndex();
}
LPCSTR CDBCenterClient::getLocalServerName()
{
return m_pDBEngine->getServerName();
}
CDataPacket* CDBCenterClient::AllocSendPacket()
{
if (m_vFreeList.count() <= 0)
{
m_vFreeList.flush();
}
if (m_vFreeList.count() <= 0)
{
allocSendPacketList(m_vFreeList,512);
}
CDataPacket* m_TempData = m_vFreeList.pop();
m_TempData->setLength(0);
return m_TempData;
}
void CDBCenterClient::FreeBackUserDataPacket(CDataPacket *pPacket)
{
m_vFreeList.append(pPacket);
}

View File

@@ -0,0 +1,140 @@
#ifndef DBCENTER_CLIENT_H_
#define DBCENTER_CLIENT_H_
/*
连接DBCenter的Client封装类。
*/
class CDBServer;
class CDBGateManager;
class CDBDataServer;
class CDBCenterClient : public CCustomJXClientSocket,
public ILogicDBRequestHost
{
public:
typedef CCustomJXClientSocket Inherited;
public:
CDBCenterClient(CDBServer *pDBEngine);
virtual ~CDBCenterClient();
void Init();
void Stop();
/*
* Comments: 投递更新连接的逻辑服务器列表消息
* Param const CBaseList<int> & serverIdList:
* @Return void:
* @Remark:
*/
void PostUpdateLogicClientList(const CBaseList<int> &serverIdList);
/*
* Comments: 更新本DBServer连接的逻辑客户端列表
* Param INT_PTR nCount: 连接的逻辑服务器客户端数量
* Param int *idList: 连接的逻辑服务器ID列表
* @Return void:
* @Remark:
*/
void UpdateLogicClientList(INT_PTR nCount, int *idList);
/*
* Comments: 回收空闲的CDataPacket类
* Param CDataPacket * pPacket:
* @Return void:
* @Remark: CommonClient收到来自CommonServer的数据包之后本地分配数据包对象将内容缓存起来然后通过逻辑线程处理。
逻辑线程处理完数据后,调用此接口释放数据包对象。
*/
void FreeBackUserDataPacket(CDataPacket* pPacket);
//////////////////////////////////////////////////////////////////////////
// ILogicDBRequestHost
virtual CDataPacket& AllocDataPacket(const jxSrvDef::INTERSRVCMD nCmd);
virtual void FlushDataPacket(CDataPacket &packet);
virtual int CatchCreateGuild(int nActor,
LPCSTR sGuildName,
LPCSTR sFoundName,
int nIndex,
Uint64 hActor,
BYTE nZY,
INT_PTR nIcon)
{
return 0;
}
//追踪内存
void Trace()
{
OutputMsg(rmNormal,"---------------CDBCenterClient Trace...------");
m_sDataHandler.Trace();
OutputMsg(rmNormal,"---------------CDBCenterClient Trace end-----");
}
protected:
////////////////////////////////////////////////////////////////////////////////////////////////////
// Virtual Function Of CCustomJXClientSocket
virtual LPCSTR getLocalServerName();
virtual jxSrvDef::SERVERTYPE getLocalServerType();
//TODO. 临时测试用。DBServer不需要这个而是需要自己维护DB连接的逻辑服务器ID的列表
virtual int getLocalServerIndex();
virtual VOID OnDispatchRecvPacket(const jxSrvDef::INTERSRVCMD nCmd, CDataPacketReader &inPacket);
virtual VOID DispatchInternalMessage(UINT uMsg, UINT64 uParam1, UINT64 uParam2, UINT64 uParam3, UINT64 uParam4);
/*
* Comments: 处理DBCenter转发的网关请求
* Param CDataPacketReader & inPacket:
* @Return void:
* @Remark: 来自DBCenter转发的网关请求包括选择角色、创建角色、删除角色等等。是用户登录游戏和进入游戏之间的
DB请求。
*/
void HandleDBGateRequest(CDataPacketReader &inPacket);
/*
* Comments: 接收查询角色列表请求
* Param CDataPacketReader & inPacket:
* @Return void:
* @Remark:
*/
void OnRecvQueryActorList(CDataPacketReader &inPacket);
/*
* Comments: 接收进入游戏请求
* Param CDataPacketReader & inPacket:
* @Return void:
* @Remark:
*/
void OnRecvEnterGame(CDataPacketReader &inPacket);
/*
* Comments: 处理DBCenter转发的逻辑请求。
* Param CDataPacketReader & inPacket:
* @Return void:
* @Remark:
*/
void HandleLogicRequest(CDataPacketReader &inPacket);
/*
* Comments: 分配数据包,用于存储接收到的数据
* @Return CDataPacket*:
* @Remark: 接收线程接收到数据并非立即处理,而是缓存起来,交给逻辑线程统一处理
*/
CDataPacket* AllocSendPacket();
private:
static const int DBC_INTERNAL_UPDATECLIENTLIST = 101; // 更新连接的逻辑客户端列表内部消息
private:
CDBServer *m_pDBEngine;
CDBGateManager *m_pGateMgr;
CGateDBReqestHandler m_gateDBReqHandler;
CDBDataClientHandler m_sDataHandler; // DB请求处理类
CGateDBReqestHandler m_loginHandler;
//CLogicDBReqestHandler m_logicDBReqHandler;
CSQLConenction *m_pSQLConn;
CQueueList<CDataPacket*> m_vFreeList;
CCSLock m_vFreeListLock;
};
#endif

View File

@@ -0,0 +1,229 @@

#include "StdAfx.h"
CDBConfig::CDBConfig(void)
{
}
CDBConfig::~CDBConfig(void)
{
}
//读取跨服配置表
bool CDBConfig::LoadCrossServerConfig()
{
/*
bool result = false;
CMemoryStream ms;
try
{
if ( ms.loadFromFile("crossserver.txt") <= 0 )
{
showError(_T("unable to load config from file crossserver.txt"));
return result;
}
if ( !setScript((LPCSTR)ms.getMemory()) )
{
showError(_T("parse config script failed"));
return false;
}
if ( openGlobalTable("crossserver"))
{
int nCenterServerIndex = 0;
if ( openFieldTable("map"))
{
size_t nCount = lua_objlen(m_pLua,-1);
if ( enumTableFirst() )
{
do
{
int nStart = getFieldInt("start");
int nEnd = getFieldInt("idend");
int nCenterid = getFieldInt("centerid");
if(ServerIndex >= nStart && ServerIndex <= nEnd && ServerIndex != nCenterid)
{
nCenterServerIndex = nCenterid;
//break;
}
}while (enumTableNext());
}
closeTable();
}
if(nCenterServerIndex > 0)
{
if ( openFieldTable("center"))
{
size_t nCount = lua_objlen(m_pLua,-1);
if ( enumTableFirst() )
{
ZeroMemory(&DBCenterAddr, sizeof(DBCenterAddr));
INT_PTR nIdx = 0;
do
{
// 读取DBCenter服务器配置
int nServerId = getFieldInt("id");
if(nServerId == nCenterServerIndex)
{
getFieldStringBuffer("commondbsrv", DBCenterAddr.szAddr, sizeof(DBCenterAddr.szAddr));
DBCenterAddr.nPort = getFieldInt("dbport");
// break;
}
nIdx++;
}while (enumTableNext());
}
closeTable();//GateService
}
}
closeTable();//关闭DBServer
}
}
catch(RefString &s)
{
OutputMsg( rmNormal, s.rawStr() );
}
catch(...)
{
OutputMsg( rmNormal, _T("unexpected error on load config") );
}
*/
//数据服不再读取配置了
return true;
}
bool CDBConfig::ReadConfig(const char *pszConfigFileName)
{
if (!pszConfigFileName)
pszConfigFileName = "DBServerLinux.txt";
bool result = false;
CMemoryStream ms;
try
{
if ( ms.loadFromFile(pszConfigFileName) <= 0 )
// if ( ms.loadFromFile("E:/WorkSpace/WorkSVN/tcgp/trunk/Phoenix/server/build/DBServer/DBServer.txt") <= 0 )
{
showError(_T("unable to load config from file DBServerLinux.txt"));
return result;
}
if ( !setScript((LPCSTR)ms.getMemory()) )
{
showError(_T("parse config script failed"));
return false;
}
if ( openGlobalTable("DBServer"))
{
getFieldStringBuffer(("ServerName"), ServerName,sizeof(ServerName));
ServerIndex = getFieldInt("ServerIndex");
getFieldStringBuffer("BoyNameFile", m_sPrefixList, sizeof(m_sPrefixList));
//getFieldStringBuffer("NameConnectList", m_sConnectList, sizeof(m_sConnectList));
getFieldStringBuffer("GirlNameFile", m_sStuffixList, sizeof(m_sStuffixList));
LPCTSTR stemp = getFieldString("EsqlToolPath","D:\\cqAdmin\\ESQL\\ESQLTool.exe");
_asncpytA(m_EsqlToolPath,stemp);
m_EsqlToolPath[sizeof(m_EsqlToolPath)-1] = 0;
int nDef =0;
DbConf.boUtf8= getFieldInt("utf8", &nDef ) ?true:false; //数据库的编码是不是utf8
if ( openFieldTable("GateService"))
{
getFieldStringBuffer(("Address"), GateAddr.szAddr,sizeof(GateAddr.szAddr));
GateAddr.nPort = getFieldInt("Port");
closeTable();//GateService
}
if ( openFieldTable("DBService"))
{
getFieldStringBuffer(("Address"), DataAddr.szAddr,sizeof(DataAddr.szAddr));
DataAddr.nPort = getFieldInt("Port");
closeTable();//DBService
}
if ( openFieldTable("LogServer"))
{
getFieldStringBuffer(("Address"), LogAddr.szAddr,sizeof(LogAddr.szAddr));
LogAddr.nPort = getFieldInt("Port");
closeTable();//LogServer
}
/*
if ( openFieldTable("SessionServer"))
{
getFieldStringBuffer(("Address"), SessionAddr.szAddr,sizeof(SessionAddr.szAddr));
SessionAddr.nPort = getFieldInt("Port");
closeTable();//SessionServer
}
*/
if ( openFieldTable("NameServer"))
{
getFieldStringBuffer(("Address"), NameAddr.szAddr,sizeof(NameAddr.szAddr));
NameAddr.nPort = getFieldInt("Port");
closeTable();//NameServer
}
// 读取DBCenter服务器配置
/*
去掉了dbsencter的读取
ZeroMemory(&DBCenterAddr, sizeof(DBCenterAddr));
if (feildTableExists("DBCenter") && openFieldTable("DBCenter"))
{
getFieldStringBuffer("Address", DBCenterAddr.szAddr, sizeof(DBCenterAddr.szAddr));
DBCenterAddr.nPort = getFieldInt("Port");
closeTable();
}
*/
if ( openFieldTable("SQL"))
{
getFieldStringBuffer(("Host"), DbConf.szHost,sizeof(DbConf.szHost));
DbConf.nPort = getFieldInt("Port");
getFieldStringBuffer(("DBName"), DbConf.szDbName,sizeof(DbConf.szDbName));
getFieldStringBuffer(("DBUser"), DbConf.szUser,sizeof(DbConf.szUser));
char szTemp[100];
//getFieldStringBuffer(("DBPass"), szTemp,sizeof(szTemp));
// getFieldStringBuffer(("Key"), DbConf.szKey,sizeof(DbConf.szKey));
//密码要解密
//DecryptPassword(DbConf.szPassWord,sizeof(DbConf.szPassWord),szTemp,"123456abc123456a");
getFieldStringBuffer(("DBPass"), DbConf.szPassWord,sizeof(DbConf.szPassWord));
closeTable();//DB
result = true;
}
closeTable();//关闭DBServer
}
}
catch(RefString &s)
{
OutputMsg( rmNormal, s.rawStr() );
}
catch(...)
{
OutputMsg( rmNormal, _T("unexpected error on load config") );
}
if(result)
{
result = LoadCrossServerConfig();
}
return result;
}
void CDBConfig::ShowError(const LPCTSTR sError)
{
m_sLastErrDesc = sError;
RefString sErr;
sErr = _T("[Configuration Error]");
sErr += sError;
//集中处理错误为了简单起见此处直接抛出异常。异常会在readConfig中被捕获从而立刻跳出对配置的循环读取。
throw sErr;
}

View File

@@ -0,0 +1,60 @@
#ifndef _DB_CONFIG_H_
#define _DB_CONFIG_H_
class CCustomLuaConfig;
typedef struct AddrPortConf
{
char szAddr[20];
int nPort;
} ADDRPORTCONF,*PADDRPORTCONF;
typedef struct DbConf{
char szHost[20];
int nPort;
char szDbName[20];
char szUser[20];
char szPassWord[128];
char szKey[17];//用于解密的key16位
int boUtf8;
}DBCONF,*PDBCONF;
class CDBConfig:
public CCustomLuaConfig
{
public:
/*
* 只读取同目录下的指定配置文件
*/
bool ReadConfig(const char *pszConfigFileName);
//装置跨服配置文件
bool LoadCrossServerConfig();
public:
CDBConfig(void);
~CDBConfig(void);
public:
char ServerName[128];
int ServerIndex;
ADDRPORTCONF GateAddr;
ADDRPORTCONF DataAddr;
ADDRPORTCONF LogAddr;
ADDRPORTCONF SessionAddr;
ADDRPORTCONF NameAddr;
ADDRPORTCONF DBCenterAddr;
DBCONF DbConf;
CHAR m_EsqlToolPath[128]; //esqltool的配置路径
CHAR m_sPrefixList[32];
//CHAR m_sConnectList[32];
CHAR m_sStuffixList[32];
protected:
void ShowError(const LPCTSTR sError);
};
#endif

View File

@@ -0,0 +1,582 @@
#include "StdAfx.h"
void CActorCacheData::PostponeNextSaveTick()
{
m_nNextSaveTick = _getTickCount() + CDBDataCache::s_nActorCacheSaveInterval;
}
//const TICKCOUNT CActorCacheData::s_nExpireTime = 20; // for test
//const TICKCOUNT CDBDataCache::s_nCheckInterval = 1000; // for test
//TICKCOUNT CDBDataCache::s_nActorCacheSaveInterval = 5000; // for test
const TICKCOUNT CActorCacheData::s_nExpireTime = 15 * CMiniDateTime::SecOfMin * 1000;
const TICKCOUNT CDBDataCache::s_nCheckInterval = 5 * 1000;
TICKCOUNT CDBDataCache::s_nActorCacheSaveInterval = 20000;//10 * CMiniDateTime::SecOfMin * 1000;
//s_aActorCacheHandler与s_aCDT2RespSrvCmdID顺序要一一对应
const CDBDataCache::SaveHandler CDBDataCache::s_aActorCacheHandler[] = {
&CDBDataCache::SaveActorBasicData,
&CDBDataCache::SaveBagItemData,
&CDBDataCache::SaveEquipItemData,
&CDBDataCache::SaveDepotItemData,
&CDBDataCache::SavePetItemData,
&CDBDataCache::SaveSkillData,
&CDBDataCache::SaveOtherGameSetsData,
&CDBDataCache::SaveQuestData,
&CDBDataCache::SaveGuildData,
&CDBDataCache::SaveMiscData,
&CDBDataCache::SaveAchieveData,
&CDBDataCache::SaveScriptData,
&CDBDataCache::SavePetData,
&CDBDataCache::SavePetSkillData,
&CDBDataCache::SavCombatGameInfoData,
&CDBDataCache::SavCombatRecordData,
&CDBDataCache::SaveFriendData,
&CDBDataCache::SavGamesetData,
&CDBDataCache::SaveActorMailData,
&CDBDataCache::SaveAlmirahItemData,
&CDBDataCache::SaveDeathData,
&CDBDataCache::SaveDeathDropData,
&CDBDataCache::SaveConsignData,
};
//s_aActorCacheHandler与s_aCDT2RespSrvCmdID顺序要一一对应
const jxSrvDef::INTERSRVCMD CDBDataCache::s_aCDT2RespSrvCmdID[] = {
dcSave,
dcSaveBagItem,
dcSaveEquipItem,
dcSaveDepotItem,
dcSaveHeroItem,
dcSaveSkill,
dcSaveOtherGameSets,
dcDefault, // for quest data!!! no response
dcSaveActorGuild,
dcDefault, // for misc data!!! no response
dcDefault, // for achieve data!!! no response
dcSaveVar,
dcSaveHeroData,
dcSaveHeroSkillData,
dcSaveCombatGameInfo,
dcLoadCombatRecord,
dcSaveFriendsData,
dcSaveGameSetData,
dcSaveOfflineMail,
dcSaveAlmirahItem,
dcSaveDeathData,
dcSaveDeathDropData,
dcSaveActorConsignment,
};
jxSrvDef::INTERSRVCMD CDBDataCache::GetCmdIdByCDT(enActorCacheDataType tp)
{
if (tp >= 0 && tp < enCT_Max)
return s_aCDT2RespSrvCmdID[tp];
return dcDefault;
}
CDBDataCache::CDBDataCache() : m_sACDHandleMgr(_T("ActorCacheDataHandleMgr"))
{
m_bHasExpireCache = false;
SetDBClient(NULL, NULL);
m_nNextCheckTime = _getTickCount();
m_listIter.setList(m_list);
}
void CDBDataCache::SetDBClient(ILogicDBRequestHost* pHost, CDBDataClientHandler* handler)
{
m_pHost = pHost;
m_pClientHandler = handler;
}
bool CDBDataCache::CacheData(enActorCacheDataType cdType, CDataPacketReader& packet)
{
if (cdType >= 0 && cdType < enCT_Max)
{
unsigned int nActorId = 0;
int nRawServerId = 0, nLoginServerId = 0;
switch (cdType)
{
case enCT_ActorBasicData:
case enCT_BagItemData:
case enCT_EquipItemData:
case enCT_DepotItemData:
case enCT_PetItemData:
case enCT_SkillData:
case enCT_GameOtherSetData:
case enCT_QuestData:
case enCT_MiscData:
case enCT_AchieveData:
case enCT_ScriptData:
case enCT_PetData:
case enCT_PetSkillData:
case enCT_CombatGameData:
case enCT_CombatRecordData:
case enCT_FriendData:
case enCT_DeathData:
case enCT_DeathDropData:
case enCT_GameSetData:
case enCT_MailData:
case enCT_AlmirahItemData:
case enCT_SoldierSoulData:
case enCT_ConsignData:
nActorId = GetActorId(packet, 8);
break;
case enCT_GuildData:
nActorId = GetActorId(packet, 12);
break;
default:
break;
}
if (nActorId > 0)
{
CActorCacheDataHandle acdhandle;
CActorCacheData* pData = GetActorCacheDataByActorId(nActorId);
if (!pData)
{
pData = AllocActorCacheData(nActorId, acdhandle);
if (pData)
{
pData->Init(m_allocator, nActorId);
pData->PostponeNextSaveTick();
}
}
//pData->SetDirty(true); 修改为每类数据更新标记
pData->SetDirty(cdType, true);
CDataPacket& cachePacket = pData->m_sActorCacheData[cdType];
cachePacket.setPosition(0);
size_t nLen = packet.getAvaliableLength();
cachePacket.setLength(nLen);
cachePacket.writeBuf(packet.getOffsetPtr(), nLen);
cachePacket.setPosition(0);
}
// Response to request
jxSrvDef::INTERSRVCMD respCmdId = GetCmdIdByCDT(cdType);
if (respCmdId != dcDefault && m_pClientHandler)
{
//CDataPacket& respPacket = m_pHost->AllocDataPacket(respCmdId);//m_pDBClient->allocProtoPacket(respCmdId);
//respPacket << nActorId << (BYTE)reSucc;
////m_pDBClient->flushProtoPacket(respPacket);
//m_pHost->FlushDataPacket(respPacket);
}
}
else
{
OutputMsg(rmError, _T("CacheData[type=%d] failed"), (int)cdType);
}
return true;
}
unsigned int CDBDataCache::GetActorId(CDataPacketReader& packet, INT_PTR nOffset)
{
unsigned int nActorId = 0;
if (packet.getAvaliableLength() < sizeof(nActorId) + nOffset)
return 0;
INT_PTR nPos = packet.getPosition();
if (nOffset != 0)
packet.adjustOffset(nOffset);
packet >> nActorId;
packet.setPosition(nPos);
return nActorId;
}
void CDBDataCache::OnActorLogin(CDataPacketReader& packet)
{
unsigned int nActorId = GetActorId(packet, 0);
SaveActorDataImmediately(nActorId, false);
}
void CDBDataCache::OnActorLogout(CDataPacketReader& packet)
{
DECLARE_FUN_TIME_PROF()
//int nActorId = GetActorId(packet, 0);
int nRawServerId = 0, nLoginServerId = 0;
unsigned int nActorId = 0;
bool bNeedAck = false;
packet >> nRawServerId >> nLoginServerId >> nActorId >> bNeedAck;
SaveActorDataImmediately(nActorId, false);
GetLogicDBRequestHandler().UpdateCharOnlineStatus(nActorId, 0);
if (bNeedAck && m_pHost)
{
CDataPacket &retPacket = m_pHost->AllocDataPacket(dcLogout);
retPacket << nRawServerId << nLoginServerId << nActorId << jxInterSrvComm::DbServerProto::reSucc;
m_pHost->FlushDataPacket(retPacket);
}
}
void CDBDataCache::SaveAllActorDataImmediately()
{
OutputMsg(rmNormal, _T("Prepare to Save all Actor Data"));
SaveData(false, false);
OutputMsg(rmNormal, _T("Save all Actor Data End"));
GetLogicDBRequestHandler().UpdateCharOnlineStatus(0,0);
}
CLogicDBReqestHandler& CDBDataCache::GetLogicDBRequestHandler()
{
return m_pClientHandler->GetDBRequestHandler();
}
bool CDBDataCache::SaveActorBasicData(CDataPacketReader& packet, bool bResp)
{
//m_pDBClient->SaveActorToDB(packet, bResp);
GetLogicDBRequestHandler().SaveActorToDB(packet, bResp);
return true;
}
bool CDBDataCache::SaveBagItemData(CDataPacketReader& packet, bool bResp)
{
//m_pDBClient->SaveItems(packet, bResp);
GetLogicDBRequestHandler().SaveItems(packet, bResp);
return true;
}
bool CDBDataCache::SaveEquipItemData(CDataPacketReader& packet, bool bResp)
{
//m_pDBClient->SaveItems(packet, bResp);
GetLogicDBRequestHandler().SaveItems(packet, bResp);
return true;
}
bool CDBDataCache::SaveDepotItemData(CDataPacketReader& packet, bool bResp)
{
//m_pDBClient->SaveItems(packet, bResp);
GetLogicDBRequestHandler().SaveItems(packet, bResp);
return true;
}
bool CDBDataCache::SavCombatGameInfoData( CDataPacketReader& packet, bool bResp)
{
GetLogicDBRequestHandler().SaveActorCombatBaseInfo(packet);
return true;
}
bool CDBDataCache::SavCombatRecordData( CDataPacketReader& packet, bool bResp)
{
GetLogicDBRequestHandler().SaveActorCombatLog(packet);
return true;
}
bool CDBDataCache::SaveFriendData( CDataPacketReader& packet, bool bResp)
{
GetLogicDBRequestHandler().SaveActorFriendsData(packet);
return true;
}
bool CDBDataCache::SaveDeathData( CDataPacketReader& packet, bool bResp)
{
GetLogicDBRequestHandler().SaveActorDeathData(packet);
return true;
}
bool CDBDataCache::SaveDeathDropData( CDataPacketReader& packet, bool bResp)
{
GetLogicDBRequestHandler().SaveActorDeathDropData(packet);
return true;
}
bool CDBDataCache::SavGamesetData(CDataPacketReader& packet,bool bResp)
{
GetLogicDBRequestHandler().SaveActorGameSetData(packet);
return true;
}
bool CDBDataCache::SavePetItemData(CDataPacketReader& packet, bool bResp)
{
//m_pDBClient->SaveItems(packet, bResp);
GetLogicDBRequestHandler().SaveItems(packet, bResp);
return true;
}
bool CDBDataCache::SaveSkillData(CDataPacketReader& packet, bool bResp)
{
//m_pDBClient->SaveSkillToDB(packet, bResp);
GetLogicDBRequestHandler().SaveSkillToDB(packet, bResp);
return true;
}
bool CDBDataCache::SaveOtherGameSetsData(CDataPacketReader& packet, bool bResp)
{
//m_pDBClient->SaveSkillToDB(packet, bResp);
GetLogicDBRequestHandler().SaveOtherGameSetsToDB(packet, bResp);
return true;
}
bool CDBDataCache::SaveQuestData(CDataPacketReader& packet, bool bResp)
{
//m_pDBClient->SaveQuestToDB(packet, bResp);
GetLogicDBRequestHandler().SaveQuestToDB(packet, bResp);
return true;
}
bool CDBDataCache::SaveGuildData(CDataPacketReader& packet, bool bResp)
{
//m_pDBClient->SaveActorGuild(packet, bResp);
GetLogicDBRequestHandler().SaveActorGuild(packet, bResp);
return true;
}
bool CDBDataCache::SaveMiscData(CDataPacketReader& packet, bool bResp)
{
return true;
}
bool CDBDataCache::SaveAchieveData(CDataPacketReader& packet, bool bResp)
{
return true;
}
bool CDBDataCache::SaveScriptData(CDataPacketReader& packet, bool bResp)
{
GetLogicDBRequestHandler().SaveScriptDataToDB(packet, bResp);
return true;
}
bool CDBDataCache::SavePetData(CDataPacketReader& packet, bool bResp)
{
//m_pDBClient->SavePetToDB(packet, bResp);
GetLogicDBRequestHandler().SavePetToDB(packet, bResp);
return true;
}
bool CDBDataCache::SavePetSkillData(CDataPacketReader& packet, bool bResp)
{
//m_pDBClient->SavePetSkillData(packet, bResp);
GetLogicDBRequestHandler().SavePetSkillData(packet, bResp);
return true;
}
bool CDBDataCache::SaveActorMailData(CDataPacketReader & packet, bool bResp)
{
GetLogicDBRequestHandler().SaveActorMail(packet, bResp);
return true;
}
bool CDBDataCache::SaveConsignData( CDataPacketReader& packet, bool bResp)
{
GetLogicDBRequestHandler().SaveActorConsignment(packet);
return true;
}
bool CDBDataCache::SaveStaticCounts(CDataPacketReader& packet, bool bResp)
{
GetLogicDBRequestHandler().SaveActorStaticCounts(packet);
return true;
}
bool CDBDataCache::SaveData(bool bCheckCD, bool bResp, INT_PTR nTimeLmt)
{
//DECLARE_FUN_TIME_PROF()
TICKCOUNT nEndTick = _getTickCount() + nTimeLmt;
TICKCOUNT nCurrTick = 0;
if (bCheckCD)
nCurrTick = _getTickCount();
if(m_list.count()==0 || m_pClientHandler ==NULL ) return true;
CBaseLinkedList<CActorCacheData*>::NodeType* pNode = NULL;
while (pNode = m_listIter.next())
{
CActorCacheData* acd = *pNode;
SaveActorDataImpl(*acd, bCheckCD, nCurrTick, bResp);
// if read operation arrived, just pause it
if (m_pClientHandler && m_pClientHandler->HasReadOPFlag())
{
if (_getTickCount() > nEndTick)
{
OutputMsg(rmNormal, _T("有查询数据到来,暂停存盘操作"));
break;
}
}
}
return true;
}
bool CDBDataCache::SaveActorDataImmediately(unsigned int nActorId, bool bResp)
{
std::map<unsigned int, CActorCacheData*>::iterator iter = m_sACDIdxTbl.find(nActorId);
if (iter == m_sACDIdxTbl.end())
return true;
OutputMsg(rmNormal, _T("SaveActorDataImmediately actorid=%u"), nActorId);
if (CDBDataServer *pDataServer = CDBServer::s_pDBEngine->getDataServer())
{
pDataServer->m_ActorIdMapLock.Lock();
pDataServer->m_ActorIdMap[nActorId] = false;
pDataServer->m_ActorIdMapLock.Unlock();
}
CActorCacheData* acd = iter->second;
return SaveActorDataImpl(*acd, false, 0, bResp);
}
void CDBDataCache::RemoveExpireCache()
{
std::map<unsigned int, CActorCacheData*>::iterator iter = m_sACDIdxTbl.begin();
std::map<unsigned int, CActorCacheData*>::iterator iter_end = m_sACDIdxTbl.end();
for (; iter != iter_end; )
{
CActorCacheData* acd = iter->second;
if (acd->IsExpired())
{
OutputMsg(rmNormal, _T("Remove actor[%u] cache data"), iter->first);
m_sACDIdxTbl.erase(iter++);
FreeActorCacheData(acd->GetHandle(), false);
}
else
{
++iter;
}
}
}
bool CDBDataCache::SaveActorDataImpl(CActorCacheData& data, bool bCheckCD, TICKCOUNT nCurrTick, bool bResp)
{
if (!data.IsDirty())
{
if (data.m_nNextSaveTick + CActorCacheData::s_nExpireTime <= nCurrTick)
{
data.SetExpired(true);
OutputMsg(rmNormal, _T("SaveActorDataImpl set Actor[actorid=%u] expired"), data.m_nActorId);
if (!m_bHasExpireCache)
m_bHasExpireCache = true;
}
return true;
}
if (!bCheckCD || (bCheckCD && data.CheckAndSet(nCurrTick)) )
{
if (data.IsDirty())
{
INT_PTR nCount = __min(ArrayCount(s_aActorCacheHandler), enCT_Max);
OutputMsg(rmNormal, _T("Save Actor[actorid=%u] Data,dirtyflag=%lld"), data.m_nActorId,data.m_sACDDirtyFlag);
for (INT_PTR i = 0; i < nCount; i++)
{
if (data.IsACDDirty((int)i))
{
//OutputMsg(rmNormal, _T("Save ACD, type=%d"), (int)i);
bool bRet = (this->*s_aActorCacheHandler[i])(data.m_sActorCacheData[i], bResp);
if (!bRet)
{
OutputMsg(rmError, _T("SaveData Failed(Actorid=%u, cacheType=%d"), data.m_nActorId, i);
}
}
}
data.ResetDirty();
}
}
return true;
}
void CDBDataCache::RunOne(TICKCOUNT nCurrTick)
{
if (nCurrTick >= m_nNextCheckTime)
{
m_nNextCheckTime += s_nCheckInterval;
SaveData(true, true, 2000);
}
if (m_bHasExpireCache)
{
RemoveExpireCache();
m_bHasExpireCache = false;
}
}
CActorCacheData* CDBDataCache::AllocActorCacheData(unsigned int nActorId, CActorCacheDataHandle &handle)
{
CActorCacheData* adc = this->m_sACDHandleMgr.Acquire(handle);
if (adc)
{
adc->SetHandle(handle);
m_sACDIdxTbl.insert(std::make_pair(nActorId, adc));
CBaseLinkedList<CActorCacheData*>::NodeType* node = m_list.linkAfter(adc);
adc->m_node = node;
}
else
{
OutputMsg(rmError,"AllocActorCacheData Acquire fail,actorid=%u",nActorId);
}
return adc;
}
CActorCacheData* CDBDataCache::GetActorCacheData(const CActorCacheDataHandle& handle)
{
CActorCacheData* adc = this->m_sACDHandleMgr.GetDataPtr(handle);
return adc;
}
CActorCacheData* CDBDataCache::GetActorCacheDataByActorId(unsigned int nActorId)
{
std::map<unsigned int, CActorCacheData*>::iterator iter = m_sACDIdxTbl.find(nActorId);
if (iter != m_sACDIdxTbl.end())
return iter->second;
return NULL;
}
void CDBDataCache::FreeActorCacheData(const CActorCacheDataHandle& handle, bool updateIndex)
{
CActorCacheData* acd = GetActorCacheData(handle);
if (!acd)
OutputMsg(rmError, _T("%s can't find item in index table"), __FUNCTION__);
//OutputMsg(rmNormal, _T("FreeActorCacheData,actorid=%u"),acd->m_nActorId);
if (updateIndex)
{
std::map<unsigned int, CActorCacheData*>::iterator iter = m_sACDIdxTbl.find(acd->m_nActorId);
if (iter != m_sACDIdxTbl.end())
m_sACDIdxTbl.erase(iter);
}
m_listIter.remove(acd->m_node);
acd->m_node = 0;
m_sACDHandleMgr.Release(handle);
}
void CDBDataCache::Trace()
{
OutputMsg(rmNormal,"---cache start---");
INT_PTR nSize =0;
CBaseLinkedList<CActorCacheData*>::NodeType* pNode = NULL;
while (pNode = m_listIter.next())
{
CActorCacheData* acd = *pNode;
if(acd)
{
nSize += acd->Trace();
}
}
OutputMsg(rmNormal," actor cache total size=%d",(int)nSize);
OutputMsg(rmNormal,"CDBDataCache CBufferAllocator");
CBufferAllocator::ALLOCATOR_MEMORY_INFO memoryInfo;
m_allocator.GetMemoryInfo(&memoryInfo);
OutputMsg(rmNormal,"super alloc=%d,free=%d",(int)memoryInfo.SuperBuffer.dwAllocSize,(int)memoryInfo.SuperBuffer.dwFreeSize);
OutputMsg(rmNormal,"large alloc=%d,free=%d",(int)memoryInfo.LargeBuffer.dwAllocSize,(int)memoryInfo.LargeBuffer.dwFreeSize);
OutputMsg(rmNormal,"middle alloc=%d,free=%d",(int)memoryInfo.MiddleBuffer.dwAllocSize,(int)memoryInfo.MiddleBuffer.dwFreeSize);
OutputMsg(rmNormal,"small alloc=%d,free=%d",(int)memoryInfo.SmallBuffer.dwAllocSize,(int)memoryInfo.SmallBuffer.dwFreeSize);
OutputMsg(rmNormal,"---cache end---");
}
bool CDBDataCache::SaveAlmirahItemData(CDataPacketReader& packet, bool bResp)
{
//m_pDBClient->SaveItems(packet, bResp);
GetLogicDBRequestHandler().SaveAlmirahItem(packet, bResp);
return true;
}

View File

@@ -0,0 +1,334 @@
#pragma once
#include <map>
class CDBDataCache;
class CActorCacheData;
//////////////////////////////////////////////////////////////////////////
// 角色Cache数据句柄管理器类型定义
//////////////////////////////////////////////////////////////////////////
typedef Handle<UINT> CActorCacheDataHandle;
typedef HandleMgr<CActorCacheData, CActorCacheDataHandle> CActorCacheDataHandleMgr;
class CActorCacheData
{
public:
CActorCacheDataHandle m_handle; // 句柄
CBaseLinkedList<CActorCacheData*>::NodeType* m_node; // 对应于在list中的节点用于删除时提高效率
unsigned int m_nActorId; // 角色Id
TICKCOUNT m_nNextSaveTick; // 下一次存盘时间
CDataPacket m_sActorCacheData[enCT_Max]; // 角色数据Cache
Uint64 m_sACDDirtyFlag; // 角色数据更新标记。支持最多64中类型
//bool m_sACDDirty[enCT_Max]; // 角色数据Cache脏标记对每个类型的数据都区分
//bool m_bDirty; // 数据是否需要更新
bool m_bExpired; // 是否过期如果过期下次RunOne会删除
static const TICKCOUNT s_nExpireTime; // 过期时间
CActorCacheData() : m_handle(0), m_node(0), m_nActorId(0), m_bExpired(false),m_sACDDirtyFlag(0){}
inline void Init(CBufferAllocator &allocator, unsigned int nActorId)
{
for (INT_PTR i = 0; i < enCT_Max; i++)
{
m_sActorCacheData[i].setAllocator(&allocator);
m_sActorCacheData[i].setPosition(0);
}
m_nActorId = nActorId;
m_nNextSaveTick = _getTickCount();
}
//追踪内存情况
INT_PTR Trace()
{
INT_PTR nTotalSize=0;//总内存
for (INT_PTR i = 0; i < enCT_Max; i++)
{
INT_PTR nSize =m_sActorCacheData[i].getMemorySize();
/*
if(nSize >4096)
{
OutputMsg(rmNormal,"Actorid=%d,msgid=%d,size=%d",m_nActorId,(int)i,(int)nSize);
}
*/
nTotalSize += nSize;
}
//OutputMsg(rmNormal,"Actorid=%d,memory=%d",m_nActorId,(int)nTotalSize);
return nTotalSize;
}
//// 判断数据是否脏
inline bool IsDirty() const {
return m_sACDDirtyFlag != 0;
}
inline bool IsACDDirty(int tp) const {
return (m_sACDDirtyFlag & (Uint64)((1 << tp))) != 0 ? true : false;
}
inline void SetDirty(int tp, bool bDirty)
{
if (bDirty)
{
m_sACDDirtyFlag |= (Uint64)((1 << tp));
}
else
{
m_sACDDirtyFlag &= ~(Uint64)(1 << tp);
}
}
inline void ResetDirty()
{
m_sACDDirtyFlag = 0;
}
//inline bool IsDirty() const {
// return m_bDirty;
//}
//// 设置数据脏属性
//inline void SetDirty(bool bDirty) {
// m_bDirty = bDirty;
// if (bDirty && IsExpired())
// SetExpired(false);
//}
// 获取句柄
inline CActorCacheDataHandle GetHandle() const { return m_handle; }
// 设置句柄
inline void SetHandle(CActorCacheDataHandle& handle)
{
m_handle = handle;
}
// 过期相关的操作
inline bool IsExpired() const { return m_bExpired; }
inline void SetExpired(bool bExpired) {
if (m_bExpired != bExpired)
m_bExpired = bExpired;
}
inline bool CheckAndSet(TICKCOUNT nCurrTick)
{
if (nCurrTick >= m_nNextSaveTick)
{
PostponeNextSaveTick();
return true;
}
return false;
}
void PostponeNextSaveTick();
inline bool operator < (const CActorCacheData& data)
{
return m_nActorId < data.m_nActorId ? true : false;
}
private:
CActorCacheData(const CActorCacheData& rhs)
{
m_nActorId = rhs.m_nActorId;
m_bExpired = false;
ResetDirty();
}
};
class CDBDataClientHandler;
class CDBDataCache
{
friend class CActorCacheData;
public:
CDBDataCache();
virtual ~CDBDataCache(){}
public:
/*
* Comments: 设置DBClient
* Param ILogicDBRequestHost *pHost:
* Param CDBDataClientHandler* handler: DB请求处理器
* @Return void:
* @Remark:
*/
void SetDBClient(ILogicDBRequestHost* pHost, CDBDataClientHandler* handler);
/*
* Comments: 缓存角色数据
* Param enActorCacheDataType cdType: 缓存数据类型
* Param CDataPacketReader & packet: 缓存数据
* @Return bool: 成功返回true失败返回false
* @Remark:
*/
bool CacheData(enActorCacheDataType cdType, CDataPacketReader& packet);
/*
* Comments: 保存Cache数据
* Param bCheckCD: 指定是否检测CD
* Param bResp: 是否回应消息给逻辑服
* Param INT_PTR nTimeLmt: 时间限制
* @Return bool: 成功返回true失败返回false
* @Remark:
*/
bool SaveData(bool bCheckCD, bool bResp, INT_PTR nTimeLmt = INT_MAX);
/*
* Comments: 例行处理
* Param nCurrentTick: 当前的Tickount
* @Return void:
* @Remark:
*/
void RunOne(TICKCOUNT nCurrTick);
/*
* Comments: 角色登录
* Param CDataPacketReader & packet:
* @Return void:
* @Remark:
*/
void OnActorLogin(CDataPacketReader& packet);
/*
* Comments: 角色退出
* Param
* @Return void:
* @Remark:
*/
void OnActorLogout(CDataPacketReader& packet);
void SaveAllActorDataImmediately();
/*
* Comments:追踪内存的使用情况
* @Return void:
*/
void Trace();
protected:
/*
* Comments: 获取角色Id
* Param CDataPacketReader & packet:
* Param INT_PTR nOffset: 角色Id在消息包中的偏移
* @Return unsigned int: 成功返回角色id失败返回0
* @Remark: 读取数据中的角色id字段并且不修改packet内容
*/
unsigned int GetActorId(CDataPacketReader& packet, INT_PTR nOffset = 0);
/*
* Comments:立刻保存角色数据
* Param int nActorId:
* Param bool bResp: 是否给逻辑服回应答消息
* @Return bool:
* @Remark:
*/
bool SaveActorDataImmediately(unsigned int nActorId, bool bResp = true);
/*
* Comments: 移除过期CacheData
* @Return void:
* @Remark:
*/
void RemoveExpireCache();
/*
* Comments: 分配一个角色Cache数据节点
* Param int nActorId: 角色Id
* Param CActorCacheDataHandle & handle: 返回分配的ACD节点句柄
* @Return CActorCacheData*: 返回可存储ACD对象节点指针
* @Remark:
*/
CActorCacheData* AllocActorCacheData(unsigned int nActorId, CActorCacheDataHandle &handle);
/*
* Comments: 根据句柄查询指定ACD节点对象
* Param CActorCacheDataHandle & handle: ACD节点句柄
* @Return CActorCacheData*: 返回对应的ACD对象指针
* @Remark:
*/
CActorCacheData* GetActorCacheData(const CActorCacheDataHandle& handle);
/*
* Comments: 根据角色Id查找ACD节点对象
* Param int nActorId:
* @Return CActorCacheData*:
* @Remark:
*/
CActorCacheData* GetActorCacheDataByActorId(unsigned int nActorId);
/*
* Comments: 释放指定句柄的ACD节点对象
* Param CActorCacheDataHandle & handle: ACD节点句柄
* Param , bool updateIndex: 为true表示在释放ACD节点同时更新索引表
* @Return void:
* @Remark:
*/
void FreeActorCacheData(const CActorCacheDataHandle& handle, bool updateIndex = true);
/*
* Comments: 根据角色缓存数据类型查找对应的消息号
* Param enActorCacheDataType tp:
* @Return jxSrvDef::INTERSRVCMD:
* @Remark:
*/
jxSrvDef::INTERSRVCMD GetCmdIdByCDT(enActorCacheDataType tp);
/*
* Comments: 保存角色数据
* Param CActorCacheData & data: 角色数据
* Param bool bCheckCD: 是否检测CD
* Param TICKCOUNT nCurrTick: 当前的TickCount
* Param bool bResp: 是否给逻辑服务器会操作结果应答消息
* @Return bool: 成功返回true失败返回false
* @Remark:
*/
bool SaveActorDataImpl(CActorCacheData& data, bool bCheckCD, TICKCOUNT nCurrTick, bool bResp);
bool SaveActorBasicData(CDataPacketReader& packet, bool bResp = true);
bool SaveBagItemData(CDataPacketReader& packet, bool bResp = true);
bool SaveEquipItemData(CDataPacketReader& packet, bool bResp = true);
bool SaveDepotItemData(CDataPacketReader& packet, bool bResp = true);
bool SavePetItemData(CDataPacketReader& packet, bool bResp = true);
bool SaveOtherGameSetsData(CDataPacketReader& packet, bool bResp = true);
bool SaveSkillData(CDataPacketReader& packet, bool bResp = true);
bool SaveQuestData(CDataPacketReader& packet, bool bResp = true);
bool SaveGuildData(CDataPacketReader& packet, bool bResp = true);
bool SaveMiscData(CDataPacketReader& packet, bool bResp = true);
bool SaveAchieveData(CDataPacketReader& packet, bool bResp = true);
bool SaveScriptData(CDataPacketReader& packet, bool bResp = true);
bool SavePetData(CDataPacketReader& packet, bool bResp = true);
bool SavePetSkillData(CDataPacketReader& packet, bool bResp = true);
bool SavCombatGameInfoData( CDataPacketReader& packet, bool bResp = true);
bool SavCombatRecordData( CDataPacketReader& packet, bool bResp = true);
bool SaveFriendData( CDataPacketReader& packet, bool bResp = true);
bool SavGamesetData(CDataPacketReader& packet, bool bResp = true);
bool SaveActorMailData(CDataPacketReader& packet, bool bResp = true);
bool SaveAlmirahItemData(CDataPacketReader& packet, bool bResp = true); // 衣橱系统
bool SaveDeathData( CDataPacketReader& packet, bool bResp = true);
bool SaveDeathDropData( CDataPacketReader& packet, bool bResp = true);
bool SaveConsignData( CDataPacketReader& packet, bool bResp = true);//寄卖
bool SaveStaticCounts( CDataPacketReader& packet, bool bResp = true);//计数器
CLogicDBReqestHandler& GetLogicDBRequestHandler();
private:
typedef bool (CDBDataCache::*SaveHandler)(CDataPacketReader&, bool);
CBufferAllocator m_allocator; // BuffAllocator
ILogicDBRequestHost *m_pHost;
CDBDataClientHandler* m_pClientHandler; // DB请求处理器
CActorCacheDataHandleMgr m_sACDHandleMgr; // 角色Cache数据句柄管理器
std::map<unsigned int, CActorCacheData*> m_sACDIdxTbl; // 角色Cache数据索引表 actorid --> CActorCacheData*
CBaseLinkedList<CActorCacheData*> m_list; // 用于遍历
wylib::container::CLinkedListIterator<CActorCacheData*> m_listIter; // 用于保存上次遍历位置的迭代器
TICKCOUNT m_nNextCheckTime; // 检测更新角色数据定时器
bool m_bHasExpireCache; // 标记是否删除Cache数据
static const TICKCOUNT s_nCheckInterval; // 检测更新角色数据定时器间隔默认5s检测一次
static const SaveHandler s_aActorCacheHandler[]; // 角色数据Cache处理器表
static const jxSrvDef::INTERSRVCMD s_aCDT2RespSrvCmdID[]; // 角色缓存数据类型到应答消息命令ID映射表
public:
static TICKCOUNT s_nActorCacheSaveInterval; // 角色数据存盘间隔
};

View File

@@ -0,0 +1,524 @@
#include "StdAfx.h"
#define GUILD_NAME_MAX_LEN 7
CDBDataClient::CDBDataClient(CDBDataServer *lpDataServer, CSQLConenction *lpSQLConnection, SOCKET nSocket, PSOCKADDR_IN pAddrIn)
:Inherited()
{
SetClientSocket(nSocket, pAddrIn);
m_pDataServer = lpDataServer;
m_pSQLConnection = lpSQLConnection;
m_dwClosedTick = 0;
m_ASyncNameOPList.setLock(&m_ASyncNameOPListLock);
m_pHugeSQLBuffer = (PCHAR)m_Allocator.AllocBuffer(dwHugeSQLBufferSize);
// m_sDataHandler.Start(this, m_pSQLConnection);
m_loginHandler.Init(m_pSQLConnection,m_pDataServer);
}
void CDBDataClient::SetNewSQLConnection(CSQLConenction *lpSQLConnection)
{
m_sDataHandler.Start(this, lpSQLConnection);
}
CDBDataClient::~CDBDataClient()
{
m_Allocator.FreeBuffer(m_pHugeSQLBuffer);
ClearASyncNameOPList();
m_sDataHandler.Stop();
}
CDataPacket& CDBDataClient::AllocDataPacket(const jxSrvDef::INTERSRVCMD nCmd)
{
return allocProtoPacket(nCmd);
}
void CDBDataClient::FlushDataPacket(CDataPacket &packet)
{
flushProtoPacket(packet);
}
VOID CDBDataClient::OnDisconnected()
{
m_dwClosedTick = _getTickCount();
OutputMsg( rmWaning, _T("数据客户端(%s:%d)连接已断开"), GetRemoteHost(), GetRemotePort() );
//不能调用父类的断开连接函数,因为希望在连接断开后继续保留套接字中的数据以便处理
// TODO.更新连接的逻辑服务器列表
}
VOID CDBDataClient::Disconnected()
{
Inherited::Disconnected();
if (m_pDataServer)
m_pDataServer->UpdateLogicClientList();
}
VOID CDBDataClient::OnError(INT errorCode)
{
//输出错误消息
OutputError( errorCode, _T("数据客户端(%s:%d)套接字发生错误"), GetRemoteHost(), GetRemotePort() );
//断开连接
close();
}
VOID CDBDataClient::DispatchInternalMessage(UINT uMsg, UINT64 uParam1, UINT64 uParam2, UINT64 uParam3,UINT64 uParam4)
{
TICKCOUNT nTick;
switch(uMsg)
{
case DCIM_CREATE_ACTOR_RESULT:
//ProcessCreateActor((INT_PTR)uParam2,(unsigned int)uParam3,(PCREATEACTORDATA)uParam4);
m_loginHandler.OnCreateActorResult((INT_PTR)uParam1,(unsigned int)uParam2,(PCREATEACTORDATA)uParam3,this );
break;
case DCIM_CREATE_CS_ACTOR_RESULT:
m_loginHandler.OnCreateCrossServerActorResult((INT_PTR)uParam1,(unsigned int)uParam2,(PCREATEACTORDATA)uParam3,this );
break;
case DCIM_RENAMECHAR_RESULT:
//名称客户端返回重命名角色的结果(Param1=操作结果,Param2=申请更名操作时传递的操作唯一标识)
ProcessRenameCharResult((PASYNCNAMEOPDATA)uParam2, (int)uParam1);
break;
case DCIM_ALLOC_GUILID_RESULT:
//名称客户端返回申请帮会ID的结果(Param1=操作结果,Param2=帮会IDParam3=申请帮会ID操作时传递的操作唯一标识)
ProcessAllocGuildResult((PASYNCNAMEOPDATA)uParam3, (unsigned int)uParam1, (unsigned int)uParam2);
break;
case DCIM_SEND_LOAD_ACTOR:
//发送认证信息
nTick = _getTickCount();
//输出这一步到服务器浪费的时间
OutputMsg(rmTip,"actorid=%lld,CDBDataClient send loadactor to ligic, pass=%d ms",uParam2, (int)(nTick -uParam3 ));
CDataPacket& retPack = allocProtoPacket(dcLoadActor);
retPack << (unsigned int)uParam1;//sessionid,见LOADACTORSTRUCT定义是unsigned int类型
retPack << (unsigned int)uParam2;//角色id
flushProtoPacket(retPack);
break;
}
}
VOID CDBDataClient::OnRun()
{
}
void CDBDataClient::OnDispatchRecvPacketEx(const jxSrvDef::INTERSRVCMD nCmd, CDataPacketReader& inPacket)
{
//是登陆的消息包,要最优先处理,让玩家迅速能够拿到角色列表
if(nCmd >= dcGetActorList && nCmd < dcLoginMsgMax)
{
//CDataPacket& out = allocProtoPacket(nCmd);
m_loginHandler.OnRecvLoginMsg(nCmd,inPacket,this); //处理登陆消息,不做缓存,立刻处理
//flushProtoPacket(out);
return;
}
else
{
m_sDataHandler.AddMessage(nCmd, inPacket);
}
}
VOID CDBDataClient::OnDispatchRecvPacket(const jxSrvDef::INTERSRVCMD nCmd, CDataPacketReader &inPacket)
{
DECLARE_FUN_TIME_PROF()
if (nCmd == 999)
OutputMsg(rmNormal, _T("%s recv InitDB Msg"), __FUNCTION__);
if (nCmd == dcQuery)
OutputMsg(rmNormal, _T("recv query actor msg"));
return OnDispatchRecvPacketEx(nCmd, inPacket);
}
VOID CDBDataClient::DefaultPacket(CDataPacketReader &inPacket)
{
}
VOID CDBDataClient::ClearASyncNameOPList()
{
INT_PTR i;
PASYNCNAMEOPDATA pNameOPData;
m_ASyncNameOPList.lock();
for ( i=m_ASyncNameOPList.count()-1; i>-1; --i )
{
pNameOPData = m_ASyncNameOPList[i];
m_Allocator.FreeBuffer(m_ASyncNameOPList);
}
m_ASyncNameOPList.clear();
m_ASyncNameOPList.unlock();
}
CDBDataClient::PASYNCNAMEOPDATA CDBDataClient::PeekASyncNameOPData(PASYNCNAMEOPDATA lpOPData)
{
INT_PTR nIndex = m_ASyncNameOPList.index(lpOPData);
if ( nIndex > - 1 )
{
m_ASyncNameOPList.remove(nIndex);
return lpOPData;
}
return NULL;
}
INT_PTR CDBDataClient::RenameCharOnDatabase(const INT_PTR nCharId, LPCSTR sNewCharName)
{
INT_PTR nError = 0;
nError = m_pSQLConnection->Query(szSQLSP_RenameCharactor, (unsigned int)nCharId, sNewCharName);
if ( !nError )
{
MYSQL_ROW pRow = m_pSQLConnection->CurrentRow();
if ( !pRow || !pRow[0] )
nError = 1;
else if ( pRow[0][0] == '0' )
nError = 2;
m_pSQLConnection->ResetQuery();
}
else nError = 1;
return nError;
}
VOID CDBDataClient::ProcessRenameCharResult(PASYNCNAMEOPDATA lpOPData, const INT_PTR nRenameError)
{
INT_PTR nError;
//如果更名操作数据不存在于此客户端中则不处理因为允许有多个客户端连接具有同一个服务器ID
if ( !PeekASyncNameOPData(lpOPData) )
return;
//更名成功
if ( nRenameError == jxInterSrvComm::NameServerProto::neSuccess )
{
//如果数据库连接未就绪则不予处理
if ( !m_pSQLConnection->Connected() )
{
nError = aeLocalInternalError;
//打印错误消息
OutputMsg( rmError, _T("数据客户端(%s,%d, %s:%d)申请对角色(%d)改名的操作已经被名称服务器接受,")
_T("但当前数据库连接尚未就绪"), getClientName(), getClientServerIndex(), GetRemoteHost(), GetRemotePort(),
lpOPData->RenameChar.nCharId );
}
else
{
nError = RenameCharOnDatabase(lpOPData->RenameChar.nCharId, lpOPData->RenameChar.sCharName );
if ( nError != 0 )
{
if ( nError == 1 )//数据库查询失败,当作为服务器内部错误返回
nError = aeLocalDataBaseError;
else if ( nError == 2 )//查询返回失败值,当作为角色名称已经存在错误返回
nError = aeNameInuse;
else nError = aeLocalInternalError;//如果添加了新的错误且未修改此代码,则全部当做服务器内部错误返回
}
}
}
//更名失败则转换错误号
else if ( nRenameError == jxInterSrvComm::NameServerProto::neInvalidName )
nError = aeInvalidName;
else if ( nRenameError == jxInterSrvComm::NameServerProto::neTimedOut )
nError = aeTimedOut;
else if ( nRenameError == jxInterSrvComm::NameServerProto::neDataBaseError )
nError = aeServerDataBaseError;
else nError = aeServerInternalError;
//返回数据客户端操作结果
#pragma __CPMSG__(返回逻辑服务器对角色进行改名的结果nError为表0表示成功否则表示错误号)
//释放更名操作占用的内存
m_Allocator.FreeBuffer(lpOPData);
}
void CDBDataClient::SendAddGuildResult(int nRawServerId, int nLoginServerId,
int nErr,int index,Uint64 hHandle,unsigned int nGid,LPCSTR sGuildName,LPCSTR sFoundName,BYTE nZY,INT_PTR nIcon)
{
CDataPacket& out = allocProtoPacket(dcAddGuild);
out << nRawServerId << nLoginServerId;
out << (BYTE)nErr;//内部错误
out << (int)index;
out << (Uint64)hHandle;
if (nErr == jxSrvDef::aeSuccess)
{
out << (unsigned int)nGid;
out.writeString(sGuildName);
out.writeString(sFoundName);
}
flushProtoPacket(out);
}
VOID CDBDataClient::ProcessAllocGuildResult(PASYNCNAMEOPDATA lpOPData, const INT_PTR nResult, INT_PTR nGuildId)
{
DECLARE_FUN_TIME_PROF()
INT_PTR nError = 0;
if(lpOPData ==NULL) return;
//如果创建帮会操作数据不存在于此客户端中则不处理因为允许有多个客户端连接具有同一个服务器ID
if ( !PeekASyncNameOPData(lpOPData) )
return;
//申请帮会ID成功
if ( nResult == jxInterSrvComm::NameServerProto::neSuccess )
{
//如果数据库连接未就绪则不予处理
if ( !m_pSQLConnection->Connected() )
{
nError = reDbErr;
//打印错误消息
OutputMsg( rmError, _T("数据客户端(%s:%d, %s:%d)申请创建的帮会(%s)已经被名称服务器分配ID(%u)")
_T("但当前数据库连接尚未就绪"), getClientName(), getClientServerIndex(), GetRemoteHost(), GetRemotePort(),
lpOPData->CreateGuild.sGuildName, nGuildId );
}
else
{
//如果存在了这个名字,则不创建
if(m_pDataServer->GetJobZyMgr()->IsGuildNameExist(lpOPData->CreateGuild.sGuildName,lpOPData->CreateGuild.nServerIndex) )
{
nError = reNameInUse;
}
else
{
nError = m_pSQLConnection->Exec(szSQLSP_CreateGuild,
(unsigned int)nGuildId,
lpOPData->CreateGuild.nActorid,
lpOPData->CreateGuild.sGuildName,
lpOPData->CreateGuild.sFoundName,
lpOPData->CreateGuild.nServerIndex);
if ( nError != 0 )
{
if ( nError == 1 )//数据库查询失败,当作为服务器内部错误返回
nError = reDbErr;
else if ( nError == 2 )//查询返回失败值,当作为角色名称已经存在错误返回
nError = reNameInUse;
else nError = reInterErr;//如果添加了新的错误且未修改此代码,则全部当做服务器内部错误返回
}
else
{
m_pSQLConnection->ResetQuery();
//创建成功
m_pDataServer->GetJobZyMgr()->OnNewGuildNameCreate(lpOPData->CreateGuild.nServerIndex,lpOPData->CreateGuild.sGuildName, (unsigned int)nGuildId);
nError = reSucc;//正确
}
}
}
}
//申请帮会ID失败则转换错误号
else if ( nResult == jxInterSrvComm::NameServerProto::neInvalidName )
nError = reNameError;
else if ( nResult == jxInterSrvComm::NameServerProto::neTimedOut )
nError = reTimeOut;
else if ( nResult == jxInterSrvComm::NameServerProto::neDataBaseError )
nError = reDbErr;
else if (nResult == jxInterSrvComm::NameServerProto::neNameinuse)
nError = reNameInUse;
else nError = reInterErr;
//返回数据客户端操作结果
SendAddGuildResult(0, 0, (int)nError,lpOPData->CreateGuild.nIndex,lpOPData->CreateGuild.hActor,(unsigned int)nGuildId,lpOPData->CreateGuild.sGuildName,
lpOPData->CreateGuild.sFoundName,lpOPData->CreateGuild.nZY,lpOPData->CreateGuild.wIcon);
//释放创建帮会操作占用的内存
m_Allocator.FreeBuffer(lpOPData);
}
VOID CDBDataClient::DispatchRecvMsg(LPCSTR lpData, SIZE_T dwSize)
{
#pragma __CPMSG__(拆分单个通信数据包进行数据处理)
}
int CDBDataClient::CatchRenameChar(LPCSTR lpData, SIZE_T dwSize)
{
unsigned int nCharId = 0;
INT_PTR nError = 0;
char sNewCharName[128];
//如果数据库尚未连接则无法处理
if ( !m_pSQLConnection->Connected() )
{
OutputMsg(rmError, _T("数据客户端(%s:%d, %s:%d)请求重命名角色,但数据库连接尚未就绪"),
getClientName(), getClientServerIndex(), GetRemoteHost(), GetRemotePort() );
//返回数据客户端服务器内部错误的消息
return reDbErr;
}
//解码新角色名
sprintf(sNewCharName,"%s",lpData);
//检查数据合法性不合法则返回ASYNCRERR_INVALIDDATA错误
if ( !sNewCharName[0] || strlen(sNewCharName) < 4 )
{
return reNameError;
}
//将角色名称的第一个字符之后的字母转换为小写
//m_pDataServer->GetDBEngine()->LowerCaseNameStr(sNewCharName,sizeof(sNewCharName));
//从本地数据库检查角色名称是否存在
int nServerIndex = 0;
nError = m_pSQLConnection->Query(szSQLSP_GetCharactorIdByName, sNewCharName,nServerIndex);//nServerIndex应该由逻辑服务器传递过来
if ( !nError )
{
if ( m_pSQLConnection->CurrentRow() )
nError = aeNameInuse;
m_pSQLConnection->ResetQuery();
}
else nError = reDbErr;//查询失败返回服务器内部错误
//发生错误则返回
if ( nError )
{
return reDbErr;
}
//通过需要通过名称服务器修改角色名称
//建立更名操作数据
PASYNCNAMEOPDATA pASyncNameOPData = (PASYNCNAMEOPDATA)m_Allocator.AllocBuffer(sizeof(*pASyncNameOPData));
pASyncNameOPData->RenameChar.nCharId = nCharId;
_asncpytA(pASyncNameOPData->RenameChar.sCharName, sNewCharName);
m_ASyncNameOPList.add(pASyncNameOPData);
//向名称同步客户端投递申请角色更名
m_pDataServer->GetDBEngine()->getNameSyncClient()->PostCharRename(nCharId, getClientServerIndex(),
sNewCharName, (UINT_PTR)pASyncNameOPData);
return reSucc;
}
int CDBDataClient::CatchRemoveGuild(int Guild)
{
int nError = 0;
//如果行会名字存在的话
if (!m_pDataServer->GetJobZyMgr()->RemoveGuildById(Guild) )
{
return jxInterSrvComm::DbServerProto::reInterErr;
}
return aeSuccess;
}
//处理创建帮会
int CDBDataClient::CatchCreateGuild(int nActor,LPCSTR sGuildName,LPCSTR sFoundName,int nIndex,Uint64 hActor,BYTE nZY,INT_PTR nIcon)
{
DECLARE_FUN_TIME_PROF()
int nError = 0;
CREATEGUILD_DATA CreateGuildData;//创建帮会的数据结构
//如果数据库尚未连接则无法处理
if ( !m_pSQLConnection->Connected() )
{
OutputMsg(rmError, _T("数据客户端(%s:%d, %s:%d)请求创建帮会,但数据库连接尚未就绪"),
getClientName(), getClientServerIndex(), GetRemoteHost(), GetRemotePort() );
return aeLocalDataBaseError;
}
//解码新角色名
//sprintf_s(CreateGuildData.sGuildName,"%s",sGuildName);
//sprintf_s(CreateGuildData.sFoundName,"%s",sFoundName);
memcpy(CreateGuildData.sGuildName,sGuildName,sizeof(CreateGuildData.sGuildName));
memcpy(CreateGuildData.sFoundName,sFoundName,sizeof(CreateGuildData.sFoundName));
CreateGuildData.nZY = nZY;
CreateGuildData.nIndex = nIndex;
CreateGuildData.hActor = hActor;
CreateGuildData.nActorid = nActor;
CreateGuildData.nServerIndex = getClientServerIndex();
CreateGuildData.wIcon =(WORD) nIcon;
//检查数据合法性不合法则返回ASYNCRERR_INVALIDDATA错误
if ( !CreateGuildData.sGuildName[0] || strlen(CreateGuildData.sGuildName) < 1 )
{
return jxInterSrvComm::DbServerProto::reNameError;
}
//将角色名称的第一个字符之后的字母转换为小写
//m_pDataServer->GetDBEngine()->LowerCaseNameStr(CreateGuildData.sGuildName,sizeof(CreateGuildData.sGuildName));
INT_PTR nLen = CDBServer::GetStrLenUtf8(CreateGuildData.sGuildName);
//校验行会名称最大长度
if ( nLen <= 0 || nLen > GUILD_NAME_MAX_LEN || !m_pDataServer->GetDBEngine()->CheckNameStr(CreateGuildData.sGuildName))
{
OutputMsg(rmError,_T("guild name is invalid!name=%s"),CreateGuildData.sGuildName);
return jxInterSrvComm::DbServerProto::reNameError;
}
int nServerIndex = getClientServerIndex();
//如果行会名字存在的话
if (m_pDataServer->GetJobZyMgr()->IsGuildNameExist(CreateGuildData.sGuildName,nServerIndex) )
{
return jxInterSrvComm::DbServerProto::reNameInUse;
}
//先通过名称服务器同步帮会名称并申请帮会ID创建帮会的实际操作将在名称服务器返回帮会ID后进行
//建立创建帮会操作数据
PASYNCNAMEOPDATA pASyncNameOPData = (PASYNCNAMEOPDATA)m_Allocator.AllocBuffer(sizeof(*pASyncNameOPData));
pASyncNameOPData->CreateGuild = CreateGuildData;
m_ASyncNameOPList.add(pASyncNameOPData);
//向名称同步客户端投递同步帮会名称并申请帮会ID的消息
m_pDataServer->GetDBEngine()->getNameSyncClient()->PostAllocateGuildId(getClientServerIndex(),
CreateGuildData.sGuildName, (UINT_PTR)pASyncNameOPData);
return aeSuccess;
}
BOOL CDBDataClient::HasRemainData()
{
char *sptr;
PDATABUFFER pBuffer;
//如果有异步名称操作数据则返回TRUE
if ( m_ASyncNameOPList.count() > 0 )
return TRUE;
//如果消息队列非空则仍需继续处理
if ( getInternalMessageCount() > 0 )
return TRUE;
//如果网络数据包未处理完毕则返回TRUE
pBuffer = getRecvBuffer();
if ( pBuffer->nOffset > 0 )
{
if ( sptr = strchr(pBuffer->pPointer, '#') )
{
if ( sptr = strchr(sptr, '!') )
return TRUE;
}
}
pBuffer = getProcRecvBuffer();
if ( pBuffer->nOffset > 0 )
{
if ( sptr = strchr(pBuffer->pPointer, '#') )
{
if ( sptr = strchr(sptr, '!') )
return TRUE;
}
}
return FALSE;
}
bool CDBDataClient::OnValidateRegData(const jxSrvDef::PSERVER_REGDATA pRegData)
{
return pRegData->GameType == SERVER_REGDATA::GT_JianXiaoJiangHu && pRegData->ServerType == GameServer;
}
void CDBDataClient::OnRegDataValidated()
{
if (m_pDataServer)
m_pDataServer->UpdateLogicClientList();
}

View File

@@ -0,0 +1,197 @@
#ifndef _DB_DATA_CLIENT_H_
#define _DB_DATA_CLIENT_H_
/*****
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
●重要说明 ●
在2007年开发的c版的dbserver中如果保存数据失败则会将SQL语句转储到
内存中并在退出的时候保存到文件,启动再加载进内存。同时当客户端选择角色
的时候判断角色ID是否在转储列表中如果存在则提示保护数据安全并禁止进入
游戏。
目前游戏引擎具有保存角色数据失败转储文件到内存以及硬盘的功能并可在
启动时恢复数据,因此本版本的数据服务程序将不再提供保存角色失败的转储功
能。角色数据保存失败将完全依赖于游戏引擎的内存以及文件的转储机制。
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
*****/
class CDBDataServer;
class CDataPacket;
class CDBDataClient : public CCustomJXServerClientSocket,
public ILogicDBRequestHost
{
friend class CDBDataServer;
friend class CDBDataCache;
friend class CDBDataClientHandler;
public:
typedef CCustomJXServerClientSocket Inherited;
typedef VOID (CDBDataClient::*OnHandleSockPacket)(CDataPacketReader &packet);
public:
CDBDataClient(CDBDataServer *lpDataServer, CSQLConenction *lpSQLConnection, SOCKET nSocket, PSOCKADDR_IN pAddrIn);
~CDBDataClient();
//判断是否具有尚未处理完成对的数据
BOOL HasRemainData();
//////////////////////////////////////////////////////////////////////////
// ILogicDBRequestHost
CDataPacket& AllocDataPacket(const jxSrvDef::INTERSRVCMD nCmd);
void FlushDataPacket(CDataPacket &packet);
void Trace()
{
OutputMsg(rmNormal,"CDBDataClient Trace %s",getClientName());
m_sDataHandler.Trace();
OutputMsg(rmNormal,"---BufferAllocator start---");
CBufferAllocator::ALLOCATOR_MEMORY_INFO memoryInfo;
m_Allocator.GetMemoryInfo(&memoryInfo);
OutputMsg(rmNormal,"super alloc=%d,free=%d",(int)memoryInfo.SuperBuffer.dwAllocSize,(int)memoryInfo.SuperBuffer.dwFreeSize);
OutputMsg(rmNormal,"large alloc=%d,free=%d",(int)memoryInfo.LargeBuffer.dwAllocSize,(int)memoryInfo.LargeBuffer.dwFreeSize);
OutputMsg(rmNormal,"middle alloc=%d,free=%d",(int)memoryInfo.MiddleBuffer.dwAllocSize,(int)memoryInfo.MiddleBuffer.dwFreeSize);
OutputMsg(rmNormal,"small alloc=%d,free=%d",(int)memoryInfo.SmallBuffer.dwAllocSize,(int)memoryInfo.SmallBuffer.dwFreeSize);
OutputMsg(rmNormal,"---BufferAllocator end---");
}
protected:
//覆盖连接断开的函数
VOID OnDisconnected();
/* 覆盖父类连接断开的函数以便情况注册数据,从而使得对象可以重用 */
VOID Disconnected();
//覆盖套接字错误的函数
VOID OnError(INT errorCode);
//覆盖处理内部消息的函数
virtual VOID DispatchInternalMessage(UINT uMsg, UINT64 uParam1, UINT64 uParam2, UINT64 uParam3,UINT64 uParam4);
/*** 子类需覆盖的函数集 ***/
/* 处理单个通信数据包
* nCmd 通信消息命令
* inPacket 已经读取出通信命令的数据包,数据包的读取位置指向命令数据后的内容
*/
virtual VOID OnDispatchRecvPacket(const jxSrvDef::INTERSRVCMD nCmd, CDataPacketReader &inPacket);
/* 验证客户端注册数据是否有效
*@return 返回true表示注册数据有效并返回false则关闭连接
*/
virtual bool OnValidateRegData(const jxSrvDef::PSERVER_REGDATA pRegData);
virtual void OnRegDataValidated();
//处理创建帮会
int CatchCreateGuild(int nActor,LPCSTR sGuildName, LPCSTR sFoundName,int nIndex,Uint64 hActor,BYTE nZY,INT_PTR nIcon);
int CatchRemoveGuild(int);
private:
//大型SQL查询语句缓冲长度
static const SIZE_T dwHugeSQLBufferSize = 1024 * 1024 * 32;
//定义异步名称操作角色改名和申请创建帮会时同步名称并申请ID的操作的数据结构
typedef union tagASyncNameOPData
{
//角色重命名数据
struct
{
unsigned int nCharId; //角色ID
char sCharName[128];//角色名称
} RenameChar;
//创建帮会数据
jxSrvDef::CREATEGUILD_DATA CreateGuild;
}*PASYNCNAMEOPDATA;
protected:
//清除异步名称操作数据列表
VOID ClearASyncNameOPList();
//从异步名称操作数据列表中提取操作数据如果lpOPData指针存在于异步名称操作数据列表中则删除并返回lpOPData否则返回NULL
PASYNCNAMEOPDATA PeekASyncNameOPData(PASYNCNAMEOPDATA lpOPData);
//在本地数据库中重命名角色如果操作成功则返回0数据库查询失败则返回1数据库重命名操作函数返回失败值时则返回2
INT_PTR RenameCharOnDatabase(const INT_PTR nCharId, LPCSTR sNewCharName);
//处理名称服务器对角色重命名操作的返回
VOID ProcessRenameCharResult(PASYNCNAMEOPDATA lpOPData, const INT_PTR nRenameError);
//处理名称服务器对申请帮会ID操作的返回
VOID ProcessAllocGuildResult(PASYNCNAMEOPDATA lpOPData, const INT_PTR nError, INT_PTR nGuildId);
//处理创建角色
//VOID ProcessCreateActor( INT_PTR nError,unsigned int nActorId,PCREATEACTORDATA pData);
//默认的
VOID DefaultPacket(CDataPacketReader &inPacket);
virtual VOID OnRun();
//VOID LoadActorCombatRank(CDataPacketReader &inPacket);
//VOID LoadActorCombatGameInfo(CDataPacketReader &inPacket);
//VOID UpdateActorCombatAward(CDataPacketReader &inPacket);
//VOID SaveActorCombatGameInfo(CDataPacketReader &inPacket);
//VOID LoadCombatRecord(CDataPacketReader &inPacket);
//VOID SaveCombatRecordToDb(CDataPacketReader &inPacket);
////任务的
//VOID QueryQuestFromDB(CDataPacketReader &inPacket);
//VOID QueryQuestFromDB(int nActorId);
//VOID SaveQuestToDB(CDataPacketReader &inPacket, bool bResp = true);
////int GetMainQuest(int nActorId,CDataPacket& out);
//int SaveMainQuest(int nActorId,char* pBuf,SIZE_T nSize);
//int GetGoingQuest(int nActorid,CDataPacket& out);
//int SaveGoingQuest(int nActorid,int nTaskId,int id,int value);
//int GetRepeatQuest(int nActorid,CDataPacket& out);
//int SaveRepeatQuest(int nActorid,int nTaskId,int qtime);
//int CleanQuestData(int nActorId);
private:
//分派客户端收到的数据包的处理函数
VOID DispatchRecvMsg(LPCSTR lpData, SIZE_T dwSize);
//处理角色重命名
int CatchRenameChar(LPCSTR lpData, SIZE_T dwSize);
/*
* Comments:创建一个帮派成功后,调用本函数向逻辑服务器发送结果
* Param int nErr:错误码
* Param int index:消息在队列中的索引
* Param Uint64 hHandle:创建这个帮派的角色的handle以方便向他发送结果提示语
* Param int nGid:创建成功的话这个是帮派的id号
* Param LPCSTR sGuildName:帮派名称
* Param LPCSTR sFoundName:创始人名称
* Param BYTE nZY:阵营编号
* @Return VOID:
*/
void SendAddGuildResult(int nRawServerId,
int nLoginServerId,
int nErr,
int index,
Uint64 hHandle,
unsigned int nGid,
LPCSTR sGuildName,
LPCSTR sFoundName,
BYTE nZY,
INT_PTR nIcon);
// 新的派发数据包处理函数。只是派发,不处理
void OnDispatchRecvPacketEx(const jxSrvDef::INTERSRVCMD nCmd, CDataPacketReader &inPacket);
void SetNewSQLConnection(CSQLConenction *lpSQLConnection);
private:
CDBDataServer* m_pDataServer; // 所属数据服务器
CSQLConenction* m_pSQLConnection; // 数据库连接对象
CSQLConenction* m_pNewSQLConnection; // 数据库连接对象
TICKCOUNT m_dwClosedTick; // 连接断开的时间
PCHAR m_pHugeSQLBuffer; // 大型SQL查询语句缓冲长度为dwHugeSQLBufferSize
CLockList<PASYNCNAMEOPDATA> m_ASyncNameOPList; // 异步名称操作队列
CCSLock m_ASyncNameOPListLock; //异步名称操作队列锁
CDBDataClientHandler m_sDataHandler; // DB请求处理类
CGateDBReqestHandler m_loginHandler; //登陆的消息
};
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,162 @@
#ifndef DB_DATA_CLIENT_HANDLER_H__
#define DB_DATA_CLIENT_HANDLER_H__
/*
DBClient逻辑处理类。处理来自客户端(主要是逻辑服)的DB请求这里之关系逻辑处理不关心数据接收相关的处理。
原来的DBClient将通信线程和DB请求逻辑处理和在一起在逻辑服DB操作比较频繁、DB查询压力大查询和更新DB
比较缓慢的情况下会导致堆积的未处理请求越来越多延迟很慢并且由于DBClient数据处理不过来导致逻辑服那边堆
积的 DB请求数据包也越来越多造成逻辑服内存消耗巨大。
为解决上述问题将DBClient的数据接收和处理逻辑分开。接收数据线程只关心数据接收不处理逻辑这样不会造
成堆积数据包;同时逻辑处理区分优先级,不是一次性处理完所有大量玩家的存盘数据,分时处理,并且设定优先级策略,
查询数据的优先级高于更新数据的优先级。
*/
class CDBDataClientHandler :
public wylib::thread::CBaseThread,
public CSendPacketPool
{
public:
friend class CDBDataCache;
// ctor and dtor
CDBDataClientHandler();
~CDBDataClientHandler();
/*
* Comments: 开始运行。
* @Param ILogicDBRequestHost* pHost:
* @Param CSQLConenction *lpSQLConnection:
* @Return bool: 成功返回true失败返回false
* @Remark: 开启后台线程并且等待后台线程开始运行。
*/
bool Start(ILogicDBRequestHost* pHost, CSQLConenction *lpSQLConnection);
/*
* Comments:
* @Return bool:
* @Remark:
*/
bool Stop();
/*
* Comments: 添加一个DB请求的消息
* Param jxSrvDef::INTERSRVCMD nCmd: 消息Id
* Param CDataPacketReader & packet: 消息数据
* @Return void:
* @Remark: 将DB请求数据添加到队列中。这里不处理数据。供通信线程调用
*/
void AddMessage(jxSrvDef::INTERSRVCMD nCmd, CDataPacketReader& packet);
CLogicDBReqestHandler& GetDBRequestHandler() { return m_LogicDBReqHandler; }
//追踪内存使用情况
void Trace();
protected:
/*
* Comments: 设置读操作标记
* Param BOOL flag:
* @Return void:
* @Remark: 如果当前有读操作未完成flag设置为true否则设置为false
*/
inline void SetReadOpFlag(BOOL flag)
{
InterlockedExchange(&m_bHasReadOp, flag);
}
/*
* Comments: 获取读操作标记
* @Return bool: 如果当前存在读操作返回true否则返回false
* @Remark:
*/
BOOL HasReadOPFlag() const { return m_bHasReadOp; }
/*
* Comments: 判断当前是否是读操作
* Param jxSrvDef::INTERSRVCMD nCmd:
* @Return bool:
* @Remark:
*/
bool IsReadCmd(jxSrvDef::INTERSRVCMD nCmd);
/*
* Comments: 线程处理函数
* @Return void:
* @Remark:
*/
virtual void OnRountine();
/*
* Comments: 线程逻辑处理函数
* @Return void:
* @Remark:
*/
void ThreadLogicProc();
/*
* Comments: DB请求逻辑处理
* @Return void:
* @Remark: 遍历DB请求列表并且处理。对于玩家存盘请求直接加入到ActorCache数据里头对于查询数据直接执行SQL查询
*/
void RunOne();
/*
* Comments: 分配数据包
* @Return void:
* @Remark:
*/
CDataPacket* AllocPacket();
/*
* Comments: 释放用完的数据包
* Param CDataPacket * packet:
* @Return void:
* @Remark:
*/
void FreePacket(CDataPacket* packet);
/*
* Comments: 销毁数据包列表
* Param CQueueList<CDataPacket * > & pkgList:
* @Return void:
* @Remark: 删除对象
*/
void DestroyPacketList(CQueueList<CDataPacket*>& pkgList);
/*
* Comments: 处理DB请求消息
* Param jxSrvDef::INTERSRVCMD nCmd: 消息码
* Param CDataPacket & packet: 消息参数
* @Return void:
* @Remark:
*/
void HandleDBMessage(jxSrvDef::INTERSRVCMD nCmd, CDataPacket &packet);
private:
CQueueList<CDataPacket*> m_sMsgList; // DB请求消息列表格式消息ID+消息参数)。
CCSLock m_sMsgListLock;
CQueueList<CDataPacket*> m_sFreeList; // 自由消息数据包
CCSLock m_sFreeListLock;
//CBufferAllocator m_allocator; // BuffAllocator用于DataPacket的内存分配
CDBDataCache m_sActorCacheData; // 角色DB存盘Cache数据
volatile long m_bHasReadOp; // 当前是否有读DB操作
volatile long m_lStop; // 线程停止标记
volatile long m_lHasStart; //是否已经启动
volatile long m_lLogicIsRunning; //逻辑线程是否已经启动
ILogicDBRequestHost* m_pHost; //
CCSLock m_sStartLock; // 线程开始启动锁
#ifdef WIN32
HANDLE m_hStartEvent; //启动信号事件
HANDLE m_hStopEvent; //停止信号事件
#else
sem_t m_hStartEvent; //启动信号事件
sem_t m_hStopEvent; //停止信号事件
#endif
CLogicDBReqestHandler m_LogicDBReqHandler; // DB请求处理
static int s_nDBHandleSleep; // DB逻辑处理睡眠时间
TICKCOUNT m_memoryTimer; //定时器
};
#endif // _DB_DATA_CLIENT_HANDLER_H__

View File

@@ -0,0 +1,573 @@

#include "StdAfx.h"
#include "FeeDb.h"
bool CDBDataServer::m_bGableIsClose =false;
CDBDataServer::CDBDataServer(CDBServer* lpDBEngine)
{
m_pDBServer = lpDBEngine;
SetServiceName("数据");
m_dwDeleteOutDataTick = 0;
m_SQLConnection.SetMultiThread(TRUE);
TICKCOUNT curTick = _getTickCount();
m_dwNextDumpTime = curTick + sDumpInterval;
m_dwSaveNameFile = curTick + sSaveNameInterval;
m_dwNextUpdateClientListTick = curTick + sUpdateLogicClientListInterval;
m_jobzyMgr.SetParam(&m_NowSQLConnection);
m_nNextZyJobSaveTime = curTick + 43200000; //12小时存一次盘
m_pCurClient = NULL;
m_CloseClientList.empty();
}
CDBDataServer::~CDBDataServer()
{
}
CCustomServerClientSocket* CDBDataServer::CreateClientSocket(SOCKET nSocket, PSOCKADDR_IN pAddrIn)
{
// 记录这个DBDataClient
m_pCurClient = new CDBDataClient(this, &m_NowSQLConnection, nSocket, pAddrIn);
m_pCurClient->SetNewSQLConnection(&m_SQLConnection);
return m_pCurClient;
}
VOID CDBDataServer::DestroyClientSocket(CCustomServerClientSocket *pClientSocket)
{
m_CloseClientLock.Lock();
CDBDataClient* pDC = (CDBDataClient*)pClientSocket;
for(INT_PTR i= m_CloseClientList.count() -1; i >=0; i-- )
{
if(m_CloseClientList[i] == pDC)
{
m_CloseClientLock.Unlock();
return;
}
}
OutputMsg(rmNormal, _T("Start to call datahandler.stop()"));
pDC->m_sDataHandler.Stop();
OutputMsg(rmNormal, _T("Call datahandler.stop() return"));
m_CloseClientList.add(pDC);
m_CloseClientLock.Unlock();
if ((void*)pClientSocket == (void*)m_pCurClient)
{
m_pCurClient = NULL;
}
}
VOID CDBDataServer::ProcessClients()
{
Inherited::ProcessClients();
ProcessClosedClients();
}
VOID CDBDataServer::DispatchInternalMessage(UINT uMsg, UINT64 uParam1, UINT64 uParam2, UINT64 uParam3,UINT64 uParam4)
{
TICKCOUNT nCurrentTick;
OutputMsg(rmTip, "CDBDataServer::DispatchInternalMessage:%d", uMsg);
switch(uMsg)
{
//向指定的服务器发送打开角色加载认证的消息(Param1=服务器ID,Param2=会话ID,Param3=角色ID)
case DSIM_POST_OPEN_CHAR_LOAD:
{
nCurrentTick = _getTickCount();
int nTime = (int)(nCurrentTick - uParam4);
OutputMsg(rmTip,"actorid=%lld,to DispatchInternalMessage, pass=%d ms",uParam3,nTime);
PostClientInternalMessages(uParam1, DCIM_SEND_LOAD_ACTOR, uParam2, uParam3, nCurrentTick,0);
}
break;
case DCIM_POST_CREATE_ACTOR_RESULT:
{
PostClientInternalMessages(uParam1, DCIM_CREATE_ACTOR_RESULT, uParam2, uParam3, uParam4,0);
break;
}
case DCIM_POST_CREATE_CS_ACTOR_RESULT:
{
PostClientInternalMessages(uParam1, DCIM_CREATE_CS_ACTOR_RESULT, uParam2, uParam3, uParam4,0);
break;
}
//向指定的服务器返回重命名角色的结果(Param1=服务器ID,Param2=操作结果,Param3=申请更名操作时传递的操作唯一标识)
case DSIM_POST_RENAMECHAR_RESULT:
//将此消息转发到指定ID内部数据客户端
PostClientInternalMessages(uParam1, DCIM_RENAMECHAR_RESULT, uParam2, uParam3, 0);
break;
//名称客户端向指定的服务器返回申请帮会ID的结果(Param1=服务器ID,
//Param2=2个INT_PTR的数组[0]保存操作结果,[1]保存帮会ID处理消息后必须对数组进行free释放,
//Param3=申请帮会ID操作时传递的操作唯一标识)
case DSIM_POST_ALLOC_GUILID_RESULT:
//将此消息转发到指定ID内部数据客户端
PostClientInternalMessages(uParam1, DCIM_ALLOC_GUILID_RESULT, ((PINT_PTR)uParam2)[0], ((PINT_PTR)uParam2)[1], uParam3);
//释放返回值数组
free((LPVOID)uParam2);
break;
}
}
VOID CDBDataServer::OnSocketDataThreadStop()
{
Inherited::OnSocketDataThreadStop();//调用父类的处理函数以便关闭所有连接
OutputMsg( rmTip, _T("正在等待所有数据客户端的数据处理完毕……"));
do
{
SingleRun();
Sleep(10);
}
while ( !AllDataProcessed() );
//强制释放所有客户端连接占用的内存(销毁连接对象)
FreeAllClient();
OutputMsg( rmTip, _T("所有数据客户端的数据已处理完毕!"));
}
VOID CDBDataServer::SingleRun()
{
//连接数据库
ConnectSQL();
Inherited::SingleRun();
}
VOID CDBDataServer::OnRun()
{
TICKCOUNT dwCurTick = _getTickCount();
////每分钟从数据库中删除一次过期数据,过期数据在保存角色数据的时候将角色对应的
////物品、技能、任务等数据的charid字段更新为了0将多次零散的SQL delete操作合并
////为多次update一次delete以提高数据库操作性能
if ( m_NowSQLConnection.Connected() && dwCurTick >= m_dwDeleteOutDataTick )
{
if(m_dwDeleteOutDataTick)
{
// //删除过期背包物品
if ( !m_NowSQLConnection.Exec( "delete from actorbagitem where actorid = 0;" ) )
m_NowSQLConnection.ResetQuery();
//删除过期装备物品
if ( !m_NowSQLConnection.Exec( "delete from actorequipitem where actorid = 0;" ) )
m_NowSQLConnection.ResetQuery();
//删除过期仓库物品
if ( !m_NowSQLConnection.Exec( "delete from actordepotitem where actorid = 0;" ) )
m_NowSQLConnection.ResetQuery();
//删除过期技能
if ( !m_NowSQLConnection.Exec( "delete from skill where actorid = 0;" ) )
m_NowSQLConnection.ResetQuery();
//删除过期任务进度
if ( !m_NowSQLConnection.Exec( "delete from goingquest where actorid = 0;" ) )
m_NowSQLConnection.ResetQuery();
//删除过期完成任务数据
if ( !m_NowSQLConnection.Exec( "delete from repeatquest where actorid = 0;" ) )
m_NowSQLConnection.ResetQuery();
//删除过期的好友数据
if ( !m_NowSQLConnection.Exec( "delete from actorfriends where actorid = 0;" ) )
m_NowSQLConnection.ResetQuery();
//删除过期的宠物数据
if (!m_NowSQLConnection.Exec("delete from actorpets where actorid=0;"))
m_NowSQLConnection.ResetQuery();
if (!m_NowSQLConnection.Exec("delete from actorpetitem where actorid=0;"))
m_NowSQLConnection.ResetQuery();
if (!m_NowSQLConnection.Exec("delete from petskills where actorid=0;"))
m_NowSQLConnection.ResetQuery();
if (!m_NowSQLConnection.Exec("delete from actorrelation where actorid=0;"))
m_NowSQLConnection.ResetQuery();
}
m_dwDeleteOutDataTick = dwCurTick + 60000;
}
if(m_SQLConnection.Connected() && dwCurTick >= m_dwNextDumpTime)
{
//每5分钟dump一次
if(m_dwNextDumpTime)
{
CTimeProfMgr::getSingleton().dump();
}
m_dwNextDumpTime = dwCurTick + sDumpInterval; //5分钟执行一次dump
}
if ( dwCurTick >= m_dwSaveNameFile)//保存随机名字的文件
{
if(m_dwSaveNameFile)
{
//m_pDBServer->SaveNameFile();
}
m_dwSaveNameFile += sSaveNameInterval;//5分钟保存一次
}
if (dwCurTick >= m_dwNextUpdateClientListTick)
{
UpdateLogicClientList();
m_dwNextUpdateClientListTick = dwCurTick + sUpdateLogicClientListInterval;
}
if (m_nNextZyJobSaveTime <= dwCurTick)
{
//现在只有职业数据需要存盘
if (m_jobzyMgr.HasLoadJobData() && m_NowSQLConnection.Connected())
{
m_jobzyMgr.SaveJobData();
}
m_nNextZyJobSaveTime = dwCurTick + 43200000; //12个小时存一次
}
// 读取充值指令
if (m_FeeSQLConnection.Connected() && dwCurTick >= m_nNextReadFeeTime)
{
char token[128];
if (m_pCurClient && m_pCurClient->connected())
{
int nError = m_FeeSQLConnection.Query("call loadfee_notice(%d);", CDBServer::s_pDBEngine->getServerIndex());
if ( !nError )
{
if (MYSQL_ROW pRow = m_FeeSQLConnection.CurrentRow())
{
int nCount = m_FeeSQLConnection.GetRowCount();
CDataPacket& out = m_pCurClient->allocProtoPacket(dcNoticeFee);
INT_PTR pos = out.getPosition();
out << (int)0;
nCount = 0;
unsigned int nActorId;
ACCOUNT sAccount;
do
{
sscanf(pRow[0], "%u", &nActorId);
strlcpy((sAccount), (pRow[1]? pRow[1] : ""), sizeof(sAccount));
if(nActorId != 0) {
if (m_ActorIdMap[nActorId])
{
nCount++;
OutputMsg(rmTip,_T("[Fee]0-1 充值通知在线ActorId%dAccount%s"),nActorId,sAccount);
out << nActorId;
out.writeString(sAccount);
} else {
OutputMsg(rmTip,_T("[Fee]0-2 充值通知离线ActorId%dAccount%s"),nActorId,sAccount);
}
} else {
nCount++;
OutputMsg(rmTip,_T("[Fee]0-3 充值通知不指定角色ActorId%dAccount%s"),nActorId,sAccount);
out << nActorId;
out.writeString(sAccount);
}
}
while(pRow = m_FeeSQLConnection.NextRow());
int* pCount = (int*)out.getPositionPtr(pos);
*pCount = nCount;
m_pCurClient->flushProtoPacket(out);
}
m_FeeSQLConnection.ResetQuery();
}
else
{
OutputMsg(rmTip, _T("m_FeeSQLConnection serverindex:%d nError:%d"),CDBServer::s_pDBEngine->getServerIndex(), nError);
}
m_nNextReadFeeTime = dwCurTick + 1000;
}
}
}
void CDBDataServer::UpdateLogicClientList()
{
char szData[10240];
CDataPacket packet(szData, sizeof(szData));
packet.setLength(0);
size_t nPos = packet.getPosition();
CBaseList<int> sList;
CDBDataClient *pClient;
for (INT_PTR i = 0; i < m_ClientList.count(); i++)
{
pClient = (CDBDataClient *)m_ClientList[i];
if (pClient->registed())
{
sList.add((int)pClient->getClientServerIndex());
}
}
//OutputMsg(rmError, _T("%s update client list, count=%d"), __FUNCTION__, (int)sList.count());
/*
CDBCenterClient *pDBCenterClient = GetDBEngine()->getDBCenterClient();
pDBCenterClient->PostUpdateLogicClientList(sList);
*/
}
void CDBDataServer::Trace()
{
OutputMsg(rmNormal,"CDBDataServer Trace start...");
CDBDataClient *pClient;
for (INT_PTR i = 0; i < m_ClientList.count(); i++)
{
pClient = (CDBDataClient *)m_ClientList[i];
if (pClient && pClient->registed() )
{
pClient->Trace();
}
}
OutputMsg(rmNormal,"CDBDataServer Trace end...");
}
INT_PTR CDBDataServer::SendDataClientMsg(const INT_PTR nServerIndex, LPCVOID lpData, SIZE_T dwSize)
{
INT_PTR i, nResult = 0;
CDBDataClient *pClient;
for (i=m_ClientList.count()-1; i>-1; --i)
{
pClient = (CDBDataClient*)m_ClientList[i];
if ( pClient->registed() )
{
if ( !nServerIndex || pClient->getClientServerIndex() == nServerIndex )
{
pClient->AppendSendBuffer(lpData, dwSize);
nResult++;
}
}
}
return nResult;
}
BOOL CDBDataServer::getGameReady(int nSrvIdx)
{
INT_PTR i;
BOOL result = FALSE;
CDBDataClient *pClient;
for (i=m_ClientList.count()-1; i>-1; --i)
{
pClient = (CDBDataClient*)m_ClientList[i];
if ( pClient->registed() )
{
if ( !nSrvIdx || pClient->getClientServerIndex() == nSrvIdx )
{
result = TRUE;
break;
}
}
}
return result;
}
INT_PTR CDBDataServer::PostClientInternalMessages(UINT64 nServerIndex, UINT uMsg, UINT64 uParam1, UINT64 uParam2, UINT64 uParam3,UINT64 uParam4)
{
INT_PTR i, nResult = 0;
CDBDataClient *pClient;
for (i=m_ClientList.count()-1; i>-1; --i)
{
pClient = (CDBDataClient*)m_ClientList[i];
if ( pClient->registed() )
{
if ( !nServerIndex || pClient->getClientServerIndex() == nServerIndex )
{
pClient->PostInternalMessage(uMsg, uParam1, uParam2, uParam3,uParam4);
nResult++;
}
}
}
return nResult;
}
BOOL CDBDataServer::ConnectSQL()
{
if ( !m_SQLConnection.Connected() )
{
if ( _getTickCount() >= m_dwReconnectSQLTick )
{
m_pDBServer->SetupSQLConnection(&m_SQLConnection);
if ( m_SQLConnection.Connect() )
{
if (m_pDBServer->IsUtf8())
{
if (mysql_set_character_set(m_SQLConnection.GetMySql(),"utf8"))
{
OutputMsg( rmError, _T("设置utf8编码出错 !!!") );
}
}
//mysql_options(m_SQLConnection.GetMySql(), MYSQL_SET_CHARSET_NAME, "utf8");
//if (m_SQLConnection.Exec("charset utf8"))
//{
// OutputMsg( rmError, _T("设置utf8字符编码出错"));
//}
//else
//{
// m_SQLConnection.ResetQuery();
//}
return TRUE;
}
//如果连接SQL失败则将在5秒后重试
m_dwReconnectSQLTick = _getTickCount() + 5 * 1000;
return FALSE;
}
}
if (!m_FeeSQLConnection.Connected())
{
if ( _getTickCount() >= m_dwReconnectSQLTick )
{
m_pDBServer->SetupSQLConnection(&m_FeeSQLConnection);
OutputMsg(rmTip, _T("m_FeeSQLConnection fail "));
if ( m_FeeSQLConnection.Connect() )
{
OutputMsg(rmTip, _T("m_FeeSQLConnection success"));
return TRUE;
}
//如果连接SQL失败则将在5秒后重试
m_dwReconnectSQLTick = _getTickCount() + 5 * 1000;
return FALSE;
}
}
if (!m_NowSQLConnection.Connected())
{
if ( _getTickCount() >= m_dwReconnectSQLTick )
{
m_pDBServer->SetupSQLConnection(&m_NowSQLConnection);
OutputMsg(rmTip, _T("m_NowSQLConnection fail "));
if ( m_NowSQLConnection.Connect() )
{
if (m_pDBServer->IsUtf8())
{
if (mysql_set_character_set(m_NowSQLConnection.GetMySql(),"utf8"))
{
OutputMsg( rmError, _T("设置utf8编码出错 !!!") );
}
}
m_jobzyMgr.LoadJobInitData();
//m_jobzyMgr.LoadZyInitData(); //阵营的数据暂时屏蔽
m_jobzyMgr.LoadActorNameInitData();
m_jobzyMgr.LoadGuildNameInitData();//行会名字
OutputMsg(rmTip, _T("NowSQL mysql connection character set: %s"), mysql_character_set_name(m_NowSQLConnection.GetMySql()));
// OutputMsg(rmTip, _T("m_NowSQLConnection success()"));
return TRUE;
}
//如果连接SQL失败则将在5秒后重试
m_dwReconnectSQLTick = _getTickCount() + 5 * 1000;
return FALSE;
}
}
return TRUE;
}
VOID CDBDataServer::ProcessClosedClients()
{
INT_PTR i;
CDBDataClient *pClient;
TICKCOUNT dwCurTick = _getTickCount();
//必须降序循环,因为连接可能在循环中被移除
for ( i=m_CloseClientList.count()-1; i>-1; --i )
{
pClient = m_CloseClientList[i];
//连接被关闭后依然要调用Run函数因为可能有重要的网络数据或逻辑数据没有处理完
pClient->Run();
//连接关闭5分钟后再释放连接对象
if ((dwCurTick - pClient->m_dwClosedTick >= 5 * 60 * 1000) || pClient->m_dwClosedTick == 0)
{
m_CloseClientList.remove(i);
delete pClient;
}
}
}
BOOL CDBDataServer::AllDataProcessed()
{
INT_PTR i;
CDBDataClient *pClient;
//如果消息队列非空则仍需继续处理
if ( getInternalMessageCount() > 0 )
return FALSE;
//判断数据客户端的数据是否处理完毕
for ( i=m_ClientList.count()-1; i>-1; --i )
{
pClient = (CDBDataClient*)m_ClientList[i];
if ( !pClient->registed() )
continue;
if ( pClient->HasRemainData() )
return FALSE;
}
for ( i=m_CloseClientList.count()-1; i>-1; --i )
{
pClient = m_CloseClientList[i];
if ( !pClient->registed() )
continue;
if ( pClient->HasRemainData() )
return FALSE;
}
return TRUE;
}
VOID CDBDataServer::FreeAllClient()
{
INT_PTR i;
CDBDataClient *pClient;
//关闭所有客户端
CloseAllClients();
//销毁所有连接
for ( i=m_CloseClientList.count()-1; i>-1; --i )
{
pClient = m_CloseClientList[i];
//delete pClient;
pClient->m_dwClosedTick = 0;
}
//m_CloseClientList.clear();
}
INT_PTR CDBDataServer::GetAvailableDataClientCount(const INT_PTR nServerIndex)
{
//OutputMsg( rmTip, _T("GetAvailableDataClientCount():nServerIndex=%d"),nServerIndex );
if ( nServerIndex == 0 )
{
return m_ClientList.count();
}
INT_PTR i, nResult = 0;
CDBDataClient *pClient;
m_ClientList.lock();
for ( i=m_ClientList.count() - 1; i > - 1; --i )
{
pClient = (CDBDataClient*)m_ClientList[i];
if ( pClient->connected() && pClient->getClientServerIndex() == nServerIndex )
{
nResult++;
}
else
{
//test
//OutputMsg( rmError, _T("connected()=%d,ClientIndex=%d"),(int)(pClient->connected()),pClient->getClientServerIndex() );
}
}
m_ClientList.unlock();
return nResult;
}
BOOL CDBDataServer::IsCharSavedFailure(const INT_PTR nCharId)
{
//测试先返回FALSE
return FALSE;
}

View File

@@ -0,0 +1,181 @@
#ifndef _DB_DATA_SERVER_H_
#define _DB_DATA_SERVER_H_
#include <map>
class CJobZyCountMgr;
class CDBServer;
class CDBDataClient;
//内部消息号
typedef enum tagDbServerInterMsg
{
DSIM_POST_OPEN_CHAR_LOAD = 3001,
DSIM_POST_RENAMECHAR_RESULT,
DSIM_POST_ALLOC_GUILID_RESULT,
DCIM_POST_CREATE_ACTOR_RESULT, //收到了名字服务器返回的创建角色的结构
DCIM_POST_CREATE_CS_ACTOR_RESULT, //收到了名字服务器返回的创建角色的结构
DCIM_RENAMECHAR_RESULT = 4001,
DCIM_ALLOC_GUILID_RESULT,
DCIM_SEND_LOAD_ACTOR,
DCIM_CREATE_ACTOR_RESULT,
DCIM_CREATE_CS_ACTOR_RESULT,//跨服角色创建
};
class CDBDataServer
: public CCustomServerSocket
{
public:
typedef CCustomServerSocket Inherited;
static const int sSaveNameInterval = 300000; // 保存随机名称间隔
static const int sDumpInterval = 300000; // dump时间间隔
static const int sUpdateLogicClientListInterval = 10000; // 10s更新一次
static bool m_bGableIsClose;
public:
CDBDataServer(CDBServer* lpDBEngine);
~CDBDataServer();
//获取所属DB引擎
inline CDBServer* GetDBEngine(){ return m_pDBServer; }
//获取指定ID的数据客户端数量如果nServerIndex参数为0则返回总的已连接的数据客户端数量
INT_PTR GetAvailableDataClientCount(const INT_PTR nServerIndex);
//判断指定的角色是否保存数据失败了如果角色的数据通过DataClient保存失败则处于数据同步和安全考虑角色将不能登录
BOOL IsCharSavedFailure(const INT_PTR nCharId);
//向特定的数据服务器投递打开角色加载认证数据
inline VOID PostOpenCharLoad(UINT64 nServerIndex, UINT64 nSessionId, UINT64 nCharId,UINT64 nCurrentTick )
{
PostInternalMessage(DSIM_POST_OPEN_CHAR_LOAD, nServerIndex, nSessionId, nCharId,nCurrentTick);
}
/*投递通过名称服务器申请帮会名称的结果
*pResult 使用一个包含2个INT_PTR的数组[0]保存操作结果(jxSrvDef::ASYNC_OPERROR)[1]保存帮会ID
*/
inline VOID PostAllocGuildNameResult(INT_PTR nServerIndex, PINT_PTR pResult, UINT_PTR lpCreateGuildIdent)
{
PostInternalMessage(DSIM_POST_ALLOC_GUILID_RESULT, nServerIndex, (UINT_PTR)pResult, lpCreateGuildIdent);
}
/* 投递通过名称服务器修改一个角色的名字的结果 */
inline VOID PostRenameCharResult(INT_PTR nServerIndex, jxInterSrvComm::NameServerProto::NAMESERVER_OPERROR eError, UINT_PTR lpRenameCharIdent)
{
PostInternalMessage(DSIM_POST_RENAMECHAR_RESULT, nServerIndex, eError, lpRenameCharIdent);
}
inline VOID PostCreateActorResult(INT_PTR nServerIndex, int eError, unsigned int nActorId,PCREATEACTORDATA pData)
{
PostInternalMessage(DCIM_POST_CREATE_ACTOR_RESULT, nServerIndex, eError,nActorId,(UINT64)pData);
}
inline VOID PostCreateCrossServerActorResult(INT_PTR nServerIndex, int eError, unsigned int nActorId,PCREATEACTORDATA pData)
{
PostInternalMessage(DCIM_POST_CREATE_CS_ACTOR_RESULT, nServerIndex, eError,nActorId,(UINT64)pData);
}
// 检查逻辑服务器是否已经连接上来
BOOL getGameReady(int nSrvIdx);
inline CSQLConenction* GetSQLConnection() { return &m_SQLConnection; }
/*
* Comments: 更新连接的逻辑客户端列表
* @Return void:
* @Remark:
*/
void UpdateLogicClientList();
//获取玩家和阵营的人数的管理器
inline CJobZyCountMgr *GetJobZyMgr()
{
return &m_jobzyMgr;
}
//查找内存的使用情况
void Trace();
protected:
//覆盖创建连接对象的函数
CCustomServerClientSocket* CreateClientSocket(SOCKET nSocket, PSOCKADDR_IN pAddrIn);
//覆盖销毁一个已经建立的客户端对象
VOID DestroyClientSocket(CCustomServerClientSocket *pClientSocket);
//覆盖父类处理客户端连接的函数
VOID ProcessClients();
//覆盖分派内部消息处理的函数
VOID DispatchInternalMessage(UINT uMsg, UINT64 uParam1, UINT64 uParam2, UINT64 uParam3,UINT64 uParam4);
//覆盖当客户端连接处理线程停止前调用函数
VOID OnSocketDataThreadStop();
//覆盖父类例行执行函数
VOID SingleRun();
//覆盖父类调用例行RUN的函数
VOID OnRun();
//排行榜保存时间读取
BOOL LoadRefreshRankTime();
//排行榜保存时间
VOID SaveRefreshRankTime();
//向数据客户端追加发送数据如果nServerIndex为0则向所有数据客户端追加发送数据
//lpData是编码后的数据如果为空则dwSize必须为0如果boPrimary为TRUE则数据会优先发送
//函数返回向多少个数据客户端的发送缓冲追加了数据
INT_PTR SendDataClientMsg(const INT_PTR nServerIndex, LPCVOID lpData, SIZE_T dwSize);
//向数据客户端投递内部消息如果nServerIndex为0则向所有数据客户端投递消息
//函数返回向多少个数据客户端投递了消息
INT_PTR PostClientInternalMessages(UINT64 nServerIndex, UINT uMsg, UINT64 uParam1, UINT64 uParam2, UINT64 uParam3,UINT64 uParam4=0);
private:
//连接到数据库
BOOL ConnectSQL();
//处理已经关闭的数据客户端对象
VOID ProcessClosedClients();
//判断是否所有数据数据均已处理完毕以便安全的停止服务
BOOL AllDataProcessed();
//强制释放所有客户端连接占用的内存(销毁连接对象)
VOID FreeAllClient();
private:
CDBServer* m_pDBServer; //所属数据引擎管理器
CSQLConenction m_SQLConnection; //数据库连接对象--数据线程调用
TICKCOUNT m_dwReconnectSQLTick;//下次重新连接数据的时间
TICKCOUNT m_dwDeleteOutDataTick;//下次从数据库中删除作废数据的时间
TICKCOUNT m_dwNextDumpTime; //下次dmp的时间
TICKCOUNT m_dwSaveNameFile;
CBaseList<CDBDataClient*> m_CloseClientList; //已经关闭的数据客户端列表
TICKCOUNT m_dwNextUpdateClientListTick; // 下次更新客户端列表时间
CCSLock m_CloseClientLock;
CJobZyCountMgr m_jobzyMgr; //管理职业平衡以及阵营平衡的管理器
TICKCOUNT m_nNextZyJobSaveTime;
public://TODO 这里暂时这样后续需要换成Get/Set API提供访问修改
CDBDataClient* m_pCurClient;
std::map<unsigned int,bool> m_ActorIdMap;
CCSLock m_ActorIdMapLock;
CSQLConenction m_FeeSQLConnection; //充值数据库连接对象
TICKCOUNT m_nNextReadFeeTime;//下次读取充值指令的时间
public://TODO 这里暂时这样后续需要换成Get/Set API提供访问修改
CSQLConenction m_NowSQLConnection; //当前线程数据库对象
private:
///*** 定义内部逻辑处理消息号 ***/
////向特定的数据服务器投递打开角色加载认证数据Param1=服务器IDParam2=会话IDParam3=角色ID
//static const UINT DSIM_POST_OPEN_CHAR_LOAD = 3001;
////名称客户端向指定的服务器返回重命名角色的结果(Param1=服务器ID,Param2=操作结果,Param3=申请更名操作时传递的操作唯一标识)
//static const UINT DSIM_POST_RENAMECHAR_RESULT = 3002;
///*名称客户端向指定的服务器返回申请帮会ID的结果
// Param1=服务器ID,
// Param2=2个INT的数组[0]保存操作结果,[1]保存帮会ID处理消息后必须对数组进行free释放,
// Param3=申请帮会ID操作时传递的操作唯一标识
//*/
//static const UINT DSIM_POST_ALLOC_GUILID_RESULT = 3003;
};
#endif

1021
server/DBServer/DBGate.cpp Normal file

File diff suppressed because it is too large Load Diff

125
server/DBServer/DBGate.h Normal file
View File

@@ -0,0 +1,125 @@
#ifndef _GATE_H_
#define _GATE_H_
using namespace wylib::time::tick64;
using namespace wylib::container;
class CDBGateManager;
class CDBServer;
/*******************************************************
网关类
********************************************************/
class CDBGate
: public CCustomServerGate
{
friend class CDBGateManager;
public:
CDBGate();
virtual ~CDBGate();
/*
* Comments: 逻辑服务器返回收到了玩家的数据
* Param const unsigned int nSessionID: sessionID
* Param const unsigned int nActorId: 玩家的的actorID
* @Return void:
*/
void OnLogicRsponseSessionData(const unsigned int nSessionID,const unsigned int nActorId);
static bool m_bGableIsClose; //盗梦空间是否关闭
virtual void OnRountine()
{
CCustomServerGate::OnRountine();
}
protected:
/*** 覆盖父类的逻辑处理函数集 ***/
CCustomServerGateUser* CreateGateUser();
VOID DestroyGateUser(CCustomServerGateUser* pUser);
VOID OnOpenUser(CCustomServerGateUser *pGateUser);
VOID OnCloseUser(CCustomServerGateUser *pGateUser);
VOID OnGateClosed();
VOID OnDispatchUserMsg(CCustomServerGateUser *pUser, char* pBuffer, SIZE_T nBufferSize);
VOID OnRun();
virtual VOID DispatchInternalMessage(UINT uMsg, UINT64 uParam1, UINT64 uParam2, UINT64 uParam3,UINT64 uParam4);
private:
//处理用户列表
VOID ProcessUsers();
VOID AddAllGateUsersToFreeList();
//通过全局会话ID查找网关用户如果找到用户且lpIndex非空则会想*lpIndex填充网关用户的索引
CDBGateUser* GetGateUserPtrBySessionId(const int nSessionId, PINT_PTR lpIndex = NULL);
//处理用户选择角色进入游戏的消息
int UserSelCharEntryGame(CDBGateUser *pGateUser, int nCharId,
char* sGateHost,SIZE_T nHostLen,PINT_PTR nGatePort);
//处理名称服务器返回申请角色名称的结果
BOOL NameServerAllocCharIdResult(const int nSessionId, const INT_PTR nError, const int nCharId);
//处理各个数据包
private:
//根据帐户ID查询出相关的角色列表,结果会添加到pPacket中
CDataPacket* QueryActorList(CDBGateUser *pGateUser, char* lpData, SIZE_T nSize);
//处理创建角色包
CDataPacket* CreateActor(CDBGateUser *pGateUser, char* lpData,SIZE_T nSize);
CDataPacket* DeleteActor(CDBGateUser *pGateUser, char* lpData,SIZE_T nSize);
CDataPacket* EntryGameReq(CDBGateUser *pGateUser, char* lpData,SIZE_T nSize);
//随机生成名字
CDataPacket* RandNameReq(CDBGateUser *pGateUser, char* lpData,SIZE_T nSize);
//查询最少人选择的职业
CDataPacket* QueryLessJobReq(CDBGateUser *pGateUser, char* lpData,SIZE_T nSize);
BYTE QueryLessJobReq( BYTE &bJob, int serverindex );
CDataPacket* QueryZYReq(CDBGateUser *pGateUser, char* lpData,SIZE_T nSize);
BYTE QueryZYReq( BYTE& bZY ,int serverindex);
INT_PTR QueryActorCount(INT_PTR nAccountId, INT_PTR nServerIndex);
WORD QueryZyList(INT_PTR nServerIndex);
// 当名字服务器返回创建角色结果时,执行本函数
// 1.数据库中插入新的角色信息 2.返回客户端结果
VOID ProcessNameSrvResult(CDBGateUser* pGateUser,int nCharId, INT_PTR nError);
void SendClientLogin(const unsigned int nSessionID,const unsigned int nActorId);
// 设置网关管理器
void SetGateManager(CDBGateManager* mgr){ m_pGateMgr = mgr; }
//inline void InitDBReqHandler() { m_reqHandler.Init(m_pSQLConnection, m_pGateMgr); }
//// 封装DB请求处理
///*
//* Comments: 获取指定账号ID的所有角色列表信息
//* Param const int nActorId: 玩家账号ID
//* Param const int nServerId: 角色所在的逻辑服务器ID
//* Param CDataPacket &: 输出数据包
//* @Return void:
//* @Remark: 输出内容包括错误码1Byte) + 角色数目1Byte + 角色信息列表。如果查询失败,只有错误码。
//*/
//void GetActorList(const int nActorId, const int nServerId, CDataPacket &packet);
//有可能玩家连接了2个连接或者连接没有关闭导致逻辑服发过来的时候发给了另外一个连接
//所以玩家登陆的时候根据账户id把以前的连接需要关闭避免发错连接也避免僵尸连接
VOID DeleteOldActor(CDBGateUser *pGateUser);
public:
typedef CCustomServerGate Inherited;
static const INT_PTR MAX_GATE_USER = 8192; //最大网关用户数
static const INT_PTR SSM_LOGIC_RESPONSE_SESSION_DATA =40001;
private:
CDBGateManager* m_pGateMgr; // 网关管理器
CDBGateUser m_GateUsers[MAX_GATE_USER]; //网关用户数组
CSQLConenction* m_pSQLConnection; //数据库连接对象
CDBServer* m_pDBServer; //所属数据引擎
CBaseList<CCustomServerGateUser*> m_FreeUserList; //空闲网关用户列表
PERFORMANCEINFO m_MaxTimeUserMsgPerformance;//处理用户单个消息最高的时间
CGateDBReqestHandler m_reqHandler; // GateDBReqHandler
};
#endif

View File

@@ -0,0 +1,496 @@

#include "StdAfx.h"
CDBGateManager::CDBGateManager(CDBServer *lpDBEngine)
:Inherited()
{
m_dwReconnectSQLTick = 0;
m_pDBServer = lpDBEngine;
m_bLoadZyJobData = false;
m_SQLConnection.SetMultiThread(TRUE);
m_nNextZyJobSaveTime = _getTickCount();
m_bZyDataDirty = false;
m_bJobDataDirty = false;
}
CDBGateManager::~CDBGateManager()
{
}
BOOL CDBGateManager::ConnectSQL()
{
if ( !m_SQLConnection.Connected() )
{
if ( _getTickCount() >= m_dwReconnectSQLTick )
{
m_pDBServer->SetupSQLConnection(&m_SQLConnection);
if ( m_SQLConnection.Connect() )
{
mysql_options(m_SQLConnection.GetMySql(), MYSQL_SET_CHARSET_NAME, "utf8");
//if (m_SQLConnection.Exec("charset utf8"))
//{
// OutputMsg( rmError, _T("设置utf8字符编码出错"));
//}
//else
//{
// m_SQLConnection.ResetQuery();
//}
OnDBConnected();
return TRUE;
}
//如果连接SQL失败则将在5秒后重试
m_dwReconnectSQLTick = _getTickCount() + 5 * 1000;
return FALSE;
}
}
return TRUE;
}
VOID CDBGateManager::AllocCharIdResult(const int nSessionId, const INT_PTR nResult, const int nCharId)
{
INT_PTR i;
for ( i=0; i<ArrayCount(m_Gates); ++i )
{
if ( m_Gates[i].NameServerAllocCharIdResult(nSessionId, nResult, nCharId) )
{
break;
}
}
}
VOID CDBGateManager::LogicResponseSessionData(const unsigned int nSessionId,unsigned int nActorId)
{
for ( INT_PTR i=0; i< ArrayCount(m_Gates); ++i )
{
m_Gates[i].OnLogicRsponseSessionData(nSessionId,nActorId);
}
}
VOID CDBGateManager::Initialize()
{
INT_PTR i;
for ( i=0; i<ArrayCount(m_Gates); ++i )
{
m_Gates[i].m_pSQLConnection = &m_SQLConnection;
m_Gates[i].m_pDBServer = m_pDBServer;
m_Gates[i].SetGateManager(this);
// 需保证在调用InitDBReqHandler之前 CDBGate对象已经设置好SQlConnection以及GateManager
//m_Gates[i].InitDBReqHandler();
//将网关添加到列表
m_GateList[i] = &m_Gates[i];
}
}
VOID CDBGateManager::Uninitialize()
{
INT_PTR i;
for ( i=0; i<ArrayCount(m_GateList); ++i )
{
//将网关从列表移除
m_GateList[i] = NULL;
}
}
VOID CDBGateManager::Stop()
{
OutputMsg(rmNormal, _T("Save Zy Data..."));
SaveZyData();
OutputMsg(rmNormal, _T("Save Job Data..."));
SaveJobData();
OutputMsg(rmNormal, _T("Stop GateManager..."));
Inherited::Stop();
OutputMsg(rmNormal, _T("Stop GateManager End..."));
}
VOID CDBGateManager::OnResultGateUserExists(int nSessionId, const BOOL boOnline)
{
m_pDBServer->PostQueryUserExistsBySessionIdResult(nSessionId, boOnline);
}
VOID CDBGateManager::DispatchInternalMessage(UINT uMsg, UINT64 uParam1, UINT64 uParam2, UINT64 uParam3,UINT64 uParam4)
{
switch (uMsg)
{
case GTIM_ALLOC_CHARID_RESULT://申请角色ID返回此消息由NSClient发送(Param1=会话ID,Param2=操作结果,Param3=角色ID仅在操作成功时有效)
AllocCharIdResult((int)uParam1, (int)uParam2, (int)uParam3);
break;
case LOGIC_RESPONSE_DB_SESSION_DATA:
LogicResponseSessionData((unsigned int)uParam1, (unsigned int)uParam2);
break;
default:
Inherited::DispatchInternalMessage(uMsg, uParam1, uParam2, uParam3,uParam4);
break;
}
}
VOID CDBGateManager::OnRun()
{
if ( Started() )
{
ConnectSQL();
TICKCOUNT curTime = _getTickCount();
if (m_nNextZyJobSaveTime <= curTime)
{
if (m_bLoadZyJobData && m_SQLConnection.Connected())
{
SaveZyData();
SaveJobData();
}
m_nNextZyJobSaveTime = curTime + 1000 * 300; // 300s 存一次盘
}
}
}
VOID CDBGateManager::OnDBConnected()
{
if (!m_bLoadZyJobData)
{
OutputMsg(rmNormal, _T("DBConnected, Load Zy and Job Data"));
LoadZyInitData();
LoadJobInitData();
m_bLoadZyJobData = true;
}
else
{
OutputMsg(rmNormal, _T("DBReConnected, Save Zy and Job Data"));
SaveZyData();
SaveJobData();
}
}
VOID CDBGateManager::LoadZyInitData()
{
m_zyLock.Lock();
int nError = m_SQLConnection.Query(szSQLSP_LoadZyDistributeData);
if (reSucc == nError)
{
MYSQL_ROW pRow = m_SQLConnection.CurrentRow();
int nCount = m_SQLConnection.GetRowCount();
INT_PTR nLastSrvIdx = -1; // Invalid srv idx
int nZy, nUserCount, nSrvIdx;
PlayerZYDistribute zyDist;
zyDist.m_nServerIdx = nLastSrvIdx;
while (pRow)
{
sscanf(pRow[0], "%d", &nZy);
sscanf(pRow[1], "%d", &nUserCount);
sscanf(pRow[2], "%d", &nSrvIdx);
if (nZy > zyNone && nZy < zyMax && nUserCount > 0) // 只保存nUserCount大于0的阵营
{
if (nLastSrvIdx != nSrvIdx)
{
if (zyDist.m_nServerIdx != -1)
m_vecZyDist.add(zyDist);
zyDist.Reset();
zyDist.m_nServerIdx = nSrvIdx;
nLastSrvIdx = nSrvIdx;
}
zyDist.m_anPlayerCount[nZy] = nUserCount;
}
pRow = m_SQLConnection.NextRow();
}
// add last server zy distribute info
if (zyDist.m_nServerIdx != -1)
m_vecZyDist.add(zyDist);
m_SQLConnection.ResetQuery();
m_bLoadZyJobData = true;
}
m_zyLock.Unlock();
}
VOID CDBGateManager::SaveZyData()
{
m_zyLock.Lock();
if (m_bLoadZyJobData && m_bZyDataDirty)
{
if (m_SQLConnection.Connected())
{
char szSql[1024];
for (INT_PTR i = 0; i < m_vecZyDist.count(); i++)
{
// clean first
PlayerZYDistribute& dist = m_vecZyDist[i];
sprintf(szSql, szSQLSP_CleanZyDistributeData, (int)dist.m_nServerIdx);
int nError = m_SQLConnection.RealExec(szSql, strlen(szSql));
if (nError == reSucc)
{
bool bFirstItem = true;
sprintf(szSql, "%s", szSQLSP_AddZyDistributeData);
for (INT_PTR j = zyNone+1; j < zyMax; j++)
{
char szTemp[128];
if (dist.m_anPlayerCount[j] > 0)
{
if (!bFirstItem)
{
strcat(szSql, ",");
}
if (bFirstItem)
bFirstItem = false;
sprintf(szTemp, "(%d,%d,%d)", (int)j, (int)dist.m_anPlayerCount[j], (int)dist.m_nServerIdx);
strcat(szSql, szTemp);
}
}
m_SQLConnection.ResetQuery();
nError = m_SQLConnection.RealExec(szSql, strlen(szSql));
if (nError != reSucc)
{
OutputMsg(rmError, _T("%s add zy count record failed(srvidx=%d"), __FUNCTION__, (int)dist.m_nServerIdx);
}
else
{
m_SQLConnection.ResetQuery();
}
}
}
m_bZyDataDirty = false;
}
}
m_zyLock.Unlock();
}
tagZhenying CDBGateManager::GetPriorityZY(int nSrvIdx)
{
m_zyLock.Lock();
tagZhenying priorZy = zyNone;
for (INT_PTR i = 0; i < m_vecZyDist.count(); i++)
{
PlayerZYDistribute& dist = m_vecZyDist[i];
if (nSrvIdx == dist.m_nServerIdx)
{
// find zy in which less user
INT_PTR nCount = 0x7FFFFFFF;
for (INT_PTR j = zyNone+1; j < zyMax; j++)
{
if (dist.m_anPlayerCount[j] < nCount /*&& dist.m_anPlayerCount[j] >= 0*/)
{
priorZy = (tagZhenying)j;
nCount = dist.m_anPlayerCount[j];
}
}
}
}
if (priorZy == zyNone)
priorZy = zyWuJi;
m_zyLock.Unlock();
return priorZy;
}
VOID CDBGateManager::LoadJobInitData()
{
m_jobLock.Lock();
int nError = m_SQLConnection.Query(szSQLSP_LoadJobDistributeData);
if (reSucc == nError)
{
MYSQL_ROW pRow = m_SQLConnection.CurrentRow();
int nCount = m_SQLConnection.GetRowCount();
INT_PTR nLastSrvIdx = -1; // Invalid srv idx
int nJob, nUserCount, nSrvIdx;
PlayerJobDistribute jobDist;
jobDist.m_nServerIdx = nLastSrvIdx;
while (pRow)
{
sscanf(pRow[0], "%d", &nJob);
sscanf(pRow[1], "%d", &nUserCount);
sscanf(pRow[2], "%d", &nSrvIdx);
if (nJob > enVocNone && nJob < enMaxVocCount && nUserCount > 0) // 只保存nUserCount大于0的职业
{
if (nLastSrvIdx != nSrvIdx)
{
if (jobDist.m_nServerIdx != -1)
m_vecJobDist.add(jobDist);
jobDist.Reset();
jobDist.m_nServerIdx = nSrvIdx;
nLastSrvIdx = nSrvIdx;
}
jobDist.m_anPlayerCount[nJob] = nUserCount;
}
pRow = m_SQLConnection.NextRow();
}
// add last server zy distribute info
if (jobDist.m_nServerIdx != -1)
m_vecJobDist.add(jobDist);
m_SQLConnection.ResetQuery();
m_bLoadZyJobData = true;
}
m_jobLock.Unlock();
}
VOID CDBGateManager::SaveJobData()
{
m_jobLock.Lock();
if (m_bLoadZyJobData && m_bJobDataDirty)
{
if (m_SQLConnection.Connected())
{
char szSql[1024];
for (INT_PTR i = 0; i < m_vecJobDist.count(); i++)
{
// clean first
PlayerJobDistribute& dist = m_vecJobDist[i];
sprintf(szSql, szSQLSP_CleanJobDistributeData, (int)dist.m_nServerIdx);
int nError = m_SQLConnection.RealExec(szSql, strlen(szSql));
if (nError == reSucc)
{
bool bFirstItem = true;
sprintf(szSql, "%s", szSQLSP_AddJobDistributeData);
for (INT_PTR j = enVocNone+1; j < enMaxVocCount; j++)
{
char szTemp[128];
if (dist.m_anPlayerCount[j] > 0)
{
if (!bFirstItem)
{
strcat(szSql, ",");
}
if (bFirstItem)
bFirstItem = false;
sprintf(szTemp, "(%d,%d,%d)", (int)j, (int)dist.m_anPlayerCount[j], (int)dist.m_nServerIdx);
strcat(szSql, szTemp);
}
}
m_SQLConnection.ResetQuery();
nError = m_SQLConnection.RealExec(szSql, strlen(szSql));
if (nError != reSucc)
{
OutputMsg(rmError, _T("%s add job count record failed(srvidx=%d"), __FUNCTION__, (int)dist.m_nServerIdx);
}
else
{
m_SQLConnection.ResetQuery();
}
}
}
m_bJobDataDirty = false;
}
}
m_jobLock.Unlock();
}
int CDBGateManager::GetPriorityJob(int nSrvIdx)
{
m_jobLock.Lock();
int priorJob = enVocNone;
for (INT_PTR i = 0; i < m_vecJobDist.count(); i++)
{
PlayerJobDistribute& dist = m_vecJobDist[i];
if (nSrvIdx == dist.m_nServerIdx)
{
// find jobs in which less user
INT_PTR nCount = 0x7FFFFFFF;
static INT_PTR sValidVoc[] = {1, 2, 3};
static const INT_PTR snValidVocCount = ArrayCount(sValidVoc);
//for (INT_PTR j = enVocNone+1; j < enMaxVocCount; j++)
for (INT_PTR j = 0; j < snValidVocCount; j++)
{
INT_PTR nVoc = sValidVoc[j];
if (dist.m_anPlayerCount[nVoc] < nCount/* && dist.m_anPlayerCount[j] >= 0*/)
{
priorJob = (tagActorVocation)nVoc;
nCount = dist.m_anPlayerCount[nVoc];
}
}
}
}
if (priorJob == enVocNone)
priorJob = 1;
m_jobLock.Unlock();
return (int)priorJob;
}
int CDBGateManager::GetOptionalZy(int nSrvIdx)
{
m_zyLock.Lock();
int nOptMask = 7; // all zy are optional
for (INT_PTR i = 0; i < m_vecZyDist.count(); i++)
{
PlayerZYDistribute& dist = m_vecZyDist[i];
if (nSrvIdx == dist.m_nServerIdx)
{
INT_PTR nTotalCount = 0;
for (INT_PTR i = zyNone+1; i < zyMax; i++)
nTotalCount += dist.m_anPlayerCount[i];
if (nTotalCount > 0)
{
float nRate;
for (INT_PTR j = zyNone+1; j < zyMax; j++)
{
nRate = (dist.m_anPlayerCount[j] / (float)nTotalCount);
if (nRate > 0.35)
{
nOptMask &= ~(1 << (j-1));
}
}
}
}
}
m_zyLock.Unlock();
return nOptMask;
}
void CDBGateManager::OnNewPlayerCreated(int nSrvIdx, tagZhenying zy, tagActorVocation voc)
{
//OutputMsg(rmNormal, _T("create new player, zy=%d, voc=%d"), (int)zy, (int)voc);
if (zy > zyNone && zy < zyMax)
{
m_zyLock.Lock();
INT_PTR i = 0;
for (; i < m_vecZyDist.count(); i++)
{
if (m_vecZyDist[i].m_nServerIdx == nSrvIdx)
{
m_vecZyDist[i].m_anPlayerCount[zy]++;
break;
}
}
// add new node
if (i == m_vecZyDist.count())
{
PlayerZYDistribute dist;
dist.m_nServerIdx = nSrvIdx;
dist.m_anPlayerCount[zy] = 1;
m_vecZyDist.add(dist);
}
m_bZyDataDirty = true;
m_zyLock.Unlock();
}
if (voc > enVocNone && zy < enMaxVocCount)
{
m_jobLock.Lock();
INT_PTR i = 0;
for (; i < m_vecJobDist.count(); i++)
{
if (m_vecJobDist[i].m_nServerIdx == nSrvIdx)
{
m_vecJobDist[i].m_anPlayerCount[voc]++;
break;
}
}
// add new node
if (i == m_vecJobDist.count())
{
PlayerJobDistribute dist;
dist.m_nServerIdx = nSrvIdx;
dist.m_anPlayerCount[voc] = 1;
m_vecJobDist.add(dist);
}
m_bJobDataDirty = true;
m_jobLock.Unlock();
}
}

View File

@@ -0,0 +1,103 @@
#ifndef _GATEMANAGER_H_
#define _GATEMANAGER_H_
class CDBServer;
class CDBGateManager
: public CCustomGateManager
{
public:
friend class CDBGate;
typedef CCustomGateManager Inherited;
public:
CDBGateManager(CDBServer *lpDBEngine);
~CDBGateManager();
//初始化
VOID Initialize();
//卸载
VOID Uninitialize();
/* 投递创建通过名称服务器申请角色名称的结果 */
inline VOID PostAllocCharIdResult(int nSessionId, jxInterSrvComm::NameServerProto::NAMESERVER_OPERROR eError, const int nCharId)
{
PostInternalMessage(GTIM_ALLOC_CHARID_RESULT, nSessionId, eError, nCharId);
}
/*
* Comments: 收到逻辑发来的玩家的登陆认证数据
* Param const unsigned int nSessionID: 账户的id
* Param unsigned int nActorID: 角色的ID
* @Return VOID:
*/
inline VOID PostLogicResponseSessionData(const unsigned int nSessionID,unsigned int nActorID)
{
PostInternalMessage(LOGIC_RESPONSE_DB_SESSION_DATA, nSessionID, nActorID,0);
}
/* 停止网关服务器 */
VOID Stop();
// 获取优选职业(当前最少的职业)
int GetPriorityJob(int nSrvIdx);
// 获取可以选择的阵营阵营人数低于35%的才能选择),返回按位的掩码
int GetOptionalZy(int nSrvIdx);
// 获取优选阵营(当前最少的阵营)
tagZhenying GetPriorityZY(int nSrvIdx);
inline CSQLConenction* GetSQLConnectionPtr() { return &m_SQLConnection; }
protected:
/* 返回异步查询网关中是否存在指定会话ID的用户的结果 */
VOID OnResultGateUserExists(int nSessionId, const BOOL boOnline);
//进行内部消息的处理分派
virtual VOID DispatchInternalMessage(UINT uMsg, UINT64 uParam1, UINT64 uParam2, UINT64 uParam3,UINT64 uParam4);
VOID OnRun();
private:
BOOL ConnectSQL();
/* 处理名称服务器返回申请角色ID的结果
* nError 错误代码0表示成功
* nCharId 当错误代码为0时有效表示名称服务器分配的角色ID
*/
VOID AllocCharIdResult(const int nSessionId, const INT_PTR nError, const int nCharId);
//逻辑收到玩家的验证的数据
VOID LogicResponseSessionData(const unsigned int nSessionId,unsigned int nActorId);
// DB连接成功初始化阵营和职业数据
VOID OnDBConnected();
// DB服务器启动的时候自动加载玩家阵营分布数据
VOID LoadZyInitData();
// 保存玩家阵营分布数据(定时保存)
VOID SaveZyData();
// 新玩家创号
void OnNewPlayerCreated(int nSrvIdx, tagZhenying zy, tagActorVocation voc);
// DB服务器启动的时候自动加载玩家职业分布数据
VOID LoadJobInitData();
// 保存玩家职业分布数据(定时保存)
VOID SaveJobData();
private:
CDBGate m_Gates[MaxGateCount]; //网关列表
CDBServer* m_pDBServer; //所属DBEngine
CSQLConenction m_SQLConnection; //网关数据库连接对象
TICKCOUNT m_dwReconnectSQLTick; //下次重新连接数据库的时间
// 用于创建角色选择阵营和职业
bool m_bLoadZyJobData;// 是否已经加载了初始的阵营、职业分布数据针对DB断开重连的情况
wylib::container::CBaseList<PlayerZYDistribute> m_vecZyDist; // 玩家阵营分布
wylib::container::CBaseList<PlayerJobDistribute> m_vecJobDist; // 玩家职业分布
bool m_bZyDataDirty;
bool m_bJobDataDirty;
CCSLock m_zyLock;
CCSLock m_jobLock;
TICKCOUNT m_nNextZyJobSaveTime;
private:
//申请角色ID返回此消息由NSClient发送(Param1=会话ID,Param2=操作结果,Param3=角色ID仅在操作成功时有效)
static const UINT_PTR GTIM_ALLOC_CHARID_RESULT = 10001;
static const UINT_PTR LOGIC_RESPONSE_DB_SESSION_DATA = 10002; //逻辑服务器返回收到了玩家的登陆的会话数据
};
#endif

View File

@@ -0,0 +1,38 @@
#ifndef _GATEUSER_H_
#define _GATEUSER_H_
/**
网关用户类
此类不可再继承
**/
class CDBGateUser
: public CCustomServerGateUser
{
public:
typedef CCustomServerGateUser Inherited;
public:
PCREATEACTORDATAREQ pCreateCharStruct; //创建角色的数据仅当启用名称服务器的时候有意义如果值为NULL则表示没有在创建角色
TICKCOUNT dwCreateCharTimeOut;//创建角色时通过名称服务器申请角色名称的超时时间
INT_PTR nNameLibIndex; //随机名字在名字库中的索引
char sRandomName[32]; //系统发给玩家的随机名字
WORD nZyList; //发给客户端的可选的阵营列表用位表示比如第一位是1表示阵营1可选如果是0表示都不可选由系统分配
char szIP[128]; //登陆的ip
int nPort; //登陆的端口
public:
CDBGateUser():Inherited()
{
nGlobalSessionId = 0;
sAccount[0] = 0;
nZyList = -1;
szIP[0]=0;
nPort=0;
}
};
#endif

View File

@@ -0,0 +1,384 @@

#include "StdAfx.h"
const CNameSyncClient::OnHandleSockPacket CNameSyncClient::NSSockPacketHandlers[] =
{
NULL,
};
CNameSyncClient::CNameSyncClient(CDBServer *lpDBEngine)
:Inherited()
{
m_pDBServer = lpDBEngine;
SetClientName(_T("名称"));
m_NewNameOperateList.setLock(&m_NewNameOperateListLock);
}
CNameSyncClient::~CNameSyncClient()
{
}
jxSrvDef::SERVERTYPE CNameSyncClient::getLocalServerType()
{
return DBServer;
}
LPCSTR CNameSyncClient::getLocalServerName()
{
return m_pDBServer->getServerName();
}
//VOID CNameSyncClient::SendRegisteClient()
//{
// SERVER_REGDATA regData;
//
// ZeroMemory( &regData, sizeof(regData) );
// regData.GameType = SERVER_REGDATA::GT_JianXiaoJiangHu;
// regData.ServerType = getLocalServerType();
// regData.ServerIndex = m_pDBServer->getServerIndex();
// _asncpytA( regData.ServerName, m_pDBServer->getServerName() );
//
// send(&regData, sizeof(regData));
//}
/*
VOID CNameSyncClient::SendKeepAlive()
{
flushProtoPacket(allocProtoPacket(jxInterSrvComm::NameServerProto::cKeepAlive));
}
*/
VOID CNameSyncClient::OnRun()
{
INT_PTR i;
NameOperateData *pNameOP;
TICKCOUNT dwCurTick = _getTickCount();
//如果有新的名称操作数据,则发送数据并追加到操作中列表
if ( m_NewNameOperateList.count() > 0 )
{
m_NewNameOperateList.lock();
//向名称服务器发送新增加的名称操作消息
SendNewNameOperateRequest();
//将新操作的数据添加到才做中的列表中
m_NameOperatingList.addList(m_NewNameOperateList);
m_NewNameOperateList.clear();
m_NewNameOperateList.unlock();
}
//检查每个正在操作的名称请求的状态
//必须降序循环,因为列表中的数据可能被删除
for ( i=m_NameOperatingList.count()-1; i>-1; --i )
{
pNameOP = m_NameOperatingList[i];
//检查超时
if ( dwCurTick >= pNameOP->dwTimeOut )
{
NameOperateTimedOut(pNameOP);
m_NameOperatingList.remove(i);
m_Allocator.FreeBuffer(pNameOP);
}
}
}
VOID CNameSyncClient::OnDispatchRecvPacket(const jxSrvDef::INTERSRVCMD nCmd, CDataPacketReader &inPacket)
{
int nId;
NAMESERVER_OPERROR eError;
LPCSTR sName;
INT_PTR nIndex;
int nServerIndex = 0;
NameOperateData *pNameOP;
inPacket >> nServerIndex;
inPacket >> sName;
switch(nCmd)
{
case jxInterSrvComm::NameServerProto::sAllocCharId://申请角色ID返回 TODO 创角不成功,很多情况是这个 NameServer 没有返回这个协议导致的
{
pNameOP = GetNameOperatePtr(NameOperateData::noAllocCharId, sName, &nIndex,nServerIndex);
if ( pNameOP )
{
inPacket >> eError;
inPacket >> nId;
//向网关管理器投递申请角色名称返回的消息
m_pDBServer->getDataServer()->PostCreateActorResult(
pNameOP->nServerIndex, eError, nId, (PCREATEACTORDATA)pNameOP->pData);
m_NameOperatingList.remove(nIndex);
m_Allocator.FreeBuffer(pNameOP);
}
}
break;
case jxInterSrvComm::NameServerProto::sCrossAllocCharId://申请角色ID返回 TODO 创角不成功,很多情况是这个 NameServer 没有返回这个协议导致的
{
pNameOP = GetNameOperatePtr(NameOperateData::noCSAllocCharId, sName, &nIndex,nServerIndex);
if ( pNameOP )
{
inPacket >> eError;
inPacket >> nId;
//向网关管理器投递申请角色名称返回的消息
m_pDBServer->getDataServer()->PostCreateCrossServerActorResult(
pNameOP->nServerIndex, eError, nId, (PCREATEACTORDATA)pNameOP->pData);
m_NameOperatingList.remove(nIndex);
m_Allocator.FreeBuffer(pNameOP);
}
}
break;
case jxInterSrvComm::NameServerProto::sAllocGuildId://申请帮会ID返回
{
pNameOP = GetNameOperatePtr(NameOperateData::noAllocGuildId, sName, &nIndex,nServerIndex);
if ( pNameOP )
{
inPacket >> eError;
inPacket >> nId;
//使用一个包含2个INT的数组[0]保存操作结果,[1]保存帮会ID
PINT_PTR pResult = (PINT_PTR)malloc(sizeof(*pResult) * 2);
pResult[0] = eError;
pResult[1] = nId;
//向数据服务器投递申请帮会ID返回的消息
m_pDBServer->getDataServer()->PostAllocGuildNameResult(
pNameOP->nServerIndex, pResult, pNameOP->allocGuildId.nOPIdent);
m_NameOperatingList.remove(nIndex);
m_Allocator.FreeBuffer(pNameOP);
}
}
break;
case jxInterSrvComm::NameServerProto::sRenameChar://重命名角色返回
{
pNameOP = GetNameOperatePtr(NameOperateData::noRenameChar, sName, &nIndex);
if ( pNameOP )
{
inPacket >> eError;
//向数据服务器投递角色重命名返回的消息
m_pDBServer->getDataServer()->PostRenameCharResult(pNameOP->nServerIndex,
eError, pNameOP->renameChar.nOPIdent);
m_NameOperatingList.remove(nIndex);
m_Allocator.FreeBuffer(pNameOP);
}
}
break;
case jxInterSrvComm::NameServerProto::sRenameGuild://重命名帮会返回
{
pNameOP = GetNameOperatePtr(NameOperateData::noRenameGuild, sName, &nIndex);
if ( pNameOP )
{
m_NameOperatingList.remove(nIndex);
m_Allocator.FreeBuffer(pNameOP);
}
}
break;
}
}
VOID CNameSyncClient::SendNewNameOperateRequest()
{
INT_PTR i, nCount;
NameOperateData *pNameOP;
nCount = m_NewNameOperateList.count();
for ( i=0; i<nCount; ++i )
{
pNameOP = m_NewNameOperateList[i];
//构造通信数据包
switch(pNameOP->nOPType)
{
case NameOperateData::noAllocCharId://申请角色ID
{
CDataPacket &packet = allocProtoPacket(jxInterSrvComm::NameServerProto::cAllocCharId);
packet << (int)pNameOP->nServerIndex;
packet << pNameOP->sName;
flushProtoPacket(packet);
}
break;
case NameOperateData::noCSAllocCharId://申请跨服角色ID
{
CDataPacket &packet = allocProtoPacket(jxInterSrvComm::NameServerProto::cCrossAllocCharId);
packet << (int)pNameOP->nServerIndex;
packet << pNameOP->sName;
flushProtoPacket(packet);
}
break;
case NameOperateData::noAllocGuildId://申请帮会ID
{
CDataPacket &packet = allocProtoPacket(jxInterSrvComm::NameServerProto::cAllocGuildId);
packet << (int)pNameOP->nServerIndex;
packet << pNameOP->sName;
flushProtoPacket(packet);
}
break;
case NameOperateData::noRenameChar://重命名角色
{
CDataPacket &packet = allocProtoPacket(jxInterSrvComm::NameServerProto::cRenameChar);
packet << pNameOP->renameChar.nCharId;
packet << pNameOP->sName;
flushProtoPacket(packet);
}
break;
case NameOperateData::noRenameGuild://重命名帮会
{
CDataPacket &packet = allocProtoPacket(jxInterSrvComm::NameServerProto::cRenameGuild);
packet << pNameOP->guildRename.nGuildId;
packet << pNameOP->sName;
flushProtoPacket(packet);
}
break;
default:
break;
}
}
}
CNameSyncClient::NameOperateData* CNameSyncClient::GetNameOperatePtr(
const NameOperateData::eNameOperateType eOPType, LPCSTR sName, OUT PINT_PTR lpIndex,int nServerIndex)
{
INT_PTR i;
NameOperateData *pNameOP;
//检查每个正在操作的名称请求的状态
//必须降序循环,因为列表中的数据可能被删除
for ( i=m_NameOperatingList.count()-1; i>-1; --i )
{
pNameOP = m_NameOperatingList[i];
if ( pNameOP->nOPType == eOPType && !_stricmp(sName, pNameOP->sName) &&
(nServerIndex == -1 || nServerIndex == pNameOP->nServerIndex))
{
if ( lpIndex ) *lpIndex = i;
return pNameOP;
}
}
return NULL;
}
VOID CNameSyncClient::NameOperateTimedOut(const NameOperateData* pNameOP)
{
//构造通信数据包
switch(pNameOP->nOPType)
{
case NameOperateData::noAllocCharId://申请角色ID
{
//向网关管理器投递申请角色名称返回超时的结果
/////m_pDBServer->getGateManager()->PostAllocCharIdResult(pNameOP->allocCharId.nSesionId, neTimedOut, 0);
}
break;
case NameOperateData::noAllocGuildId://申请帮会ID
{
//向数据服务器投递申请帮会ID色超时的结果
//使用一个包含2个INT_PTR的数组[0]保存操作结果,[1]保存帮会ID
PINT_PTR pResult = (PINT_PTR)malloc(sizeof(*pResult) * 2);
pResult[0] = aeTimedOut;
pResult[1] = 0;
m_pDBServer->getDataServer()->PostAllocGuildNameResult(pNameOP->nServerIndex,
pResult, pNameOP->allocGuildId.nOPIdent);
}
break;
case NameOperateData::noRenameChar://重命名角色
{
//向数据服务器投递重命名角色超时的结果
m_pDBServer->getDataServer()->PostRenameCharResult(pNameOP->nServerIndex,
neTimedOut, pNameOP->renameChar.nOPIdent);
}
break;
case NameOperateData::noRenameGuild://重命名帮会
break;
}
}
BOOL CNameSyncClient::PostAllocateCharId(const int nSessionId, const int nServerIndex, LPCSTR sCharName,CREATEACTORDATA *pData)
{
if ( !connected() )
{
OutputMsg(rmError,"PostAllocateCharId fail, name server not connect");
return FALSE;
}
//构造名称操作数据
NameOperateData *pNameOP = (NameOperateData*)m_Allocator.AllocBuffer(sizeof(*pNameOP));
pNameOP->nOPType = NameOperateData::noAllocCharId;
pNameOP->nServerIndex = nServerIndex;
_asncpytA(pNameOP->sName, sCharName);
pNameOP->dwTimeOut = _getTickCount() + 10 * 1000;
pNameOP->allocCharId.nSesionId = nSessionId;
pNameOP->pData = (void *)pData;
//添加新的名称操作消息
m_NewNameOperateList.lock();
m_NewNameOperateList.add(pNameOP);
m_NewNameOperateList.unlock();
TRACE("%d,%d,%s",nSessionId,nServerIndex,sCharName);
return TRUE;
}
BOOL CNameSyncClient::PostCrossServerAllocateCharId(const int nSessionId, const int nServerIndex, LPCSTR sCharName,CREATEACTORDATA *pData)
{
if ( !connected() )
{
OutputMsg(rmError,"PostCrossServerAllocateCharId fail, name server not connect");
return FALSE;
}
//构造名称操作数据
NameOperateData *pNameOP = (NameOperateData*)m_Allocator.AllocBuffer(sizeof(*pNameOP));
pNameOP->nOPType = NameOperateData::noCSAllocCharId;
pNameOP->nServerIndex = nServerIndex;
_asncpytA(pNameOP->sName, sCharName);
pNameOP->dwTimeOut = _getTickCount() + 10 * 1000;
pNameOP->allocCharId.nSesionId = nSessionId;
pNameOP->pData = (void *)pData;
//添加新的名称操作消息
m_NewNameOperateList.lock();
m_NewNameOperateList.add(pNameOP);
m_NewNameOperateList.unlock();
TRACE("%d,%d,%s",nSessionId,nServerIndex,sCharName);
return TRUE;
}
BOOL CNameSyncClient::PostAllocateGuildId(const int nServerIndex, LPCSTR sGuildName, const UINT_PTR nOPIdent)
{
if ( !connected() )
return FALSE;
//构造名称操作数据
NameOperateData *pNameOP = (NameOperateData*)m_Allocator.AllocBuffer(sizeof(*pNameOP));
pNameOP->nOPType = NameOperateData::noAllocGuildId;
pNameOP->nServerIndex = nServerIndex;
_asncpytA(pNameOP->sName, sGuildName);
pNameOP->dwTimeOut = _getTickCount() + 10 * 1000;
pNameOP->allocGuildId.nOPIdent = nOPIdent;
//添加新的名称操作消息
m_NewNameOperateList.lock();
m_NewNameOperateList.add(pNameOP);
m_NewNameOperateList.unlock();
return TRUE;
}
BOOL CNameSyncClient::PostCharRename(const int nCharId, const int nServerIndex, LPCSTR sNewCharName, const UINT_PTR nOPIdent)
{
if ( !connected() )
return FALSE;
//构造名称操作数据
NameOperateData *pNameOP = (NameOperateData*)m_Allocator.AllocBuffer(sizeof(*pNameOP));
pNameOP->nOPType = NameOperateData::noRenameChar;
pNameOP->nServerIndex = nServerIndex;
_asncpytA(pNameOP->sName, sNewCharName);
pNameOP->dwTimeOut = _getTickCount() + 10 * 1000;
pNameOP->renameChar.nCharId = nCharId;
pNameOP->renameChar.nOPIdent = nOPIdent;
//添加新的名称操作消息
m_NewNameOperateList.lock();
m_NewNameOperateList.add(pNameOP);
m_NewNameOperateList.unlock();
return TRUE;
}

View File

@@ -0,0 +1,117 @@
#ifndef _DB_NAME_SYNC_CLIENT_H_
#define _DB_NAME_SYNC_CLIENT_H_
class CDBServer;
class CNameSyncClient :
public CCustomJXClientSocket
{
public:
typedef CCustomJXClientSocket Inherited;
typedef VOID (CNameSyncClient::*OnHandleSockPacket)(CDataPacketReader &packet);
public:
CNameSyncClient(CDBServer *lpDBEngine);
~CNameSyncClient();
//投递申请角色ID的内部消息申请角色ID成功或失败后会处理超时会向网关线程投递?消息
BOOL PostAllocateCharId(const int nSessionId, const int nServerIndex, LPCSTR sCharName,CREATEACTORDATA *pData);
//投递申请跨服角色ID的内部消息申请角色ID成功或失败后会处理超时会向网关线程投递?消息
BOOL PostCrossServerAllocateCharId(const int nSessionId, const int nServerIndex, LPCSTR sCharName,CREATEACTORDATA *pData);
//投递申请帮会ID的内部消息申请帮会ID成功或失败后会处理超时会向数据服务器线程投递?消息
//参数nOPIdent是调用者生成的具有唯一性的操作标识数据当操作具有结果成功、失败或超时
//向数据服务器投递的对应消息中将此值原样返回
BOOL PostAllocateGuildId(const int nServerIndex, LPCSTR sGuildName, const UINT_PTR nOPIdent);
//投递更改角色名称的内部消息,操作成功或失败后(会处理超时),会向数据服务器线程投递?消息
//参数nOPIdent是调用者生成的具有唯一性的操作标识数据当改名操作具有结果成功、失败或超时
//向数据服务器投递的对应消息中将此值原样返回
BOOL PostCharRename(const int nCharId, const int nServerIndex, LPCSTR sNewCharName, const UINT_PTR nOPIdent);
protected:
//覆盖发送注册客户端的消息
// VOID SendRegisteClient();
//覆盖发送保持连接消息的函数
//VOID SendKeepAlive();
//覆盖例行执行的函数,以便处理名称操作数据
VOID OnRun();
/* ★查询本地服务器的类型,以便正确的向会话服务器注册连接 */
jxSrvDef::SERVERTYPE getLocalServerType();
/*** 子类需覆盖的函数集 ***/
/* 处理单个通信数据包
* nCmd 通信消息命令
* inPacket 已经读取出通信命令的数据包,数据包的读取位置指向命令数据后的内容
*/
virtual VOID OnDispatchRecvPacket(const jxSrvDef::INTERSRVCMD nCmd, CDataPacketReader &inPacket);
/* ★查询本地服务器的名称,以便正确的发送注册数据 */
virtual LPCSTR getLocalServerName();
private:
//向名称服务器发送新增加的名称操作数据
VOID SendNewNameOperateRequest();
VOID DefaultSockPacketHandler(CDataPacketReader &inPacket);
VOID AllocCharIdResultHandler(CDataPacketReader &inPacket);
VOID AllocGuildIdResultHandler(CDataPacketReader &inPacket);
VOID RenameCharResultHandler(CDataPacketReader &inPacket);
VOID RenameGuildResultHandler(CDataPacketReader &inPacket);
private:
//定义名称客户端与名称和ID操作相关的数据结构
struct NameOperateData
{
enum eNameOperateType
{
noAllocCharId = 1, //申请角色ID客户端创建角色的时候用
noAllocGuildId, //申请帮会ID引擎服务器创建帮会的时候用
noRenameChar, //角色重命名(引擎服务器修改角色名称的时候用)
noRenameGuild, //帮会冲命名(引擎服务器修改帮会名称的时候用)
noCSAllocCharId, //申请跨服角色ID
} nOPType; //名称操作的类型
int nServerIndex; //服务器ID
char sName[128]; //名称字符串
TICKCOUNT dwTimeOut; //超时时间
union
{
//申请角色ID的数据
struct
{
int nSesionId; //全局会话ID
} allocCharId;
//申请帮会ID的数据
struct
{
UINT_PTR nOPIdent; //操作唯一标识(由数据客户端处理类内部产生,在操作具有结果原样返回)
} allocGuildId;
//申请修改帮会名称的数据
struct
{
unsigned int nGuildId; //帮会ID
UINT_PTR nOPIdent; //操作唯一标识(由数据客户端处理类内部产生,在操作具有结果原样返回)
} guildRename;
//申请修改角色名称的数据
struct
{
int nCharId; //角色ID
UINT_PTR nOPIdent; //操作唯一标识(由数据客户端处理类内部产生,在操作具有结果原样返回)
} renameChar;
};
void * pData; //缓存的数据指针
};
//查找名称操作指针如果找到对应的数据则返回数据指针如果lpIndex非空则填充*lpIndex为数据在操作中列表中的索引
//如果serverindex为-1则不限定查找条件
NameOperateData* GetNameOperatePtr(const NameOperateData::eNameOperateType eOPType, LPCSTR sName, OUT PINT_PTR lpIndex,int nServerIndex=-1);
//名称操作请求超时
VOID NameOperateTimedOut(const NameOperateData* lpOperate);
private:
CDBServer* m_pDBServer; //所属DB引擎
CBaseList<NameOperateData*> m_NameOperatingList; //正在操作的名称数据列表
CLockList<NameOperateData*> m_NewNameOperateList; //新增加的名称数据处理列表
CCSLock m_NewNameOperateListLock;//增加名称处理数据的列表锁
static const OnHandleSockPacket NSSockPacketHandlers[]; //结构化网络数据包处理函数列表
};
#endif

View File

@@ -0,0 +1,742 @@
#include "StdAfx.h"
#include "wrand.h"
CDBServer* CDBServer::s_pDBEngine = NULL;
CDBServer::CDBServer()
{
m_nServerIndex = 0;
m_sServerName[0] = 0;
m_sNameSyncServerHost[0] = 0;
m_boFirstCharEnableSelCountry = FALSE;
// SetSQLConfig("localhost", 3306, "gamedb", "root", "123456");
m_GameServerRouteList.setLock(&m_GameServerRouteListLock);
/*
m_pGateManager = new CDBGateManager(this);
m_pGateManager->Initialize();
m_pSSClient = new CDBSessionClient(this);
*/
//m_pFilterWords = NULL;
// m_pLogClient->SetLocalServerType(DBServer);
m_pNameSyncClient = new CNameSyncClient(this);
m_pDataServer = new CDBDataServer(this);
//m_pLogClient = new LogSender();
//m_pLogClient->SetServerType(jxSrvDef::DBServer);
//m_pDBCenterClient = new CDBCenterClient(this);
m_pListPrefix = new CLoadString;
//m_pListConnect = new CLoadString;
m_pListStuffix = new CLoadString;
m_bStartDbServer = FALSE;
m_boUtf8 = false;
}
CDBServer::~CDBServer()
{
OutputMsg(rmNormal, _T("Start Save Name File"));
OutputMsg(rmNormal, _T("Save Name File End"));
OutputMsg(rmNormal, _T("Start ShutDown DBServer"));
Shutdown();
OutputMsg(rmNormal, _T("ShutDown DBServer End"));
//m_pGateManager->Uninitialize();
OutputMsg(rmNormal, _T("End GateUnitialize...."));
//SafeDelete(m_pGateManager);
//OutputMsg(rmNormal, _T("Wait Del SessionClient...."));
//SafeDelete(m_pSSClient);
//OutputMsg(rmNormal, _T("Wait Del LogClient...."));
//SafeDelete(m_pLogClient);
//OutputMsg(rmNormal, _T("Wait Del DBCenterClient...."));
//SafeDelete(m_pDBCenterClient);
OutputMsg(rmNormal, _T("Wait Del NameSynClient...."));
SafeDelete(m_pNameSyncClient);
OutputMsg(rmNormal, _T("Wait Del DataServer...."));
SafeDelete(m_pDataServer);
OutputMsg(rmNormal, _T("Wait Del Name Group..."));
SafeDelete(m_pListPrefix);
//SafeDelete(m_pListConnect);
SafeDelete(m_pListStuffix);
OutputMsg(rmNormal, _T("End...."));
}
void CDBServer::Trace()
{
/*
if(m_pDBCenterClient)
{
m_pDBCenterClient->Trace();
}
*/
if(m_pDataServer)
{
m_pDataServer->Trace();
}
}
VOID CDBServer::FreeGameServerRoute()
{
INT_PTR i;
for ( i=m_GameServerRouteList.count()-1; i>-1; --i )
{
delete m_GameServerRouteList[i];
}
m_GameServerRouteList.clear();
}
VOID CDBServer::SetupSQLConnection(CSQLConenction *lpConnection)
{
lpConnection->SetServerHost(m_sSQLHost);
lpConnection->SetServerPort(m_nSQLPort);
lpConnection->SetDataBaseName(m_sSQLDBName);
lpConnection->SetUserName(m_sSQLUser);
lpConnection->SetPassWord(m_sSQLPassword);
lpConnection->SetConnectionFlags(CLIENT_FOUND_ROWS | CLIENT_MULTI_RESULTS);
}
//修改了字符串越界的问题
/*
utf-8编码规则如果是1个字节是
1个字节0xxxxxxx
2个字节110xxxxx 10xxxxxx
3个字节1110xxxx 10xxxxxx 10xxxxxx
4个字节11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
5个字节111110xx 10xxxxxx 10xxxxxx 10xxxxxx
*/
LPCSTR CDBServer::LowerCaseNameStr(LPSTR sNameStr,INT_PTR nSize)
{
LPCSTR sResult = sNameStr;
INT_PTR count=0;
while ( *sNameStr && count < nSize)
{
/*
if ( (unsigned int)*sNameStr >= 0x7F )
{
sNameStr+=3;
continue;
}
*/
//如果是多个字节的
if( (*sNameStr & 0x80))
{
}
else
{
if ( *sNameStr >= 'A' && *sNameStr <= 'Z' )
{
*sNameStr |= 0x20;
}
}
sNameStr++;
count ++;
}
return sResult;
}
PGAMESERVERROUTE getServerRoute(CBaseList<PGAMESERVERROUTE> &list, const int nServerIndex)
{
INT_PTR i;
for ( i=list.count()-1; i>-1; --i )
{
if (list[i]->nServerIndex == nServerIndex )
{
return list[i];
}
}
return NULL;
}
INT CDBServer::LoadGameServerRoute()
{
int Result = 0;
int nValue =0;
MYSQL_ROW pRow;
PGAMESERVERROUTE pRoute;
CBaseList<PGAMESERVERROUTE> RouteList;
CSQLConenction sql;
//配置数据库连接
SetupSQLConnection(&sql);
//连接数据库
if ( !sql.Connect() )
{
return -1;
}
//从数据库角色网关路由表
if ( !sql.Query(szSQLSP_LoadGameSrvRouteTable) )
{
//读取角色网关路由表
// +-------------+---------------+------------+---------------+
// | serverindex | serveraddress | serverport | selgateaddr |
// +-------------+---------------+------------+---------------+
pRow = sql.CurrentRow();
while ( pRow )
{
if(pRow[0])
{
sscanf(pRow[0], "%d", &nValue);
}
else
{
OutputMsg(rmWaning,_T("%s serverindex is NULL"),pRow[0]);
}
pRoute = getServerRoute(RouteList, nValue);
if ( !pRoute )
{
pRoute = new GAMESERVERROUTE;
ZeroMemory(pRoute, sizeof(*pRoute));
pRoute->nServerIndex = nValue;
RouteList.add(pRoute);
}
if ( pRoute->nRouteCount < ArrayCount(pRoute->RouteTable) )
{
_asncpytA(pRoute->RouteTable[pRoute->nRouteCount].sHost, pRow[1]);
sscanf(pRow[2], "%d", &nValue);
pRoute->RouteTable[pRoute->nRouteCount].nPort = nValue;
pRoute->nRouteCount++;
TRACE(_T("路由:%d %s:%d\n"), pRoute->nServerIndex, pRow[1], nValue);
Result++;
}
pRow = sql.NextRow();
}
//将从数据库中加载的游戏网关路由表保存到类数据中
m_GameServerRouteList.lock();
FreeGameServerRoute();
m_GameServerRouteList.addList(RouteList);
m_GameServerRouteList.unlock();
sql.ResetQuery();
}
//断开与数据的连接
sql.Disconnect();
return Result;
}
INT_PTR CDBServer::SelecteGameGateRouteIndex(jxSrvDef::PGAMESERVERROUTE pRoute)
{
int nMinCount = 1000000;
INT_PTR nMinCountIdx = 0;
if (pRoute->nRouteCount <= 0)
return 0;
for (INT_PTR i = 0; i < pRoute->nRouteCount; i++)
{
if (pRoute->RouteTable[i].nUserCount < nMinCount)
{
nMinCount = pRoute->RouteTable[i].nUserCount;
nMinCountIdx = i;
}
}
pRoute->RouteTable[nMinCountIdx].nUserCount++;
return nMinCountIdx;
}
void CDBServer::TraceGameServerRoute()
{
m_GameServerRouteList.lock();
PGAMESERVERROUTE pRoute;
for (INT_PTR i = 0; i < m_GameServerRouteList.count(); i++)
{
pRoute = m_GameServerRouteList[i];
for (INT_PTR j = 0; j < pRoute->nRouteCount; j++)
{
OutputMsg(rmTip, _T("路由[%s:%6d] 用户人数:%d"),
pRoute->RouteTable[j].sHost,
pRoute->RouteTable[j].nPort,
pRoute->RouteTable[j].nUserCount);
}
}
m_GameServerRouteList.unlock();
}
void CDBServer::UpdateLogicGateUserInfo(CDataPacketReader& packet)
{
DECLARE_FUN_TIME_PROF()
int nServerIdx = 0;
WORD nCount = 0;
packet >> nServerIdx >> nCount;
PGAMESERVERROUTE pRoute;
GATEUSERINFO gi;
if (nCount > 0)
{
m_GameServerRouteList.lock();
// 找到对应服务器的路由配置
bool bValidServerRoute = false;
for (INT_PTR routeIdx = m_GameServerRouteList.count()-1; routeIdx > -1; --routeIdx)
{
pRoute = m_GameServerRouteList[routeIdx];
if (pRoute->nServerIndex == nServerIdx)
{
bValidServerRoute = true;
break;
}
}
if (!bValidServerRoute)
{
OutputMsg(rmError, _T("找不到对应服务器[server_index=%d]的路由配置信息"), nServerIdx);
}
else
{
INT_PTR nCurRouteCount = pRoute->nRouteCount;
for (INT_PTR i = 0; i < nCount; i++)
{
packet >> gi;
for (INT_PTR ri = 0; ri < nCurRouteCount; ri++)
{
if (pRoute->RouteTable[ri].nPort == gi.nGatePort)
{
pRoute->RouteTable[ri].nUserCount = gi.nUserCount;
OutputMsg(rmTip, _T("更新逻辑网关[port:%d]用户数目: %d"), (int)gi.nGatePort, gi.nUserCount);
}
}
}
}
m_GameServerRouteList.unlock();
}
}
BOOL CDBServer::SelectGameServerRoute(const int nServerIndex, LPSTR lpGateHost, const SIZE_T dwHostLen, PINT_PTR lpGatePort)
{
INT_PTR i;
PGAMESERVERROUTE pRoute;
BOOL boResult = FALSE;
m_GameServerRouteList.lock();
for ( i=m_GameServerRouteList.count()-1; i>-1; --i )
{
pRoute = m_GameServerRouteList[i];
if ( pRoute->nServerIndex == nServerIndex )
{
//随机挑选一个路由地址
//int nIndex = (_getTickCount() / 1000) % pRoute->nRouteCount;
int nIndex = (int)SelecteGameGateRouteIndex(pRoute);
strncpy(lpGateHost, pRoute->RouteTable[nIndex].sHost, dwHostLen-1);
lpGateHost[dwHostLen-1] = 0;
*lpGatePort = pRoute->RouteTable[nIndex].nPort;
boResult = TRUE;
break;
}
}
m_GameServerRouteList.unlock();
return boResult;
}
VOID CDBServer::SetServerName(LPCSTR sSrvName)
{
_asncpytA(m_sServerName, sSrvName);
//m_pLogClient->SetServerName((char*)(sSrvName));
}
VOID CDBServer::SetGateServiceAddress(LPCTSTR sHost, const INT_PTR nBindPort)
{
//m_pGateManager->SetServiceHost(sHost);
//m_pGateManager->SetServicePort(nBindPort);
}
VOID CDBServer::SetSessionServerAddress(LPCTSTR sHost, const INT_PTR nPort)
{
//m_pSSClient->SetServerHost(sHost);
//m_pSSClient->SetServerPort(nPort);
}
VOID CDBServer::SetLogServerAddress(LPCTSTR sHost, const INT_PTR nPort)
{
//m_pLogClient->SetServerHost(sHost);
//m_pLogClient->SetServerPort(nPort);
}
VOID CDBServer::SetDBCenterAddress(LPCTSTR sHost, const INT_PTR nPort)
{
/*
m_pDBCenterClient->SetServerHost(sHost);
m_pDBCenterClient->SetServerPort(nPort);
*/
}
VOID CDBServer::SetSQLConfig(LPCSTR sHost, const INT_PTR nPort, LPCSTR sDBName, LPCSTR sDBUser, LPCSTR sUserPassword, bool boUtf8)
{
_asncpytA(m_sSQLHost, sHost);
m_nSQLPort = nPort;
_asncpytA(m_sSQLDBName, sDBName);
_asncpytA(m_sSQLUser, sDBUser);
_asncpytA(m_sSQLPassword, sUserPassword);
m_boUtf8 = boUtf8;
}
VOID CDBServer::SetSelectCountryEnabledOnCreateFirstChar(const BOOL boEnabled)
{
m_boFirstCharEnableSelCountry = boEnabled;
}
VOID CDBServer::SetNameSyncServerAddress(LPCTSTR sHost, const INT_PTR nPort)
{
_asncpyt(m_sNameSyncServerHost, sHost);
m_nNameSyncServerPort = nPort;
m_pNameSyncClient->SetServerHost(sHost);
m_pNameSyncClient->SetServerPort(nPort);
}
VOID CDBServer::SetDataServiceAddress(LPCTSTR sBindHost, const INT_PTR nBindPort)
{
m_pDataServer->SetServiceHost(sBindHost);
m_pDataServer->SetServicePort(nBindPort);
}
VOID CDBServer::SetServerIndex(INT nServerIndex)
{
m_nServerIndex = nServerIndex;
//m_pLogClient->SetServerIndex(nServerIndex);
}
BOOL CDBServer::Startup()
{
m_bStartDbServer = true;
CTimeProfMgr::getSingleton();
//初始化网络套接字
/*
nError = m_pSSClient->InitSocketLib();
if ( nError )
{
OutputError( nError, _T(__FUNCTION__)_T("初始化网络库失败") );
return FALSE;
}
*/
//加载角色网关路由表
//LoadGameServerRoute();
LoadFilterNames();
CheckNameFilter();
// 启动日志客户端
/*
if ( !m_pLogClient->Startup() )
return FALSE;
//启动会话客户端
if ( !m_pSSClient->Startup() )
return FALSE;
*/
//启动名称客户端
if ( !m_pNameSyncClient->Startup() )
return FALSE;
//启动数据服务器
if ( !m_pDataServer->Startup() )
return FALSE;
//启动网关管理器
//m_pGateManager->Startup();
// 启动DBCenter客户端需要在GateMgr和DataServer初始化之后
/*
if (m_pDBCenterClient->GetServerPort() != 0 && !m_pDBCenterClient->Startup())
{
OutputMsg(rmError, _T("启动连向DBCenter的客户端失败"));
return FALSE;
}
*/
//m_pDBCenterClient->Init();
return TRUE;
}
VOID CDBServer::Shutdown()
{
//停止网关
//OutputMsg(rmNormal, _T("Prepare to Stop Gate Manager"));
//m_pGateManager->Stop();
//停止会话客户端
//OutputMsg(rmNormal, _T("Prepare to Stop SessionClient"));
///m_pSSClient->Stop();
//停止数据服务器
OutputMsg(rmNormal, _T("Prepare to Stop DataServer"));
m_pDataServer->Stop();
//停止名称客户端(必须在数据服务器停止后进行)
OutputMsg(rmNormal, _T("Prepare to Stop NameSyncClient"));
m_pNameSyncClient->Stop();
//停止日志客户端(必须在数据服务器停止后进行)
OutputMsg(rmNormal, _T("Prepare to Stop LogClient"));
//m_pLogClient->Stop();
// 停止DBCenterClient
//m_pDBCenterClient->Stop();
//释放角色网关路由表
FreeGameServerRoute();
//销毁屏蔽词
/*
if ( m_pFilterWords )
{
FreeMBCSFilter(m_pFilterWords);
m_pFilterWords = NULL;
}
*/
m_filter.Destroy();
CTimeProfMgr::getSingleton().clear();
//卸载网络库
//m_pSSClient->UnintSocketLib();
}
BOOL CDBServer::getGameReady(int nSrvIdx)
{
return m_pDataServer->getGameReady(nSrvIdx);
}
void CDBServer::AddFilterName(char* sName)
{
m_filter.AddFilterWord(sName);
}
BOOL CDBServer::LoadFilterNames()
{
CSQLConenction sql;
//配置数据库连接
SetupSQLConnection(&sql);
if ( !sql.Connected() )
{
if (sql.Connect())
{
//mysql_options(sql.GetMySql(), MYSQL_SET_CHARSET_NAME, "utf8");
if (mysql_set_character_set(sql.GetMySql(),"utf8"))
{
OutputMsg( rmError, _T("设置utf8编码出错 !!!") );
}
}else
{
OutputMsg(rmError, _T("can not load filter names"));
return FALSE;
}
}
//从数据库加载屏蔽文字列表 NSSQL_LoadFilterNames
if ( sql.Query(NSSQL_LoadFilterNames) )
{
OutputMsg(rmError, _T("can not load filter names, database call error"));
return FALSE;
}
//创建屏蔽词匹配工具
//m_pFilterWords = CreateMBCSFilter(NULL);
if(m_filter.Init() ==false)
{
OutputMsg(rmError,"m_filter.Init() fail");
return FALSE;
}
int nCount = 0;
MYSQL_ROW pRow = sql.CurrentRow();
while ( pRow )
{
if ( pRow[0] && pRow[0][0] )
{
//AddMBCSFilterStrToTable(m_pFilterWords, pRow[0]);
m_filter.AddFilterWord(pRow[0]);
nCount++;
}
pRow = sql.NextRow();
}
//释放查询结果集
sql.ResetQuery();
OutputMsg(rmTip, _T("%d filter name loaded"), nCount);
return TRUE;
}
//修改了字符串越界的问题
/*
utf-8编码规则如果是1个字节是
1个字节0xxxxxxx
2个字节110xxxxx 10xxxxxx
3个字节1110xxxx 10xxxxxx 10xxxxxx
4个字节11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
5个字节111110xx 10xxxxxx 10xxxxxx 10xxxxxx
*/
INT_PTR CDBServer::GetStrLenUtf8(LPCTSTR sName)
{
LPCSTR sptr;
INT_PTR nLen = 0;
unsigned char ch;
for ( sptr = sName; *sptr; ++sptr )
{
ch = (unsigned char)*sptr;
if((ch & 0xF8) == 0xF8) //5个字节111110xx 10xxxxxx 10xxxxxx 10xxxxxx
{
sptr += 4;
}
else if( (ch & 0xF0) == 0xF0 )//4个字节11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
{
sptr += 3;
}
else if( (ch & 0xE0) == 0xE0)//3个字节1110xxxx 10xxxxxx 10xxxxxx
{
sptr += 2;
}
else if( (ch & 0xC0) == 0xC0 )//2个字节110xxxxx 10xxxxxx
{
sptr += 1;
}
nLen++;
//增加一个判断,防止恶意输入
if(nLen >1000)
{
break;
}
}
return nLen;
}
void CDBServer::CheckNameFilter()
{
for (int i=0; i <m_pListPrefix->Count(); i++)
{
LPCTSTR name = m_pListPrefix->get(i);
if (!CheckNameStr(name))
{
OutputMsg(rmWaning,"name filter error:%s",name);
}
}
for (int i=0; i <m_pListStuffix->Count(); i++)
{
LPCTSTR name = m_pListStuffix->get(i);
if (!CheckNameStr(name))
{
OutputMsg(rmWaning,"name filter error:%s",name);
}
}
}
BOOL CDBServer::CheckNameStr( LPCSTR sNameStr )
{
//检查是否包含控制字符以及英文标点符号,这些字符是不被允许的
LPCSTR sptr;
unsigned int ch;
DECLARE_FUN_TIME_PROF()
for ( sptr = sNameStr; *sptr; ++sptr )
{
//此处允许中文
ch = (unsigned int)*sptr;
if ( ch >= 0x7F )
{
sptr += 2;//UTF-8
continue;
}
//此处允许a-z
if ( ch >= 'a' && ch <= 'z' )
continue;
//此处允许A-Z
if ( ch >= 'A' && ch <= 'Z' )
continue;
//此处允许0-9
if ( ch >= '0' && ch <= '9' )
continue;
return FALSE;
}
//从名称过滤表中进行屏蔽字检查
//m_NameFilterLock.Lock();
/*
if ( m_pFilterWords )
{
sptr = MatchMBCSFilterWord(m_pFilterWords, sNameStr, NULL);
}
else
{
OutputMsg(rmWaning,"No Filter name m_pFilterWords");
sptr = NULL;
}
*/
int nLen;
sptr = m_filter.Filter((char*)sNameStr,&nLen);
//m_NameFilterLock.Unlock();
return sptr == NULL;
}
bool CDBServer::hasFilterWordsInclude(LPCSTR sNameStr)
{
LPCSTR sptr = sNameStr;
for ( sptr--; *sptr; )
{
sptr++;
if (*sptr >= 'a' && *sptr <= 'z')
continue;
if (*sptr >= 'A' && *sptr <= 'Z')
continue;
if (*sptr >= '0' && *sptr <= '9')
continue;
if (*sptr >= 0x7F)
continue;
return true;
}
//return MatchMBCSFilterWord(m_pFilterWords, sNameStr, NULL) != NULL;
int nLen;
return m_filter.Filter((char*)sNameStr,&nLen) != NULL;
}
bool CDBServer::LoadNameGroup( LPCSTR sPrifixList, /*LPCSTR sConnectList,*/ LPCSTR sStuffixList )
{
if(!m_pListPrefix->loadFromFile(sPrifixList))
{
OutputMsg(rmError, _T("%s load %s file error"), __FUNCTION__, sPrifixList);
return false;
}
/*if(!m_pListConnect->loadFromFile(sConnectList))
{
OutputMsg(rmError, _T("%s load %s file error"), __FUNCTION__, sConnectList);
return false;
}*/
if(!m_pListStuffix->loadFromFile(sStuffixList))
{
OutputMsg(rmError, _T("%s load %s file error"), __FUNCTION__, sStuffixList);
return false;
}
return true;
}
bool CDBServer::GetRandomGroupName( char * sName, int nNameSize )
{
LPCSTR sPrefix = m_pListPrefix->GetRandomName();
//LPCSTR sConnect = m_pListConnect->GetRandomName();
LPCSTR sStuffix = m_pListStuffix->GetRandomName();
if (sPrefix != NULL /*&& sConnect != NULL*/ && sStuffix != NULL)
{
sprintf_s(sName, nNameSize, "%s%s", sPrefix, sStuffix);
return true;
}
return false;
}
void CDBServer::RunEsqlFile(char* sToolPath,char* sDbName)
{
if(sToolPath && sDbName)
{
m_pEsqlMgr.EsqlMain(sToolPath,sDbName);
}
}

206
server/DBServer/DBServer.h Normal file
View File

@@ -0,0 +1,206 @@
#ifndef _DBENGINE_H_
#define _DBENGINE_H_
#include "CFilter.h"
class CDBGateManager;
class CDBSessionClient;
class LogSender;
class CNameSyncClient;
class CDBDataServer;
class CDBCenterClient;
class CEsqlManager;
class CDBServer
{
public:
CDBServer();
~CDBServer();
inline LPCSTR getServerName(){ return m_sServerName; };
//inline CDBGateManager* getGateManager(){ return m_pGateManager; };
//inline CDBSessionClient* getSessionClient(){ return m_pSSClient; };
//inline LogSender* getLogClient(){ return m_pLogClient; };
inline CNameSyncClient* getNameSyncClient(){ return m_pNameSyncClient; }
//inline CDBCenterClient* getDBCenterClient() { return m_pDBCenterClient; }
inline CDBDataServer* getDataServer(){ return m_pDataServer; }
inline BOOL getSelectCountryEnabledOnCreateFirstChar(){ return m_boFirstCharEnableSelCountry; }
inline INT getServerIndex() { return m_nServerIndex;}
BOOL getGameReady(int nSrvIdx);
//配置数据库连接对象
VOID SetupSQLConnection(CSQLConenction *lpConnection);
//将名称字符串中首个字符之后的字母全部转换为小写
LPCSTR LowerCaseNameStr(LPSTR sNameStr,INT_PTR nSize);
//加载游戏网关路由表,返回-1表示发生错误否则表示加载的路由信息数量
INT LoadGameServerRoute();
// 输出游戏路由信息
void TraceGameServerRoute();
//为网关用户选择角色网关路由地址选择路由地址成功则返回TRUE并将地址保存在lpGateHost中会添加终止字符将端口保存在lpGatePort中
BOOL SelectGameServerRoute(const int nServerIndex, LPSTR lpGateHost, const SIZE_T dwHostLen, PINT_PTR lpGatePort);
//获取会话数据
inline BOOL GetSessionData(const int nSessionId, OUT jxSrvDef::PGLOBALSESSIONOPENDATA pSessionData)
{
//return m_pSSClient->GetSessionData(nSessionId, pSessionData);
return FALSE;
}
//依据会话ID关闭连接到网关中的用户
inline VOID PostCloseGateUserBySessionId(const int nSessionId)
{
//m_pGateManager->PostCloseGateUserByGlobalSessionId(nSessionId);
}
//异步检查网关中是否存在会话为特定值的用户
inline VOID PostQueryUserExistsBySessionId(const int nSessionId)
{
//m_pGateManager->PostQueryGateUserExistsBySessionId(nSessionId);
}
//网关向DBSSClient返回对用户是否存在的查询的消息
inline VOID PostQueryUserExistsBySessionIdResult(const int nSessionId, const BOOL boExists)
{
//m_pSSClient->PostQuerySessionExistsResult(nSessionId, boExists);
}
//网关向DBSSClient投递改变会话状态的消息
inline VOID PostChangeSessionState(const int nSessionId, const jxSrvDef::GSSTATE nState)
{
//m_pSSClient->PostChangeSessionState(nSessionId, nState);
}
//当网关用户关闭的时候,向会话模块投递用户关闭的消息,以便决定是否应该删除会话
inline VOID PostSSClientUserClosed(const int nSessionId)
{
//m_pSSClient->PostCloseSession(nSessionId);
}
//向特定的数据服务器投递打开角色加载认证数据
inline VOID PostDBServerOpenCharLoad(const int nServerIndex, UINT64 nSessionId, UINT64 nCharId,UINT64 nCurrentTick)
{
m_pDataServer->PostOpenCharLoad(nServerIndex, nSessionId, nCharId,nCurrentTick);
}
//设置服务器名称
VOID SetServerName(LPCSTR sSrvName);
//设置网关服务的地址和端口
VOID SetGateServiceAddress(LPCTSTR sHost, const INT_PTR nBindPort);
//设置会话服务器地址和端口,设置会在会话客户端下次连接的时候生效
VOID SetSessionServerAddress(LPCTSTR sHost, const INT_PTR nPort);
//设置日志服务器地址和端口
VOID SetLogServerAddress(LPCTSTR sHost, const INT_PTR nPort);
// 设置DBCenter服务器地址和断开
VOID SetDBCenterAddress(LPCTSTR sHost, const INT_PTR nPort);
//设置数据库连接配置
VOID SetSQLConfig(LPCSTR sHost, const INT_PTR nPort, LPCSTR sDBName, LPCSTR sDBUser, LPCSTR sUserPassword, bool boUtf8);
//设置是否允许在创建第一个角色的时候选择国家
VOID SetSelectCountryEnabledOnCreateFirstChar(const BOOL boEnabled);
//设置名称服务器地址和端口,设置会在名称客户端下次连接的时候生效
VOID SetNameSyncServerAddress(LPCTSTR sHost, const INT_PTR nPort);
//设置数据服务的绑定地址和端口
VOID SetDataServiceAddress(LPCTSTR sBindHost, const INT_PTR nBindPort);
VOID SetServerIndex(INT nServerIndex);
//启动数据服务器的服务
BOOL Startup();
//停止数据服务器的服务
VOID Shutdown();
//读入关键字敏感词
BOOL LoadFilterNames();
//增加关键字敏感词
void AddFilterName(char* sName);
//获取utf8格式的字符串的长度1个汉字和1个英文字符都是1
static INT_PTR GetStrLenUtf8(LPCTSTR sName);
void CheckNameFilter();
//检查名字里是否有敏感词如果有返回false
BOOL CheckNameStr(LPCSTR sNameStr);
/*
* Comments:加载文件
* Param LPCSTR sPrifixList:
* Param LPCSTR sConnectList:
* Param LPCSTR sStuffixList:
* @Return bool:
*/
bool LoadNameGroup(LPCSTR sPrifixList, /*LPCSTR sConnectList,*/ LPCSTR sStuffixList);
//获取一个随机生成的名字
INT_PTR GetRandomName(LPCTSTR& sName,INT_PTR nSex);
bool GetRandomGroupName(char * sName, int nSize);
//判断名称字符串中是否含有非法字符
bool hasFilterWordsInclude(LPCSTR sNameStr);
// 更新逻辑网关用户信息
void UpdateLogicGateUserInfo(CDataPacketReader& packet);
//设置数据服务器启动标志
void SetDbStartFlag(bool bFlag) {m_bStartDbServer = bFlag;}
//返回数据服务器关闭的标志
bool GetDbStartFlag() {return m_bStartDbServer;}
//运行esql文件
void RunEsqlFile(char* sToolPath,char* sDbName);
//追踪内存使用情况
void Trace();
bool IsUtf8()
{
return m_boUtf8;
}
private:
//释放游戏网关路由数据
VOID FreeGameServerRoute();
INT_PTR SelecteGameGateRouteIndex(jxSrvDef::PGAMESERVERROUTE pRoute);
private:
CHAR m_sServerName[128]; //服务器名称
CHAR m_sSQLHost[128]; //数据库地址
INT_PTR m_nSQLPort; //数据库端口
CHAR m_sSQLDBName[128]; //数据库名称
CHAR m_sSQLUser[128]; //数据库用户名
CHAR m_sSQLPassword[128]; //数据库用户密码
TCHAR m_sNameSyncServerHost[128]; //名称服务器地址(如果地址不为空字符串则通过名称服务器申请角色和帮会ID)
INT_PTR m_nNameSyncServerPort; //名称服务器端口
BOOL m_boFirstCharEnableSelCountry;//账号创建第一个角色时是否允许选择国家默认值为FALSE
bool m_boUtf8; //使用utf8数据编码
CFilter m_filter; //
//CDBGateManager *m_pGateManager; //网关管理器
//CDBSessionClient *m_pSSClient; //会话客户端
CNameSyncClient *m_pNameSyncClient; //名称客户端
CDBDataServer *m_pDataServer; //数据服务器
//LogSender *m_pLogClient; //日志客户端
//CDBCenterClient *m_pDBCenterClient; // DBCenter客户端
CCSLock m_GameServerRouteListLock;//游戏网关路由表锁
CLockList<jxSrvDef::PGAMESERVERROUTE> m_GameServerRouteList;//游戏网关路由表
CEsqlManager m_pEsqlMgr; //运行esql文件
// zac
int m_nServerIndex;
//PFT_MBCS_CHAR m_pFilterWords; //屏蔽词列表
CCSLock m_NameFilterLock;
CCSLock m_RandNameLock;
CLoadString * m_pListPrefix;
//CLoadString * m_pListConnect;
CLoadString * m_pListStuffix;
bool m_bStartDbServer;
public:
static CDBServer *s_pDBEngine;
};
inline CDBServer* GetGlobalDBEngine()
{
return CDBServer::s_pDBEngine;
}
#endif

View File

@@ -0,0 +1,67 @@

#include "StdAfx.h"
CDBSessionClient::CDBSessionClient(CDBServer *lpDBServer)
{
m_pDBServer = lpDBServer;
}
CDBSessionClient::~CDBSessionClient()
{
}
SERVERTYPE CDBSessionClient::getLocalServerType()
{
return DBServer;
}
int CDBSessionClient::getLocalServerIndex()
{
return m_pDBServer->getServerIndex();
}
LPCSTR CDBSessionClient::getLocalServerName()
{
return m_pDBServer->getServerName();
}
CCustomGlobalSession* CDBSessionClient::CreateSession()
{
return Inherited::CreateSession();
}
VOID CDBSessionClient::DestroySession(CCustomGlobalSession* pSession)
{
Inherited::DestroySession(pSession);
}
VOID CDBSessionClient::OnOpenSession(CCustomGlobalSession* pSession, BOOL boIsNewSession)
{
//收到打开session的包的时候向session服务器发一个包回复一下session依据这个回复告诉客户端登陆
//通过这个确认的流程保证登陆服务器的时候session的数据是到位的
//只有自己的数据服务器才会回复,其他的不需要回复
if( m_pDBServer->getGameReady(pSession->nServerIndex) )
{
CDataPacket &data = allocProtoPacket(jxInterSrvComm::SessionServerProto::cConformOpenSession); //分配一个 网络包
data << (int)pSession->nSessionId ;
data << (int)pSession->nServerIndex;
flushProtoPacket(data);
}
}
VOID CDBSessionClient::OnCloseSession(int nSessionId)
{
//会话被关闭的同时需要向网关发送按全局会话ID关闭连接的消息
m_pDBServer->PostCloseGateUserBySessionId(nSessionId);
}
VOID CDBSessionClient::OnUpdateSessionState(CCustomGlobalSession* pSession, jxSrvDef::GSSTATE oldState, jxSrvDef::GSSTATE newState)
{
}
VOID CDBSessionClient::OnQuerySessionExists(INT_PTR nSessionId)
{
//异步的通过会话ID查询网关用户网关对此消息的返回将在内部消息分派函数中处理
m_pDBServer->PostQueryUserExistsBySessionId((int)nSessionId);
}

View File

@@ -0,0 +1,57 @@
#pragma once
class CDBServer;
class CDBSessionClient
: public CCustomSessionClient
{
public:
typedef CCustomSessionClient Inherited;
public:
CDBSessionClient(CDBServer *lpDBServer);
~CDBSessionClient();
protected:
/*** 覆盖父类的会话逻辑处理函数 ***/
/* ★查询本地服务器的类型,以便正确的向会话服务器注册连接 */
jxSrvDef::SERVERTYPE getLocalServerType();
// 返回serverindex
virtual int getLocalServerIndex();
/* ★查询本地服务器的名称,以便正确的向会话服务器注册连接 */
LPCSTR getLocalServerName();
/* ★创建一个会话对象默认的操作是使用m_Allocator申请一份会话对象内存 */
CCustomGlobalSession* CreateSession();
/* ★销毁一个会话对象默认的操作是将会话对象释放回m_Allocator中 */
VOID DestroySession(CCustomGlobalSession* pSession);
/* ★当会话服务器告知有新会话打开的时,当创建会话对象并填充基本数据后调用
*pSession 会话对象
*boIsNewSession 是否是新的会话(一个会话可能已经存在与本地会话列表中,但会话实际是不在线的,此情况下用此参数区分是否是完全新打开的会话)
*/
VOID OnOpenSession(CCustomGlobalSession* pSession, BOOL boIsNewSession);
/* ★当一个会话被关闭时调用
*nSessionID 会话ID当调用此函数时会话对象已经被删除因此不能提供会话对象参数
*/
VOID OnCloseSession(int nSessionId);
//实现父类的虚函数
VOID OnCloseSession(CCustomGlobalSession *pSession){}
/* ★当被动(由会话服务器广播而进行的)更新会话状态的时候调用此函数
*pSession 会话对象
*oldState 会话更新前的状态
*newState 会话更新后的状态
*/
VOID OnUpdateSessionState(CCustomGlobalSession* pSession, jxSrvDef::GSSTATE oldState, jxSrvDef::GSSTATE newState);
/* ★查询全局会话关联的用户是否在线
*nSessionId 全局会话ID
* 此函数内不应当做阻塞式的操作例如对其他对象加锁以求立刻查询会话ID关联的用户是否存在
* 必须使用内部消息PostInternalMessage的形式向其他线程的对象发送消息并在该线程中处理消息查询会话关联的用户是否存在
* 最后使用PostQuerySessionExistsResult返回查询用户是否在线的结果
*/
VOID OnQuerySessionExists(INT_PTR nSessionId);
private:
CDBServer *m_pDBServer; //所属DBServer
};

308
server/DBServer/EsqlMgr.cpp Normal file
View File

@@ -0,0 +1,308 @@
#include "StdAfx.h"
#include "EsqlMgr.h"
static const LPCTSTR g_szEsqlFile = _T("./sql/");
CEsqlManager::CEsqlManager()
{
m_DbSQl.empty();
}
CEsqlManager::~CEsqlManager()
{
m_DbSQl.empty();
}
void CEsqlManager::EsqlMain(char* sToolPath,char* sDbName)
{
if(!sToolPath || !sDbName) return;
if (!FileExist(sToolPath) )
{
OutputMsg( rmNormal, _T("EsqlTool not exist") );
return;
}
//if (!FileExist(g_szEsqlFile) )
//{
// OutputMsg( rmNormal, _T("Esql file not exist") );
// return;
//}
GetAllFileName();
OnRunEsqlTool(sToolPath,sDbName);
DeleteEsqlFile();
OutputMsg( rmNormal, _T("load Esql file finish") );
}
bool CEsqlManager::FileExist(LPCTSTR lpszFilePath)
{
#ifdef WIN32
DWORD dwAttr = GetFileAttributes(lpszFilePath);
#else
DWORD dwAttr = access(lpszFilePath, R_OK | W_OK);
#endif
if ( dwAttr == (DWORD)-1 )
return false;
else
return true;
}
void CEsqlManager::GetAllFileName()
{
//if (!FileExist(g_szEsqlFile) )
//return;
#ifdef WIN32
WIN32_FIND_DATA FindFileData;
HANDLE hFind = INVALID_HANDLE_VALUE;
char DirSpec[MAX_PATH] = "";
DWORD dwError;
strncat (DirSpec, "*", 3);
hFind = FindFirstFile(DirSpec, &FindFileData);
if (hFind == INVALID_HANDLE_VALUE)
{
OutputMsg( rmNormal, _T("no esql file") );
return;
}
else
{
//OutputMsg( rmError, "First file name is %s\n", FindFileData.cFileName);
FindNextFile(hFind, &FindFileData);
while (FindNextFile(hFind, &FindFileData) != 0)
{
if(bSqlFile(FindFileData.cFileName))
{
OutputMsg( rmNormal, "Next file name is %s", FindFileData.cFileName);
int nId = GetEsqlId(FindFileData.cFileName);
if(nId > 0)
{
AddEsqlToList(nId,FindFileData.cFileName);
}
}
}
//for(int i =0;i<m_DbSQl.count();i++)
//{
// OutputMsg( rmNormal, "m_DbSQl index=%d ",m_DbSQl[i].nId);
//}
dwError = GetLastError();
FindClose(hFind);
if (dwError != ERROR_NO_MORE_FILES)
{
OutputMsg( rmNormal, "FindNextFile error. ");
}
}
#else
DIR * dir ;
dirent * ptr = NULL;
char DirSpec[MAX_PATH] = "";
DWORD dwError;
strncat (DirSpec, "*", 3);
dir = opendir( DirSpec ) ;
if( dir == NULL )
{
OutputMsg( rmNormal, _T("no esql file") );
return;
}
else
{
while ((ptr = readdir( dir )) != NULL)
{
if(bSqlFile(ptr->d_name))
{
OutputMsg( rmNormal, "Next file name is %s", ptr->d_name);
int nId = GetEsqlId(ptr->d_name);
if(nId > 0)
{
AddEsqlToList(nId,ptr->d_name);
}
}
}
//for(int i =0;i<m_DbSQl.count();i++)
//{
// OutputMsg( rmNormal, "m_DbSQl index=%d ",m_DbSQl[i].nId);
//}
dwError = GetLastError();
closedir(dir) ;
if (dwError != ENOENT)
{
OutputMsg( rmNormal, "FindNextFile error. ");
}
}
#endif
}
bool CEsqlManager::bSqlFile(char* fileName)
{
if(!fileName) return false;
size_t nLen = strlen(fileName);
if(nLen <= 4) return false;
char* t = &fileName[nLen-5];
if(strcmp(t,".esql") == 0) return true;
return false;
}
int CEsqlManager::GetEsqlId(char* strEsql)
{
char sName[255];
if(strEsql)
{
int j=0;
for(int i=0;i<strlen(strEsql);i++)
{
if(strEsql[i] >= 49 && strEsql[i] <58)
{
sName[j++] = strEsql[i];
}
else
{
break;
}
}
if(j > 0 && j < 255)
{
sName[j] = 0;
}
int nId = atoi(sName);
return nId;
}
return -1;
}
void CEsqlManager::AddEsqlToList(int nId,char *strEsql)
{
if(!strEsql) return;
DBSQL tmpEsql;
tmpEsql.nId = nId;
_asncpytA(tmpEsql.sFileName,strEsql);
int index = -1;
for(int i=0;i<m_DbSQl.count();i++)
{
if(tmpEsql.nId < m_DbSQl[i].nId)
{
index = i;
break;
}
}
if(index >= 0)
{
m_DbSQl.insert(index,tmpEsql);
}
else
{
m_DbSQl.add(tmpEsql);
}
}
void CEsqlManager::OnRunEsqlTool(char* sToolPath,char* sDbName)
{
INT_PTR nCount = m_DbSQl.count();
if(nCount <= 0) return;
char buf[1000];
#ifdef WIN32
GetCurrentDirectory(1000,buf); //得到当前工作路径
strcat(buf,"\\");
#else
getcwd(buf, 1000); //得到当前工作路径
strcat(buf,"/");
#endif
char dbId[32];
if(sDbName)
{
int j=0;
for(int i=0;i<strlen(sDbName);i++)
{
if(sDbName[i] >= '0' && sDbName[i] <= '9')
{
dbId[j++] = sDbName[i];
}
}
if(j >= 0 && j < 32)
{
dbId[j]=0;
}
}
else
{
dbId[0]=0;
}
OutputMsg( rmNormal, "GetCurrentDirectory %s,serveindex=%s",buf,dbId?dbId:"");
for(int i = 0;i<nCount;i++)
{
char sPath[300];
char curpath[1000];
_asncpytA(curpath,buf);
strcat(curpath,m_DbSQl[i].sFileName);
char* filename = "";
sprintf_s(sPath, sizeof(sPath),"%s %s %s %s",sToolPath,curpath,sDbName,dbId[0] !=0 ?dbId:"0");
OutputMsg( rmNormal, "OnRunEsqlTool: %s",sPath);
//找到文件的路径
char dir[MAX_PATH];
strcpy(dir,sToolPath);
for(size_t j= strlen(dir) -1; j >=0; j--)
{
if(dir[j] =='\\')
{
dir[j]=0;
break;
}
}
SetCurrentDirectory(dir);
system(sPath);
Sleep(100);
}
SetCurrentDirectory(buf);
}
void CEsqlManager::DeleteEsqlFile()
{
INT_PTR nCount = m_DbSQl.count();
if(nCount <= 0) return;
char buf[1000];
#ifdef WIN32
GetCurrentDirectory(1000,buf); //得到当前工作路径
strcat(buf,"\\");
#else
getcwd(buf, 1000); //得到当前工作路径
strcat(buf,"/");
#endif
for(int i = 0;i<nCount;i++)
{
char sPath[1000];
_asncpytA(sPath,buf);
strcat(sPath,m_DbSQl[i].sFileName);
DeleteFileA(sPath);
}
m_DbSQl.empty();
}

47
server/DBServer/EsqlMgr.h Normal file
View File

@@ -0,0 +1,47 @@
//支持数据服执行esql并自动删除
#pragma once
typedef struct tagDbEsql
{
int nId; //索引
char sFileName[256]; //文件名称
tagDbEsql()
{
memset(this,0,sizeof(*this));
}
}DBSQL;
class CEsqlManager
{
public:
CEsqlManager();
~CEsqlManager();
//运行esql的主流程
void EsqlMain(char* sToolPath,char* sDbName);
bool FileExist(LPCTSTR lpszFilePath);
//获取文件夹下所有文件名称
void GetAllFileName();
//获取esql的文件的id
int GetEsqlId(char* strEsql);
//添加到sql列表
void AddEsqlToList(int nId,char *strEsql);
//执行esql语句的工具
void OnRunEsqlTool(char* sToolPath,char* sDbName);
//删除文件
void DeleteEsqlFile();
//判断是否sql文件
bool bSqlFile(char* fileName);
private:
wylib::container::CBaseList<DBSQL> m_DbSQl;
};

View File

@@ -0,0 +1,141 @@
#include "StdAfx.h"
/*
#include "../common/db/Fuben.h"
int CDBDataClient::SaveFubenData(int nActorid,int Fbid,int Daycount,int Progress)
{
int ret = reSucc;
if ( !m_pSQLConnection->Connected() )
{
ret = reDbErr;
}
else
{
//insert
int nError = m_pSQLConnection->Exec(szSQLSP_AddCharFubenData, nActorid,Fbid,Daycount,Progress);
if ( !nError )
{
ret = reSucc;
m_pSQLConnection->ResetQuery();
}
else
{
ret = reDbErr;
}
}
if (ret != reSucc)
{
OutputMsg(rmError,_T("save fuben data error!id=%d,Fbid=%d,Daycount=%d,Progress=%d"),
nActorid,Fbid,Daycount,Progress);
}
return ret;
}
VOID CDBDataClient::SaveFuben(CDataPacketReader &inPacket)
{
int nActorId = 0;
inPacket >> nActorId;
CDataPacket& retPack = allocProtoPacket(dcSaveFuben);
retPack << nActorId;
BYTE ret = CleanFuben(nActorId);
if (ret != reSucc)
{
retPack << (BYTE)ret;
flushProtoPacket(retPack);
return;
}
WORD nCount = 0;
inPacket >> nCount;
for (int i = 0; i < nCount; i++)
{
FubenData data;
inPacket >> data;
ret = SaveFubenData(nActorId,data.wFubenId,data.wDaycount,data.bProgress);
if (ret != reSucc)
{
break;
}
}
retPack << (BYTE)ret;
flushProtoPacket(retPack);
}
int CDBDataClient::CleanFuben(INT_PTR nActorid)
{
int ret = reSucc;
if ( !m_pSQLConnection->Connected() )
{
ret = reDbErr;
}
else
{
//先删除
int nError = m_pSQLConnection->Exec(szSQLSP_CleanCharFuben, nActorid);
if ( !nError )
{
m_pSQLConnection->ResetQuery();
}else
{
ret = reDbErr;
}
}
if (ret != reSucc)
{
OutputMsg(rmError,_T("cleanfubendata error!id=%d"),
nActorid);
}
return ret;
}
VOID CDBDataClient::LoadFubenData(CDataPacketReader &inPacket)
{
int nActorId;
inPacket >> nActorId;
LoadFubenData(nActorId);
}
VOID CDBDataClient::LoadFubenData(INT_PTR nActorId)
{
CDataPacket& retPack = allocProtoPacket(dcLoadFuben);
retPack << nActorId;
//数据库连接是否就绪
if ( !m_pSQLConnection->Connected() )
{
retPack << (BYTE)reDbErr;
}
else
{
//向数据库查询进度任务数据
int nError = m_pSQLConnection->Query(szSQLSP_LoadCharFubenData, nActorId);
if ( !nError )
{
retPack << (BYTE)reSucc;
MYSQL_ROW pRow = m_pSQLConnection->CurrentRow();
WORD nCount = m_pSQLConnection->GetRowCount();
retPack << nCount;
while ( pRow)
{
FubenData data;
sscanf(pRow[0], "%d", &data.wFubenId);
sscanf(pRow[1], "%d", &data.wDaycount);
sscanf(pRow[2], "%d", &data.bProgress);
retPack << data;
pRow = m_pSQLConnection->NextRow();
}
m_pSQLConnection->ResetQuery();
}
else
{
retPack << (BYTE)reDbErr;
}
}
flushProtoPacket(retPack);
}
*/

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,115 @@
#ifndef GATE_DB_REQUEST_HANDLER_H_
#define GATE_DB_REQUEST_HANDLER_H_
/*
* 用于用户登录的验证阶段的处理
*/
class CSQLConnection;
class CDataPacket;
class CDBDataServer;
class ILogicDBRequestHost;
class CGateDBReqestHandler
{
public:
CGateDBReqestHandler();
~CGateDBReqestHandler();
bool Init(CSQLConenction *pConn, CDBDataServer *pMgr);
/*
* Comments: 查询指定账号角色列表
* Param const int nAccountId: 账号ID
* Param const int nServerId: 服务器ID
* Param CDataPacket & packet: 输出数据包
* @Return void:
* @Remark: 输出内容包括错误码1Byte) + 角色数目1Byte + 角色信息列表。如果查询失败,只有错误码。
*/
void GetActorList(const unsigned int nAccountId, const int nServerId, CDataPacket &packet);
void GetActorSecondPsw(const unsigned int nAccountId, const int nServerId, CDataPacket &packet);
/*
* Comments: 选择角色准备进入游戏
* Param const int nServerId: 登录的逻辑服务器ID
* Param const int nRawServerId: 登录的原始服务器ID
* Param const int nAccountId: 账号ID
* Param const int nActorId: 角色ID
* Param const char * szAccount: 账号名
* Param LONGLONG nIP: 登录IP地址
* @Return int: 返回错误码。0表示成功。
* @Remark:
*/
int StartEnterGame(const int nServerId,
const int nRawServerId,
const unsigned int nAccountId,
const unsigned int nActorId,
const char *szAccount,
LONGLONG nIP);
/*
* Comments:获取登陆的消息包
* Param const jxSrvDef::INTERSRVCMD nCmd:消息码
* Param CDataPacketReader & inPacket:传入的读写器
* Param CDataPacket & retPack:返回的读写器
* @Return void:
*/
void OnRecvLoginMsg(const jxSrvDef::INTERSRVCMD nCmd, CDataPacketReader& inPacket,ILogicDBRequestHost * pDataClient);
//创建角色
VOID OnCreateActorResult( INT_PTR nError,unsigned int nActorId,PCREATEACTORDATA pData,ILogicDBRequestHost * pDataClient);
//创建跨服角色
VOID OnCreateCrossServerActorResult( INT_PTR nError,unsigned int nActorId,PCREATEACTORDATA pData,ILogicDBRequestHost * pDataClient);
private:
/*
* Comments: 获取最少使用的职业,用于创建角色默认选择的职业选择用
* Param const int nServerId:
* @Return tagActorVocation:
* @Remark:
*/
int QueryLessJobReq(const int nServerId);
//创建角色
void OnCreateActor( CDataPacketReader& inPacket,ILogicDBRequestHost * pDataClient );
//删除角色
void OnDeleteActor( CDataPacketReader& inPacket,ILogicDBRequestHost * pDataClient );
//随机名字
void OnRandName( CDataPacketReader& inPacket,ILogicDBRequestHost * pDataClient );
/*
* Comments: 获取当前可以选择的阵营列表,用于创建角色选择阵营用
* Param const int nServerId:
* @Return int: 返回可以选择的阵营对应位掩码。低3位有效为0表示对应的阵营不可选为1表示阵营可选
返回值为7表示所有阵营都可以选择
* @Remark:
*/
int QueryZyList(const int nServerId);
/*
* Comments: 获取使用最少(最优先)的阵营
* Param const int nServerId: 逻辑服务器ID
* @Return tagZhenying:
* @Remark:
*/
tagZhenying QueryZYReq(const int nServerId);
//改名字
void OnChaneActorNameToDb(CDataPacketReader & inPacket,ILogicDBRequestHost * pDataClient);
void OnCheckSecondPsw(CDataPacketReader & inPacket,ILogicDBRequestHost * pDataClient);
void OnCreateSecondPsw(CDataPacketReader & inPacket,ILogicDBRequestHost * pDataClient);
INT_PTR QueryActorCount( INT_PTR nAccountId, INT_PTR nServerIndex );
INT_PTR CreateCrossServerActor( CDataPacketReader& inPacket,ILogicDBRequestHost * pDataClient);
INT_PTR QueryCrossServerActor( CDataPacketReader& inPacket,ILogicDBRequestHost * pDataClient);
private:
CSQLConenction *m_pSQLConnection;
CDBDataServer *m_pDBServer; //是这个指针
};
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,579 @@

#include "StdAfx.h"
#include "JobZyCountMgr.h"
CJobZyCountMgr::CJobZyCountMgr()
{
m_bLoadJobData = false;
m_bLoadZyData =false;
//m_nNextZyJobSaveTime = _getTickCount();
m_bZyDataDirty = false;
m_bJobDataDirty = false;
m_bLoadNameData = false;
m_SQLConnection =NULL; //设置这个链接
m_bLoadGuildNameData =false; //是否装载过行会的数据
}
//装载行会名字
void CJobZyCountMgr::LoadGuildNameInitData()
{
if(m_SQLConnection ==NULL || m_SQLConnection->Connected() ==false) return;
if(m_bLoadGuildNameData) return; //已经装载过了
m_guildNameLock.Lock();
int nError = m_SQLConnection->Query("select guildname,serverindex,guildid from guildlist where status = 1");
if (reSucc == nError)
{
MYSQL_ROW pRow = m_SQLConnection->CurrentRow();
int nCount = m_SQLConnection->GetRowCount();
while (pRow)
{
PlayerNameDistribute sNameList;
if(pRow[0])
{
memcpy(&sNameList.sName,pRow[0],sizeof(sNameList.sName));
}
sscanf(pRow[1], "%d",&sNameList.nServerIdx);
sscanf(pRow[2], "%d",&sNameList.guildid);
if(sNameList.nServerIdx > 0)
{
m_guildNameDist.add(sNameList);
}
pRow = m_SQLConnection->NextRow();
}
m_SQLConnection->ResetQuery();
m_bLoadGuildNameData = true;
}
m_guildNameLock.Unlock();
}
void CJobZyCountMgr::LoadActorNameInitData()
{
if(m_SQLConnection ==NULL || m_SQLConnection->Connected() ==false) return;
if(m_bLoadNameData) return; //已经装载过了
m_nameLock.Lock();
int nError = m_SQLConnection->Query(szSQLSP_LoadActorNameInitData);
if (reSucc == nError)
{
MYSQL_ROW pRow = m_SQLConnection->CurrentRow();
int nCount = m_SQLConnection->GetRowCount();
while (pRow)
{
PlayerNameDistribute sNameList;
if(pRow[0])
{
memcpy(&sNameList.sName,pRow[0],sizeof(sNameList.sName));
}
sscanf(pRow[1], "%d",&sNameList.nServerIdx);
if(sNameList.nServerIdx > 0)
{
m_vecNameDist.add(sNameList);
}
pRow = m_SQLConnection->NextRow();
}
m_SQLConnection->ResetQuery();
m_bLoadNameData = true;
}
m_nameLock.Unlock();
}
VOID CJobZyCountMgr::LoadJobInitData()
{
if(m_SQLConnection ==NULL || m_SQLConnection->Connected() ==false) return;
if(m_bLoadJobData) return; //已经装载过了
m_jobLock.Lock();
int nError = m_SQLConnection->Query(szSQLSP_LoadJobDistributeData);
if (reSucc == nError)
{
MYSQL_ROW pRow = m_SQLConnection->CurrentRow();
int nCount = m_SQLConnection->GetRowCount();
INT_PTR nLastSrvIdx = -1; // Invalid srv idx
int nJob, nUserCount, nSrvIdx;
PlayerJobDistribute jobDist;
jobDist.m_nServerIdx = nLastSrvIdx;
while (pRow)
{
sscanf(pRow[0], "%d", &nJob);
sscanf(pRow[1], "%d", &nUserCount);
sscanf(pRow[2], "%d", &nSrvIdx);
if (nJob > enVocNone && nJob < enMaxVocCount && nUserCount > 0) // 只保存nUserCount大于0的职业
{
if (nLastSrvIdx != nSrvIdx)
{
if (jobDist.m_nServerIdx != -1)
m_vecJobDist.add(jobDist);
jobDist.Reset();
jobDist.m_nServerIdx = nSrvIdx;
nLastSrvIdx = nSrvIdx;
}
jobDist.m_anPlayerCount[nJob] = nUserCount;
}
pRow = m_SQLConnection->NextRow();
}
if (jobDist.m_nServerIdx != -1)
m_vecJobDist.add(jobDist);
m_SQLConnection->ResetQuery();
m_bLoadJobData = true;
}
m_jobLock.Unlock();
}
VOID CJobZyCountMgr::SaveJobData()
{
if(m_SQLConnection ==NULL || m_SQLConnection->Connected() ==false) return;
m_jobLock.Lock();
if (m_bLoadJobData && m_bJobDataDirty)
{
if (m_SQLConnection->Connected())
{
char szSql[1024];
for (INT_PTR i = 0; i < m_vecJobDist.count(); i++)
{
// clean first
PlayerJobDistribute& dist = m_vecJobDist[i];
sprintf(szSql, szSQLSP_CleanJobDistributeData, (int)dist.m_nServerIdx);
int nError = m_SQLConnection->RealExec(szSql, strlen(szSql));
if (nError == reSucc)
{
bool bFirstItem = true;
sprintf(szSql, "%s", szSQLSP_AddJobDistributeData);
for (INT_PTR j = enVocNone+1; j < enMaxVocCount; j++)
{
char szTemp[128];
if (dist.m_anPlayerCount[j] > 0)
{
if (!bFirstItem)
{
strcat(szSql, ",");
}
if (bFirstItem)
bFirstItem = false;
sprintf(szTemp, "(%d,%d,%d)", (int)j, (int)dist.m_anPlayerCount[j], (int)dist.m_nServerIdx);
strcat(szSql, szTemp);
}
}
m_SQLConnection->ResetQuery();
nError = m_SQLConnection->RealExec(szSql, strlen(szSql));
if (nError != reSucc)
{
OutputMsg(rmError, _T("%s add job count record failed(srvidx=%d"), __FUNCTION__, (int)dist.m_nServerIdx);
}
else
{
m_SQLConnection->ResetQuery();
}
}
}
m_bJobDataDirty = false;
}
}
m_jobLock.Unlock();
}
int CJobZyCountMgr::GetPriorityJob(int nSrvIdx)
{
if(m_SQLConnection ==NULL || m_SQLConnection->Connected() ==false) return 1;
m_jobLock.Lock();
int priorJob = enVocNone;
for (INT_PTR i = 0; i < m_vecJobDist.count(); i++)
{
PlayerJobDistribute& dist = m_vecJobDist[i];
if (nSrvIdx == dist.m_nServerIdx)
{
// find jobs in which less user
INT_PTR nCount = 0x7FFFFFFF;
static INT_PTR sValidVoc[] = {1, 2, 3};
static const INT_PTR snValidVocCount = ArrayCount(sValidVoc);
for (INT_PTR j = 0; j < snValidVocCount; j++)
{
INT_PTR nVoc = sValidVoc[j];
if (dist.m_anPlayerCount[nVoc] < nCount/* && dist.m_anPlayerCount[j] >= 0*/)
{
priorJob = (tagActorVocation)nVoc;
nCount = dist.m_anPlayerCount[nVoc];
}
}
}
}
if (priorJob == enVocNone)
priorJob = 1;
m_jobLock.Unlock();
return (int)priorJob;
}
void CJobZyCountMgr::OnNewPlayerCreated(int nSrvIdx, tagZhenying zy, tagActorVocation voc,char sName[32])
{
//OutputMsg(rmNormal, _T("create new player, zy=%d, voc=%d"), (int)zy, (int)voc);
/*
if (zy > zyNone && zy < zyMax)
{
m_zyLock.Lock();
INT_PTR i = 0;
for (; i < m_vecZyDist.count(); i++)
{
if (m_vecZyDist[i].m_nServerIdx == nSrvIdx)
{
m_vecZyDist[i].m_anPlayerCount[zy]++;
break;
}
}
// add new node
if (i == m_vecZyDist.count())
{
PlayerZYDistribute dist;
dist.m_nServerIdx = nSrvIdx;
dist.m_anPlayerCount[zy] = 1;
m_vecZyDist.add(dist);
}
m_bZyDataDirty = true;
m_zyLock.Unlock();
}
*/
if (voc > enVocNone && zy < enMaxVocCount)
{
m_jobLock.Lock();
INT_PTR i = 0;
for (; i < m_vecJobDist.count(); i++)
{
if (m_vecJobDist[i].m_nServerIdx == nSrvIdx)
{
m_vecJobDist[i].m_anPlayerCount[voc]++;
break;
}
}
if (i == m_vecJobDist.count())
{
PlayerJobDistribute dist;
dist.m_nServerIdx = nSrvIdx;
dist.m_anPlayerCount[voc] = 1;
m_vecJobDist.add(dist);
}
m_bJobDataDirty = true;
m_jobLock.Unlock();
}
if(sName && nSrvIdx > 0)
{
PlayerNameDistribute nameList;
nameList.nServerIdx = nSrvIdx;
_asncpytA(nameList.sName,sName);
m_vecNameDist.add(nameList);
}
}
//当新行会创建了以后
void CJobZyCountMgr::OnNewGuildNameCreate(int nSrvIdx, char* sName, int nGuildId)
{
if(sName ==NULL) return ;
if(IsGuildNameExist(sName,nSrvIdx))
{
OutputMsg(rmWaning,"Guild is exist =%s",sName);
return ;
}
//是否存在
m_guildNameLock.Lock();
PlayerNameDistribute nameList;
nameList.nServerIdx = nSrvIdx;
nameList.guildid = nGuildId;
_asncpytA(nameList.sName,sName);
m_guildNameDist.add(nameList);
m_guildNameLock.Unlock();
OutputMsg(rmTip,"create guild %s",sName);
}
bool CJobZyCountMgr::RemoveGuildById(int Guild)
{
for(int i = 0; i < m_guildNameDist.count(); i++)
{
PlayerNameDistribute* nameDist = &m_guildNameDist[i];
if(( Guild == nameDist->guildid))
{
m_guildNameDist.remove(i);
return true;
}
}
return false;
}
//行会名字是否存在
bool CJobZyCountMgr::IsGuildNameExist(char* sName,int nServerindex)
{
if(sName )
{
for(int i=0;i<m_guildNameDist.count();i++)
{
PlayerNameDistribute* nameDist = &m_guildNameDist[i];
if((nServerindex <0 || nServerindex == nameDist->nServerIdx) && strcmp(sName,nameDist->sName) == 0 )
{
return true;
}
}
}
else
{
return false;
}
return false;
}
VOID CJobZyCountMgr::LoadZyInitData()
{
if(m_bLoadZyData ) return;
if(m_SQLConnection ==NULL || m_SQLConnection->Connected() ==false) return ;
m_zyLock.Lock();
int nError = m_SQLConnection->Query(szSQLSP_LoadZyDistributeData);
if (reSucc == nError)
{
MYSQL_ROW pRow = m_SQLConnection->CurrentRow();
int nCount = m_SQLConnection->GetRowCount();
INT_PTR nLastSrvIdx = -1; // Invalid srv idx
int nZy, nUserCount, nSrvIdx;
PlayerZYDistribute zyDist;
zyDist.m_nServerIdx = nLastSrvIdx;
while (pRow)
{
sscanf(pRow[0], "%d", &nZy);
sscanf(pRow[1], "%d", &nUserCount);
sscanf(pRow[2], "%d", &nSrvIdx);
if (nZy > zyNone && nZy < zyMax && nUserCount > 0) // 只保存nUserCount大于0的阵营
{
if (nLastSrvIdx != nSrvIdx)
{
if (zyDist.m_nServerIdx != -1)
m_vecZyDist.add(zyDist);
zyDist.Reset();
zyDist.m_nServerIdx = nSrvIdx;
nLastSrvIdx = nSrvIdx;
}
zyDist.m_anPlayerCount[nZy] = nUserCount;
}
pRow = m_SQLConnection->NextRow();
}
// add last server zy distribute info
if (zyDist.m_nServerIdx != -1)
m_vecZyDist.add(zyDist);
m_SQLConnection->ResetQuery();
m_bLoadZyData = true;
}
m_zyLock.Unlock();
}
VOID CJobZyCountMgr::SaveZyData()
{
if(m_SQLConnection->Connected() ==false) return ;
m_zyLock.Lock();
if (m_bLoadZyData && m_bZyDataDirty)
{
if (m_SQLConnection->Connected())
{
char szSql[1024];
for (INT_PTR i = 0; i < m_vecZyDist.count(); i++)
{
// clean first
PlayerZYDistribute& dist = m_vecZyDist[i];
sprintf(szSql, szSQLSP_CleanZyDistributeData, (int)dist.m_nServerIdx);
int nError = m_SQLConnection->RealExec(szSql, strlen(szSql));
if (nError == reSucc)
{
bool bFirstItem = true;
sprintf(szSql, "%s", szSQLSP_AddZyDistributeData);
for (INT_PTR j = zyNone+1; j < zyMax; j++)
{
char szTemp[128];
if (dist.m_anPlayerCount[j] > 0)
{
if (!bFirstItem)
{
strcat(szSql, ",");
}
if (bFirstItem)
bFirstItem = false;
sprintf(szTemp, "(%d,%d,%d)", (int)j, (int)dist.m_anPlayerCount[j], (int)dist.m_nServerIdx);
strcat(szSql, szTemp);
}
}
m_SQLConnection->ResetQuery();
nError = m_SQLConnection->RealExec(szSql, strlen(szSql));
if (nError != reSucc)
{
OutputMsg(rmError, _T("%s add zy count record failed(srvidx=%d"), __FUNCTION__, (int)dist.m_nServerIdx);
}
else
{
m_SQLConnection->ResetQuery();
}
}
}
m_bZyDataDirty = false;
}
}
m_zyLock.Unlock();
}
tagZhenying CJobZyCountMgr::GetPriorityZY(int nSrvIdx)
{
m_zyLock.Lock();
tagZhenying priorZy = zyNone;
for (INT_PTR i = 0; i < m_vecZyDist.count(); i++)
{
PlayerZYDistribute& dist = m_vecZyDist[i];
if (nSrvIdx == dist.m_nServerIdx)
{
INT_PTR nCount = 0x7FFFFFFF;
for (INT_PTR j = zyNone+1; j < zyMax; j++)
{
if (dist.m_anPlayerCount[j] < nCount)
{
priorZy = (tagZhenying)j;
nCount = dist.m_anPlayerCount[j];
}
}
}
}
if (priorZy == zyNone)
priorZy = zyWuJi;
m_zyLock.Unlock();
return priorZy;
}
int CJobZyCountMgr::GetOptionalZy(int nSrvIdx)
{
m_zyLock.Lock();
int nOptMask = 7; // all zy are optional
for (INT_PTR i = 0; i < m_vecZyDist.count(); i++)
{
PlayerZYDistribute& dist = m_vecZyDist[i];
if (nSrvIdx == dist.m_nServerIdx)
{
INT_PTR nTotalCount = 0;
for (INT_PTR i = zyNone+1; i < zyMax; i++)
nTotalCount += dist.m_anPlayerCount[i];
if (nTotalCount > 0)
{
float nRate;
for (INT_PTR j = zyNone+1; j < zyMax; j++)
{
nRate = (dist.m_anPlayerCount[j] / (float)nTotalCount);
if (nRate > 0.35)
{
nOptMask &= ~(1 << (j-1));
}
}
}
}
}
m_zyLock.Unlock();
return nOptMask;
}
bool CJobZyCountMgr::IsActorNameExist(char* sName,int nServerindex)
{
if(sName )
{
for(int i=0;i<m_vecNameDist.count();i++)
{
PlayerNameDistribute* nameDist = &m_vecNameDist[i];
if((nServerindex <0 || nServerindex == nameDist->nServerIdx) && strcmp(sName,nameDist->sName) == 0 )
{
return true;
}
}
}
else
{
return false;
}
return false;
}
void CJobZyCountMgr::ChangeNameToList(char* sName,char* srcName,int nServerIndex)
{
if(sName && srcName && nServerIndex > 0)
{
for(int i=0;i<m_vecNameDist.count();i++)
{
PlayerNameDistribute* nameDist = &m_vecNameDist[i];
if( strcmp(srcName,nameDist->sName) == 0 && nServerIndex == nameDist->nServerIdx)
{
_asncpytA(nameDist->sName,sName);
break;
}
}
}
else if(!srcName && sName)
{
PlayerNameDistribute nameDist;
nameDist.nServerIdx = nServerIndex;
_asncpytA(nameDist.sName,sName);
m_vecNameDist.add(nameDist);
}
}
/*
int CJobZyCountMgr::GetStrLenUtf8(LPCTSTR sName)
{
LPCSTR sptr;
int nLen = 0;
unsigned int ch;
for ( sptr = sName; *sptr; ++sptr )
{
ch = (unsigned int)*sptr;
if ( ch >= 0x7F )
{
sptr += 2;//UTF-8,留意++sptr
}
nLen++;
}
return nLen;
}
*/

View File

@@ -0,0 +1,159 @@

/*
*用于管理游戏里职业和阵营的平衡
*比如战士、法师、道士,在随机选择的时候选择最小的推荐给玩家,避免职业失衡
*同样的是阵营的,在游戏初始化的时候装载,每添加一条记录在内存里更新,定期存盘一次
*避免每次查询职业的平衡都去数据表里查找
*/
#pragma once
// 玩家阵营分布
struct PlayerZYDistribute
{
PlayerZYDistribute()
{
Reset();
}
void Reset()
{
/*m_nServerIdx = 0;
for (INT_PTR i = 0; i < zyMax; i++)
m_anPlayerCount[i] = -1;*/
ZeroMemory(this, sizeof(*this));
}
INT_PTR m_nServerIdx; // 服务器Id
INT_PTR m_anPlayerCount[zyMax]; // 记录三个阵营的玩家数量
};
// 玩家职业分布
struct PlayerJobDistribute
{
PlayerJobDistribute()
{
Reset();
}
void Reset()
{
/*m_nServerIdx = 0;
for (INT_PTR i = 0; i < enMaxVocCount; i++)
m_anPlayerCount[i] = -1;*/
ZeroMemory(this, sizeof(*this));
}
INT_PTR m_nServerIdx; // 服务器Id
INT_PTR m_anPlayerCount[enMaxVocCount]; // 记录各个职业的玩家数量
};
struct PlayerNameDistribute
{
int nServerIdx; // 服务器Id
int guildid; //
char sName[32]; // 记录各个职业的玩家数量
PlayerNameDistribute()
{
ZeroMemory(this, sizeof(*this));
}
};
class CJobZyCountMgr
{
public:
CJobZyCountMgr();
//设置参数
void SetParam(CSQLConenction* pSql)
{
m_SQLConnection = pSql;
}
// DB服务器启动的时候自动加载玩家阵营分布数据
VOID LoadZyInitData();
// 保存玩家阵营分布数据(定时保存)
VOID SaveZyData();
// 新玩家创号
void OnNewPlayerCreated(int nSrvIdx, tagZhenying zy, tagActorVocation voc,char sName[32]);
//当新行会创建的时候
void OnNewGuildNameCreate(int nSrvIdx, char *sName, int nGuildId);
// DB服务器启动的时候自动加载玩家职业分布数据
VOID LoadJobInitData();
// 保存玩家职业分布数据(定时保存)
VOID SaveJobData();
// 获取优选职业(当前最少的职业)
int GetPriorityJob(int nSrvIdx);
// 获取可以选择的阵营阵营人数低于35%的才能选择),返回按位的掩码
int GetOptionalZy(int nSrvIdx);
// 获取优选阵营(当前最少的阵营)
tagZhenying GetPriorityZY(int nSrvIdx);
//是否装载了职业数据
bool HasLoadJobData()
{
return m_bLoadJobData ;
}
//是否装载了正营数据
bool HasLoadZyData()
{
return m_bLoadZyData;
}
//是否装载了玩家名称数据
bool HasLoadActorNameData()
{
return m_bLoadNameData;
}
// DB服务器启动的时候自动加载玩家名称数据
void LoadActorNameInitData();
//装载行会列表
void LoadGuildNameInitData();
//判断是否名称已存在,如果判断在所有的几个服就输入-1
bool IsActorNameExist(char* sName,int nServerindex=-1);
//修改名字
void ChangeNameToList(char* sName,char* srcName,int nServerIndex);
//名字是否存在
bool IsGuildNameExist(char* sName,int nServerindex=-1);
//删除行会
bool RemoveGuildById(int Guild);
//int GetStrLenUtf8(LPCTSTR sName);
private:
// 用于创建角色选择阵营和职业
bool m_bLoadJobData;// 是否已经加载了初始的阵营、职业分布数据针对DB断开重连的情况
bool m_bLoadZyData;// 是否已经加载了初始的阵营、职业分布数据针对DB断开重连的情况
wylib::container::CBaseList<PlayerZYDistribute> m_vecZyDist; // 玩家阵营分布
wylib::container::CBaseList<PlayerJobDistribute> m_vecJobDist; // 玩家职业分布
bool m_bZyDataDirty;
bool m_bJobDataDirty;
CCSLock m_zyLock;
CCSLock m_jobLock;
CSQLConenction* m_SQLConnection; //数据库连接对象
wylib::container::CBaseList<PlayerNameDistribute> m_vecNameDist; // 已使用的玩家名称
wylib::container::CBaseList<PlayerNameDistribute> m_guildNameDist; //已使用过的行会的名称
bool m_bLoadNameData;// 是否已经加载了初始的玩家名称数据
bool m_bLoadGuildNameData; //是否装载过行会数据
CCSLock m_nameLock;
CCSLock m_guildNameLock; //行会名字的锁
};

View File

@@ -0,0 +1,88 @@

#include "StdAfx.h"
#include "wrand.h"
CLoadString::CLoadString()
{
}
CLoadString::~CLoadString()
{
}
INT_PTR CLoadString::loadFromFile( LPCSTR sFileName )
{
if (m_FileStream.loadFromFile(sFileName) <= 0)
return 0;
LPCTSTR sPtr = (LPCTSTR)m_FileStream.getMemory();
LPCTSTR sTag;
//跳过 UTF8 文件的头三个字节BOM
BYTE *pHead = (BYTE*)sPtr;
if (pHead[0]==0xEF && pHead[1]==0xBB && pHead[2]==0xBF)
{
sPtr += 3;
}
while (*sPtr)
{
//跳过行首的空白字符
while (*sPtr && (unsigned int)*sPtr <= 0x20)
sPtr++;
//将名字指针添加到名字列表中
if (*sPtr)
{
add(sPtr);
}
//搜索换行符
sTag = _tcschr(sPtr, '\n');
if (sTag)
{
*(LPTSTR)(sTag - 1) = 0; //把 '\r'也填充0
*(LPTSTR)sTag = 0;
sTag++;
//跳过行尾的空白字符
while (*sTag && (unsigned int)*sTag <= 0x20)
{
*(LPTSTR)sTag = 0;
sTag++;
}
if (*sTag)
{
sPtr = sTag;
}
}
if (NULL == sTag || !(*sTag))
{
break;
}
}
//重新填充名称使用情况指针
INT_PTR nCount = count();
OutputMsg(rmNormal, _T("加载了%s数量%d"), sFileName, nCount);
return nCount;
}
bool CLoadString::GetName(LPCSTR & sName, INT_PTR nIdx)
{
if (nIdx < 0 || nIdx >= count())
{
return false;
}
sName = (*this)[nIdx];
return true;
}
const char * CLoadString::GetRandomName()
{
INT_PTR nCount = count();
if (nCount <= 0)
{
return NULL;
}
INT_PTR nRandomVal = wrand((unsigned long)nCount);
return (*this)[nRandomVal];
}

View File

@@ -0,0 +1,25 @@

#pragma once
class CLoadString :
public wylib::container::CBaseList<LPCTSTR>
{
protected:
typedef wylib::container::CBaseList<LPCTSTR> Inherited;
public:
CLoadString();
~CLoadString();
INT_PTR Count()
{
return count();
}
INT_PTR loadFromFile(LPCSTR sFileName);
bool GetName(LPCSTR & sName, INT_PTR nIdx);
const char * GetRandomName();
private:
wylib::stream::CMemoryStream m_FileStream;
};

View File

@@ -0,0 +1,231 @@
#include "StdAfx.h"
#include "FeeDb.h"
CLogicDBReqestHandler::CLogicDBReqestHandler()
{
m_pHugeSQLBuffer = (PCHAR)m_Allocator.AllocBuffer(dwHugeSQLBufferSize);
}
CLogicDBReqestHandler::~CLogicDBReqestHandler()
{
m_Allocator.FreeBuffer(m_pHugeSQLBuffer);
}
CDataPacket& CLogicDBReqestHandler::allocProtoPacket(const jxSrvDef::INTERSRVCMD nCmd)
{
return m_pHost->AllocDataPacket(nCmd);
}
void CLogicDBReqestHandler::flushProtoPacket(CDataPacket &packet)
{
m_pHost->FlushDataPacket(packet);
}
//int CLogicDBReqestHandler::getClientServerIndex()
//{
// return m_pHost->GetClientServerIndex();
//}
void CLogicDBReqestHandler::ExecuInitDb(CDataPacketReader &inPacket)
{
DECLARE_FUN_TIME_PROF()
int nRawServerId = 0;
inPacket >> nRawServerId;
if (m_pSQLConnection->Connected())
{
int nError = m_pSQLConnection->Exec(szSQL_InitDB, nRawServerId);
if (!nError)
{
m_pSQLConnection->ResetQuery();
}
}
}
void CLogicDBReqestHandler::Trace ()
{
OutputMsg(rmNormal,"---CLogicDBReqestHandler memory start---");
CBufferAllocator::ALLOCATOR_MEMORY_INFO memoryInfo;
m_Allocator.GetMemoryInfo(&memoryInfo);
OutputMsg(rmNormal,"super alloc=%d,free=%d",(int)memoryInfo.SuperBuffer.dwAllocSize,(int)memoryInfo.SuperBuffer.dwFreeSize);
OutputMsg(rmNormal,"large alloc=%d,free=%d",(int)memoryInfo.LargeBuffer.dwAllocSize,(int)memoryInfo.LargeBuffer.dwFreeSize);
OutputMsg(rmNormal,"middle alloc=%d,free=%d",(int)memoryInfo.MiddleBuffer.dwAllocSize,(int)memoryInfo.MiddleBuffer.dwFreeSize);
OutputMsg(rmNormal,"small alloc=%d,free=%d",(int)memoryInfo.SmallBuffer.dwAllocSize,(int)memoryInfo.SmallBuffer.dwFreeSize);
OutputMsg(rmNormal,"---CLogicDBReqestHandler memory end---");
}
void CLogicDBReqestHandler::OnResponseDbSessionData(CDataPacketReader &inPacket)
{
unsigned int nSessionId=0,nActorId=0;
inPacket >> nSessionId;
inPacket >> nActorId;
//////GetGlobalDBEngine()->getGateManager()->PostLogicResponseSessionData(nSessionId, nActorId);
}
void CLogicDBReqestHandler::UpdateLogicGateUserInfo(CDataPacketReader &inPacket)
{
GetGlobalDBEngine()->UpdateLogicGateUserInfo(inPacket);
}
void CLogicDBReqestHandler::LogicSendStopDbServerCmd(CDataPacketReader &inPacket)
{
if(GetGlobalDBEngine())
{
GetGlobalDBEngine()->SetDbStartFlag(false);
}
}
void CLogicDBReqestHandler::OnReloadCrossConfig(CDataPacketReader &inPacket)
{
/*
if(GetGlobalDBEngine())
{
char szAddr[128];
szAddr[0]=0;
int nPort=0;
int nServerIndex =0;
int nRawServerIndex =0;
inPacket >> nServerIndex >> nRawServerIndex;
inPacket.readString(szAddr,sizeof(szAddr));
inPacket >> nPort;
CDBCenterClient* pClient = GetGlobalDBEngine()->getDBCenterClient();
if(pClient ==NULL)
{
OutputMsg(rmError,"CDBCenterClient is NULL");
return;
}
OutputMsg(rmTip,"serverindex=%d,dbcenter=%s,port=%d ",nRawServerIndex,szAddr?szAddr:"",nPort);
//如果当前正在连接
if(pClient->connected())
{
//如果不需要改变,则不改变
if(pClient->GetServerPort() == nPort && strcmp( pClient->GetServerHost(),szAddr)==0 )
{
OutputMsg(rmTip,"No need change,port=%d,add=%s",nPort,szAddr);
return;
}
else
{
pClient->Inherited::Stop();
if(nPort >0)
{
GetGlobalDBEngine()->SetDBCenterAddress(szAddr, nPort);
pClient->Inherited::Startup();
}
return;
}
}
else
{
GetGlobalDBEngine()->SetDBCenterAddress(szAddr, nPort);
pClient->Inherited::Startup();
return;
}
}
*/
}
void CLogicDBReqestHandler::LoadFee(CDataPacketReader &inPacket, unsigned int nActorID, int nRawServerId, int nLoginServerId)
{
CDataPacket& out = allocProtoPacket(dcLoadFee);
ACCOUNT sAccount;
out << nRawServerId << nLoginServerId;
out << nActorID;
inPacket.readString(sAccount,sizeof(sAccount));
//数据库连接是否就绪
if ( !m_pSQLConnection->Connected() )
{
out << (BYTE)reDbErr;
}
else
{
int nError = m_pSQLConnection->Query("call loadfee_actor(%d,%d,\"%s\");", nRawServerId, nActorID, sAccount);
if ( !nError )
{
out << (BYTE)reSucc;
if (MYSQL_ROW pRow = m_pSQLConnection->CurrentRow())
{
int nCount = m_pSQLConnection->GetRowCount();
INT_PTR pos = out.getPosition();
out << (int)0;
nCount = 0;
FeeData feedata;
char token[64];
do
{
nCount++;
sscanf(pRow[0], "%u", &feedata.nId);
sscanf(pRow[1], "%s", &feedata.sPf);
sscanf(pRow[2], "%u", &feedata.nActorId);
sscanf(pRow[4], "%s", &feedata.sProdId);
sscanf(pRow[5], "%u", &feedata.nNum);
strlcpy((feedata.sAccount), (pRow[3]? pRow[3] : ""), sizeof(feedata.sAccount));
strlcpy((token), (pRow[6]? pRow[6] : ""), sizeof(token));
OutputMsg(rmTip,_T("[Fee]1 请求充值数据: Id%dPfId(%s), ActorId%dAccount%sProdId%sToken%s"),
feedata.nId, feedata.sPf, feedata.nActorId, feedata.sAccount, feedata.sProdId, token
);
out.writeBuf(&feedata, sizeof(FeeData));
}
while(pRow = m_pSQLConnection->NextRow());
int* pCount = (int*)out.getPositionPtr(pos);
*pCount = nCount;
}
m_pSQLConnection->ResetQuery();
}
else
{
out << (BYTE)reDbErr;
}
}
flushProtoPacket(out);
}
void CLogicDBReqestHandler::DelFee(CDataPacketReader &inPacket, unsigned int nActorID, int nRawServerId, int nLoginServerId)
{
DECLARE_TIME_PROF("CLogicDBReqestHandler::DelFee");
//数据库连接是否就绪
if ( !m_pSQLConnection->Connected() )
{
return;
}
else
{
int nCount = 0;
inPacket >> nCount;
if (nCount > 0)
{
char buff[16];
strcpy(m_pHugeSQLBuffer,"update feecallback set flag = 999 where id in ");
unsigned int nId = 0;
strcat(m_pHugeSQLBuffer, " (");
bool isFirst = true;
for (size_t i = 0; i < nCount; i++)
{
inPacket >> nId;
if(isFirst) { sprintf(buff, "%u", nId); isFirst = false;}
else { sprintf(buff, ",%u", nId); }
strcat(m_pHugeSQLBuffer, buff);
OutputMsg(rmTip,_T("[Fee]3 完成充值: Id%dActorId%d"),nId,nActorID);
}
strcat(m_pHugeSQLBuffer, " )");
int nErrorCode = m_pSQLConnection->Exec(m_pHugeSQLBuffer);
if(!nErrorCode)
{
m_pSQLConnection->ResetQuery();
}
else
{
OutputMsg(rmError,"feecallback Finish Error,errorCode=%d,sql=%s", nErrorCode,m_pHugeSQLBuffer);
}
}
}
}

View File

@@ -0,0 +1,399 @@
#ifndef LOGIC_DB_REQUEST_HANDLER_H_
#define LOGIC_DB_REQUEST_HANDLER_H_
struct CUserItem;
struct tagOneSkillDbData;
/*
逻辑DB请求处理类。
*/
// Forward Declaration
class CSQLConenction;
class ILogicDBRequestHost;
class CLogicDBReqestHandler
{
public:
CLogicDBReqestHandler();
~CLogicDBReqestHandler();
public:
inline void SetSQLConnection(CSQLConenction *pSQLConn) { m_pSQLConnection = pSQLConn; }
inline CSQLConenction* GetSqlConnection() {return m_pSQLConnection;}
inline void SetRequestHost(ILogicDBRequestHost *pHost) { m_pHost = pHost; }
//追踪内存使用情况
void Trace ();
///*
//* Comments: 获取连接对端的ServerId
//* @Return int:
//* @Remark:
//*/
//int getClientServerIndex();
//////////////////////////////////////////////////////////////////////////
// 杂DB请求处理
//////////////////////////////////////////////////////////////////////////
void ExecuInitDb(CDataPacketReader &inPacket);
void OnResponseDbSessionData(CDataPacketReader &inPacket);
void UpdateLogicGateUserInfo(CDataPacketReader &inPacket);
void LogicSendStopDbServerCmd(CDataPacketReader &inPacket);
void OnReloadCrossConfig(CDataPacketReader &inPacket);
//////////////////////////////////////////////////////////////////////////
// 角色基本数据相关的DB请求处理
//////////////////////////////////////////////////////////////////////////
void SaveActorCustomInfo(CDataPacketReader& inPacket);//保存自定义数据
void QueryActorCustomInfo(CDataPacketReader& inPacket);//查询自定义数据
void QueryActorCustomInfoUnForbid(CDataPacketReader& inPacket);
void SaveActorCustomInfoUnForbid(CDataPacketReader& inPacket);//保存自定义数据
void QueryActorCustomInfoCustomTitleId(CDataPacketReader& inPacket);
void SaveActorCustomInfoCustomTitleId(CDataPacketReader& inPacket);//保存自定义数据
unsigned int QueryActorFromDB(CDataPacketReader &inPacket);
void QueryActoSubSystemData(CDataPacketReader &inPacket);
void SaveOfflineActorProperty(CDataPacketReader& inPacket);
void QueryOfflineUserInfo(CDataPacketReader &inPacket);
void QueryOfflineUserHeroInfo(CDataPacketReader &inPacket);
void SaveActorToDB(CDataPacketReader &inPacket, bool bResp = true);
void UpdateChallengeData(CDataPacketReader &inPacket);
void QueryActorExists(CDataPacketReader & inPacket);
void UpdateCharStatus(CDataPacketReader & inPacket);
void UpdateCharOnlineStatus(unsigned int nActorId, int nStatus);
void ChangeActorTradingQuota(CDataPacketReader & inPacket);// 修改玩家交易额度
//计数器
void LoadCircleCount();
void LoadActorStaticCounts(unsigned int nActorId, unsigned int nRawServerId, unsigned int nLoginServerId);
void SaveActorStaticCounts(CDataPacketReader& packet);
//强化
void QueryStrengthenImpl(MYSQL_ROW pRow, CDataPacket& OutPacket);
void LoadActorStrengthenInfo( unsigned int nActorID,unsigned int nRawServerId,unsigned int nLoginServerId);
void SaveActorStrengthenInfo(CDataPacketReader& packet);
//圣物dcSaveHallowsSystemInfo
void SaveHallowsSystemInfo(CDataPacketReader& packet);
void LoadHallowsSystemInfo(CDataPacketReader& packet);
//复活特权
void LoadReviveDurationSystemInfo(CDataPacketReader& packet);
void SaveReviveDurationSystemInfo(CDataPacketReader& packet);
//宠物
void QueryLootPetData(unsigned int nActorId, unsigned int nRawServerId, unsigned int nLoginServerId);
void SaveLootPetToDB(CDataPacketReader& packet, bool bResp = true);
//返利活动
void QueryRebateData(CDataPacketReader& packet);
void QueryNextDayRebateData(CDataPacketReader& packet);
void UpdateRebateData(CDataPacketReader& packet);
void SaveRebateToDB(CDataPacketReader& packet);
void ClearRebateData(CDataPacketReader& packet);
//跨服
void LoadCrossGuildId(CDataPacketReader& packet);
//成就
void LoadActorAchieveMentInfo(unsigned int nActorId, unsigned int nRawServerId, unsigned int nLoginServerId);
void SaveActorAchieveMentInfo(CDataPacketReader& packet);
void LoadOfflineAchieveMentInfo(CDataPacketReader& packet);
void SaveOfflineAchieveMentInfo(CDataPacketReader& packet);
void SaveActorGhost(CDataPacketReader& packet);
void LoadActorGhost(CDataPacketReader& packet);
//////////////////////////////////////////////////////////////////////////
// 背包物品以及活动背包相关的DB请求处理
//////////////////////////////////////////////////////////////////////////
void QueryItemsImpl(MYSQL_ROW pRow, CUserItem& data);
void QueryItems(unsigned int nActorID, unsigned int nItemStoreType, int nRawServerId, int nLoginServerId);
void SaveItems(CDataPacketReader &inPacket, bool bResp = true);
void LoadUserActiveItem(CDataPacketReader &inPacket);
void GetUserActiveItem(CDataPacketReader &inPacket);
void RemoveUserActiveItem(CDataPacketReader &inPacket);
//衣橱系统保存
void SaveAlmirahItem(CDataPacketReader & inPacket, bool bResp = true);
void LoadAlmirahItem(unsigned int nActorId, int nRawServerId, int nLoginServerId);
//////////////////////////////////////////////////////////////////////////
// 游戏设置相关的db 请求处理
//////////////////////////////////////////////////////////////////////////
void QueryOtherGameSetsFromDB(unsigned int nActorID, int nRawServerId, int nLoginServerId);
void SaveOtherGameSetsToDB(CDataPacketReader &inPacket, bool bResp = true);
//////////////////////////////////////////////////////////////////////////
// 技能相关的DB请求处理
//////////////////////////////////////////////////////////////////////////
void QuerySkillImpl(MYSQL_ROW pRow, tagOneSkillDbData& data);
void QuerySkillFromDB(unsigned int nActorID, int nRawServerId, int nLoginServerId);
void SaveSkillToDB(CDataPacketReader &inPacket, bool bResp = true);
//////////////////////////////////////////////////////////////////////////
// 任务相关的DB请求处理
//////////////////////////////////////////////////////////////////////////
void QueryQuestFromDB(CDataPacketReader &inPacket);
void SaveQuestToDB(CDataPacketReader &inPacket, bool bResp = true);
//////////////////////////////////////////////////////////////////////////
// 脚本数据相关的DB请求处理
//////////////////////////////////////////////////////////////////////////
void QueryActorScriptData(CDataPacketReader &inPacket);
void QueryActorScriptData(unsigned int nActorId, int nRawServerId, int nLoginServerId);
void SaveScriptDataToDB(CDataPacketReader &inPacket, bool bResp = true);
//////////////////////////////////////////////////////////////////////////
// 公会相关的DB请求处理
//////////////////////////////////////////////////////////////////////////
void LoadGuildList(CDataPacketReader &inPacket);
void LoadGuildDetail(CDataPacketReader &inPacket);
void AddGuild(CDataPacketReader &inPacket);
void LoadGuildSkillDb(CDataPacketReader &inPacket);
void DeleteMember(CDataPacketReader &inPacket);
void SaveActorGuild(CDataPacketReader &inPacket, bool bResp = true);
void LoadActorGuild(unsigned int nActorid);
void AddGuildMember(CDataPacketReader &inPacket);
void InitGuildSkillInfo(CDataPacketReader &inPacket);
void SaveGuildSkill(CDataPacketReader &inPacket);
void SaveGuildEventDb(CDataPacketReader &inPacket);
void LoadGuildEventDb(CDataPacketReader &inPacket);
void SaveGuild(CDataPacketReader &inPacket);
void DeleteGuild(CDataPacketReader &inPacket);
void AddMemberOffLine(CDataPacketReader &inPacket);
void SaveGuildDepotDb(CDataPacketReader &inPacket);
void LoadGuildDepoyFromDb(CDataPacketReader &inPacket);
void LoadGuildDepotRecordDb(CDataPacketReader &inPacket);
void SaveGuildDepotRecordDb(CDataPacketReader &inPacket);
void LoadActorBuildingDb(CDataPacketReader &inPacket);
void LoadGuildApplyList(CDataPacketReader &inPacket);
void DealGuildApply(CDataPacketReader &inPacket);
void LoadActorApplyResult(CDataPacketReader &inPacket);
void SaveActorApplyResult(CDataPacketReader &inPacket);
//////////////////////////////////////////////////////////////////////////
// 活动相关的DB请求处理
//////////////////////////////////////////////////////////////////////////
void LoadActivityList(CDataPacketReader &inPacket);
void SaveActivityList(CDataPacketReader &inPacket);
void LoadActorActivity(CDataPacketReader &inPacket, unsigned int nActorID, int nRawServerId, int nLoginServerId);
void SaveActorActivity(CDataPacketReader &inPacket, unsigned int nActorID, int nRawServerId, int nLoginServerId);
//////////////////////////////////////////////////////////////////////////
// boss相关的DB请求处理
//////////////////////////////////////////////////////////////////////////
void LoadBossList(CDataPacketReader &inPacket);
void SaveBossList(CDataPacketReader &inPacket);
void LoadActorBossList(CDataPacketReader &inPacket, unsigned int nActorID, int nRawServerId, int nLoginServerId);
void SaveActorBossList(CDataPacketReader &inPacket, unsigned int nActorID, int nRawServerId, int nLoginServerId);
//////////////////////////////////////////////////////////////////////////
// 消息相关的DB请求处理
//////////////////////////////////////////////////////////////////////////
void LoadMsgListFromId(unsigned int nActorId,INT64 nMsgId, int nRawServerId, int nLoginServerId);
void LoadMsgList(CDataPacketReader &inPacket);
void DeleteMsg(CDataPacketReader &inPacket);
void AddMsg(CDataPacketReader &inPacket);
void AddMsgByName(CDataPacketReader &inPacket);
//////////////////////////////////////////////////////////////////////////
// 好友相关的DB请求处理
//////////////////////////////////////////////////////////////////////////
int SaveFriendsData(unsigned int nActorid,int nRsType,int nFriendId,LPCSTR szName,UINT nParam);
void SaveFriends(CDataPacketReader &inPacket, bool bResp = true);
void LoadFriends(CDataPacketReader &inPacket);
int CleanFriends(unsigned int nActorid);
//////////////////////////////////////////////////////////////////////////
// 宠物相关的DB请求处理
//////////////////////////////////////////////////////////////////////////
void QueryPetData(unsigned int nActorID, int nRawServerId, int nLoginServerId);
void QueryPetDetailData(CDataPacketReader &inPacket); //装载宠物的装备/技能等数据
void QueryPetSkillData(unsigned int nActorID, int nRawServerId, int nLoginServerId);
void SavePetSkillData(CDataPacketReader &inPacket, bool bResp = true); //保存宠物的技能数据
void SavePetToDB(CDataPacketReader &inPacket, bool bResp = true);
//////////////////////////////////////////////////////////////////////////
// 头衔相关的DB请求处理
//////////////////////////////////////////////////////////////////////////
void LoadBaseRank(CDataPacketReader &inPacket);
void SaveBaseRank(CDataPacketReader &inPacket);
void SaveBaseRankCS(CDataPacketReader &inPacket);//跨服的排行榜保存数据
//////////////////////////////////////////////////////////////////////////
// 关系相关的DB请求处理
//////////////////////////////////////////////////////////////////////////
void QueryRelationData(unsigned int nActorId, int nRawServerId, int nLoginServerId);
void SaveRelation(CDataPacketReader &inPacket);
//////////////////////////////////////////////////////////////////////////
// 战力排行榜
//////////////////////////////////////////////////////////////////////////
VOID LoadActorCombatRank(CDataPacketReader &inPacket);
VOID LoadActorCombatGameInfo(CDataPacketReader &inPacket);
VOID UpdateActorCombatAward(CDataPacketReader &inPacket);
VOID SaveActorCombatGameInfo(CDataPacketReader &inPacket);
VOID LoadCombatRecord(CDataPacketReader &inPacket);
VOID SaveCombatRecordToDb(CDataPacketReader &inPacket);
//////////////////////////////////////////////////////////////////////////
// 职业宗师竞技
//////////////////////////////////////////////////////////////////////////
VOID LoadActorCombatBaseInfo(CDataPacketReader &inPacket);
VOID SaveActorCombatBaseInfo(CDataPacketReader &inPacket);
VOID LoadActorCombatLog(CDataPacketReader &inPacket);
VOID SaveActorCombatLog(CDataPacketReader &inPacket);
//////////////////////////////////////////////////////////////////////////
// 好友等
//////////////////////////////////////////////////////////////////////////
VOID LoadActorFriendsData(CDataPacketReader &inPacket);
VOID LoadActorFriendsData(unsigned int nActorID, int nRawServerId, int nLoginServerId);
VOID SaveActorFriendsData(CDataPacketReader &inPacket);
VOID LoadActorDeathData(unsigned int nActorID, int nRawServerId, int nLoginServerId);
VOID LoadActorDeathData(CDataPacketReader &inPacket);
VOID SaveActorDeathData(CDataPacketReader &inPacket);
VOID LoadActorDeathDropData(CDataPacketReader &inPacket);
VOID SaveActorDeathDropData(CDataPacketReader &inPacket);
VOID DeleteActorFriendData(CDataPacketReader &inPacket);
VOID AddFriendChatMsg(CDataPacketReader &inPacket);
VOID LoadFriendChatMsgData(CDataPacketReader &inPacket);
VOID LoadFiendOfflineData(CDataPacketReader &inPacket);
//后台操作
VOID AddFilterWordsDbMsg(CDataPacketReader &inPacket);
VOID BackRemoveItem(CDataPacketReader &inPacket);
VOID BackRemoveMoney(CDataPacketReader &inPacket);
VOID LoadTopLevelActorData(CDataPacketReader &inPacket);
VOID LoadTopLevelActorOneData(CDataPacketReader& inPacket);//世界等级查询
VOID LoadActorConsumeRank(CDataPacketReader &inPacket);
VOID LoadActorTopicBattle(CDataPacketReader &inPacket);
VOID LoadActorSwingLevelData(CDataPacketReader &inPacket);
VOID LoadActorHeroTopicRankData(CDataPacketReader &inPacket);
VOID LoadAllActivityData(CDataPacketReader &inPacket);
VOID LoadCombineLevelActorData(CDataPacketReader &inPacket);
VOID LoadCombineBattleActorData(CDataPacketReader &inPacket);
VOID LoadActorGameSetData(CDataPacketReader &inPacket);
VOID SaveActorGameSetData(CDataPacketReader &inPacket);
//////////////////////////////////////////////////////////////////////////
// 邮件
//////////////////////////////////////////////////////////////////////////
void QueryActorMail(unsigned int nActorID, int nRawServerId, int nLoginServerId);
void AddActorOfflineMail(CDataPacketReader & inPacket);
void SaveActorMail(CDataPacketReader & inPacket, bool bResp = true);
void LoadActorMail(CDataPacketReader & inPacket);
void LoadNewServerMail(int nServerId, int nRawServerId, int nMaxServerMailId);
void AddNewServerMail(CDataPacketReader & inPacket);
void SaveNewServerMail(CDataPacketReader & inPacket);
VOID LoadActorNewTitleData(CDataPacketReader &inPacket);
VOID SaveActorNewTitleData(CDataPacketReader &inPacket);
VOID LoadActorCustomTitleData(CDataPacketReader &inPacket);
VOID SaveActorCustomTitleData(CDataPacketReader &inPacket);
//寄卖
void SaveActorConsignment(CDataPacketReader &inPacket);//保存玩家的
void SaveConsignmentItem(CDataPacketReader &inPacket);//保存系统的,分包
//void SaveConsignmentIncome(CDataPacketReader &inPacket);
void LoadConsignmentItem(CDataPacketReader &inPacket);
void LoadConsignmentIncome(CDataPacketReader &inPacket);
//充值
void LoadFee(CDataPacketReader &inPacket, unsigned int nActorID, int nRawServerId, int nLoginServerId);
void DelFee(CDataPacketReader &inPacket, unsigned int nActorID, int nRawServerId, int nLoginServerId);
//称号
void QueryActorNewTitle(unsigned int nActorId, int nRawServerId, int nServerId);
void QueryActorCustomTitle(unsigned int nActorId, int nRawServerId, int nServerId);
void QueryActorWarChariot(unsigned int nActorId, int nRawServerId, int nServerId);
private:
//////////////////////////////////////////////////////////////////////////
// 申请和投递消息数据包
//////////////////////////////////////////////////////////////////////////
/*
* Comments: 想宿主申请一个数据包,用于发送处理结果
* Param const jxSrvDef::INTERSRVCMD nCmd:
* @Return CDataPacket&:
* @Remark:
*/
CDataPacket& allocProtoPacket(const jxSrvDef::INTERSRVCMD nCmd);
/*
* Comments: 投递数据包到宿主发送队列
* Param CDataPacket & packet:
* @Return void:
* @Remark:
*/
void flushProtoPacket(CDataPacket &packet);
//////////////////////////////////////////////////////////////////////////
// 处理DB请求的内部实现函数
//////////////////////////////////////////////////////////////////////////
bool QueryOfflineUserBasicInfo(unsigned int nActorId, int nRawServerId, int nLoginServerId);
void QueryOfflineHeroInfo(unsigned int nActorId, unsigned int nHeroId, int nRawServerId, int nLoginServerId);
void QueryOfflineHeroEquips(unsigned int nActorID,unsigned int nHeroId, int nRawServerId, int nLoginServerId);
void QueryEquipedGemData(unsigned int nActorID, int nRawServerId, int nLoginServerId);
int SaveGoingQuest(unsigned int nActorid, int nTaskId, int id, int value);
int CleanQuestData(unsigned int nActorId);
int SaveRepeatQuest(unsigned int nActorid,int nTaskId, int qtime);
void QueryQuestFromDB(unsigned int nActorId, int nRawServerId, int nLoginServerId);
int GetGoingQuest(unsigned int nActorid, CDataPacket& out);
int GetRepeatQuest(unsigned int nActorid, CDataPacket& out);
void LoadFriends(unsigned int nActorId);
/*
* Comments:创建一个帮派成功后,调用本函数向逻辑服务器发送结果
* Param int nErr:错误码
* Param int index:消息在队列中的索引
* Param Uint64 hHandle:创建这个帮派的角色的handle以方便向他发送结果提示语
* Param int nGid:创建成功的话这个是帮派的id号
* Param LPCSTR sGuildName:帮派名称
* Param LPCSTR sFoundName:创始人名称
* Param BYTE nZY:阵营编号
* @Return VOID:
*/
void SendAddGuildResult(int nRawServerId,
int nLoginServerId,
int nErr,
int index,
Uint64 hHandle,
unsigned int nGid,
LPCSTR sGuildName,
LPCSTR sFoundName,
BYTE nZY,
INT_PTR nIcon);
private:
CSQLConenction *m_pSQLConnection;
ILogicDBRequestHost *m_pHost;
CBufferAllocator m_Allocator; // 内存池
PCHAR m_pHugeSQLBuffer; // 大型SQL查询语句缓冲长度为dwHugeSQLBufferSize
static const SIZE_T dwHugeSQLBufferSize = 1024 * 1024 * 32;
};
#endif

View File

@@ -0,0 +1,42 @@
#ifndef LOGIC_DB_REQUEST_HOST_INTERFACE_H
#define LOGIC_DB_REQUEST_HOST_INTERFACE_H
/*
逻辑DB请求处理容器接口。派生类需要实现分配数据包对象和发送数据包接口用于
处理DB请求后给逻辑回的处理结果应答。
*/
class ILogicDBRequestHost
{
public:
/*
* Comments: 分配数据包
* Param const jxSrvDef::INTERSRVCMD nCmd:
* @Return CDataPacket&:
* @Remark:
*/
virtual CDataPacket& AllocDataPacket(const jxSrvDef::INTERSRVCMD nCmd) = 0;
/*
* Comments: 刷新数据包到发送队列
* Param CDataPacket &packet
* @Return void:
* @Remark:
*/
virtual void FlushDataPacket(CDataPacket &packet) = 0;
// 此函数用到DataClient里头的一些内容。暂时没有将内部消息导入到DBRequestHandler里头处理所以
// 暂时将次函数作为虚函数来实现。以后可以考虑在DBDataClient里头Post的内部消息也导入到Requesthandler
// 里头处理然后将所有相关的数据结构和实现都转移到RequestHandler里头
virtual int CatchCreateGuild(int nActor,
LPCSTR sGuildName,
LPCSTR sFoundName,
int nIndex,
Uint64 hActor,
BYTE nZY,
INT_PTR nIcon) = 0;
virtual int CatchRemoveGuild(int) = 0;
};
#endif

975
server/DBServer/MsgData.cpp Normal file
View File

@@ -0,0 +1,975 @@
#include "StdAfx.h"
#include<iostream>
#define MAIL_DATA_SEND_COUNT_EACH_TIME 50//每次发送的邮件数
#define MAILATTACH_DATA_SEND_COUNT_EACH_TIME 500//每次发送的附件数
#define LoadDbTypeServerMail 0
#define LoadDbTypeServerMailAttach 1
#define LoadDbTypeServerMailComplete 2
void CLogicDBReqestHandler::LoadMsgList(CDataPacketReader &inPacket)
{
int nRawServerId = 0, nLoginServerId = 0;
unsigned int nActorid = 0;
INT64 nMsgId = 0;
inPacket >> nRawServerId >> nLoginServerId >> nActorid;
inPacket >> nMsgId;
LoadMsgListFromId(nActorid, nMsgId, nRawServerId, nLoginServerId);
}
void CLogicDBReqestHandler::LoadMsgListFromId(unsigned int nActorId,INT64 nMsgId, int nRawServerId, int nLoginServerId)
{
DECLARE_FUN_TIME_PROF()
CDataPacket& tmp = allocProtoPacket(dcLoadMsg);
tmp << nRawServerId << nLoginServerId;
CDataPacket* out = &tmp;
(*out) << (unsigned int)nActorId;
//数据库连接是否就绪
if ( !m_pSQLConnection->Connected() )
{
(*out) << (BYTE)reDbErr ;
}
else
{
int nError = m_pSQLConnection->Query(szSQLSP_LoadCharMsgList, nActorId,nMsgId);
if ( !nError )
{
(*out) << (BYTE)reSucc ;
MYSQL_ROW pRow = m_pSQLConnection->CurrentRow();
int nCount = m_pSQLConnection->GetRowCount();
INT_PTR pos = out->getPosition();
(*out) << (WORD)0;
nCount = 0;
while ( pRow)
{
nCount++;
if (nCount > 100)
{
WORD* pCount = (WORD*)out->getPositionPtr(pos);
*pCount = (WORD)(nCount-1);
flushProtoPacket((*out));
CDataPacket& msgNew = allocProtoPacket(dcLoadMsg);
msgNew << nRawServerId << nLoginServerId;
out = &msgNew;
(*out) << (unsigned int)nActorId;
(*out) << (BYTE)reSucc;
pos = out->getPosition();
(*out) <<(WORD)0;
nCount = 1;
}
INT64 nMsgid = StrToInt64(pRow[0]);
int nMsgtype = _StrToInt(pRow[1]);
int nBufSize = LOWORD(nMsgtype);//大小是低字节
nMsgtype = HIWORD(nMsgtype); //消息类型是高字节
if (pRow[2] == NULL)
{
nBufSize = 0;
}
(*out) << (INT64)nMsgid;
(*out) << (BYTE)nMsgtype;
(*out) << (WORD)nBufSize;
if (pRow[2])
{
out->writeBuf(pRow[2],nBufSize);
}
pRow = m_pSQLConnection->NextRow();
}
WORD* pCount = (WORD*)out->getPositionPtr(pos);
*pCount = (WORD)nCount;
m_pSQLConnection->ResetQuery();
}
else
{
(*out) << (BYTE)reDbErr ;
}
}
flushProtoPacket(*out);
}
void CLogicDBReqestHandler::DeleteMsg(CDataPacketReader &inPacket)
{
DECLARE_FUN_TIME_PROF()
int nRawServerId = 0, nLoginServerId = 0;
INT64 msgid = 0;
unsigned int nActorId = 0;
inPacket >> nRawServerId >> nLoginServerId;
inPacket >> nActorId;
inPacket >> msgid;
CDataPacket& retPack = allocProtoPacket(dcDeleteMsg);
retPack << nRawServerId << nLoginServerId;
retPack << nActorId;
//数据库连接是否就绪
if ( !m_pSQLConnection->Connected() )
{
retPack << (BYTE)reDbErr ;
retPack << msgid;//如果失败了,要告诉逻辑服务器那条失败了
}
else
{
int nError = m_pSQLConnection->Exec(szSQLSP_DeleteCharMsg, nActorId,msgid);
if ( !nError )
{
m_pSQLConnection->ResetQuery();
retPack << (BYTE)reSucc ;
retPack << msgid;//如果失败了,要告诉逻辑服务器那条失败了
}
else
{
retPack << (BYTE)reDbErr ;
retPack << msgid;//如果失败了,要告诉逻辑服务器那条失败了
}
}
flushProtoPacket(retPack);
}
void CLogicDBReqestHandler::AddMsg(CDataPacketReader &inPacket)
{
DECLARE_FUN_TIME_PROF()
int nRawServerId = 0, nLoginServerId = 0;
unsigned int nActorId = 0,nSrcActorId = 0;
int nMsgType = 0;
int bufsize = 0;
inPacket >> nRawServerId >> nLoginServerId;
inPacket >> nActorId;
inPacket >> nSrcActorId;
inPacket >> nMsgType;
inPacket >> bufsize;
CDataPacket& retPack = allocProtoPacket(dcAddMsg);
retPack << nRawServerId << nLoginServerId;
retPack << nActorId;
retPack << nSrcActorId;
nMsgType = MAKELONG(bufsize,nMsgType);//a是低直接
//数据库连接是否就绪
if ( !m_pSQLConnection->Connected() )
{
retPack << (BYTE)reDbErr ;
}
else
{
char *ptr = m_pHugeSQLBuffer;
ptr += sprintf(ptr, szSQLSP_AddCharMsg, nActorId,nMsgType);
ptr[0] = '"';
ptr += 1;
ptr += mysql_escape_string(ptr, inPacket.getOffsetPtr(), bufsize);
ptr[0] = '"';
ptr[1] = ')';
ptr += 2;
int nError = m_pSQLConnection->RealQuery(m_pHugeSQLBuffer,ptr - m_pHugeSQLBuffer);
if ( !nError )
{
retPack << (BYTE)reSucc ;
MYSQL_ROW pRow = m_pSQLConnection->CurrentRow();
if (pRow)
{
INT64 Msgid = StrToInt64(pRow[0]);
retPack << (INT64)Msgid;
}
m_pSQLConnection->ResetQuery();
}
else
{
retPack << (BYTE)reDbErr ;
}
}
flushProtoPacket(retPack);
}
void CLogicDBReqestHandler::AddMsgByName(CDataPacketReader &inPacket)
{
DECLARE_FUN_TIME_PROF()
int nRawServerId = 0, nLoginServerId = 0;
int nSrcActorId = 0;
int nServerIdx = -1;
int nMsgType = 0;
int bufsize = 0;
ACTORNAME actorName;
inPacket >> nRawServerId >> nLoginServerId;
inPacket >> nSrcActorId;
inPacket >> nServerIdx;
inPacket.readString(actorName,ArrayCount(actorName));
inPacket >> nMsgType;
inPacket >> bufsize;
int actorId = 0;
CDataPacket& retPack = allocProtoPacket(dcAddMsgByActorName);
retPack << nRawServerId << nLoginServerId;
retPack.writeString(actorName);
retPack << (int)nSrcActorId;
nMsgType = MAKELONG(bufsize,nMsgType);//a是低直接
//数据库连接是否就绪
if ( !m_pSQLConnection->Connected() )
{
retPack << (BYTE)reDbErr ;
}
else
{
char *ptr = m_pHugeSQLBuffer;
ptr += sprintf(ptr, szSQLSP_AddCharMsgByName, nServerIdx, actorName,nMsgType);
ptr[0] = '"';
ptr += 1;
ptr += mysql_escape_string(ptr, inPacket.getOffsetPtr(), bufsize);
ptr[0] = '"';
ptr[1] = ')';
ptr += 2;
int nError = m_pSQLConnection->RealQuery(m_pHugeSQLBuffer, ptr - m_pHugeSQLBuffer);
if ( !nError )
{
retPack << (BYTE)reSucc ;
MYSQL_ROW pRow = m_pSQLConnection->CurrentRow();
if (pRow)
{
unsigned int nActorId = _StrToInt(pRow[0]);
INT64 Msgid = StrToInt64(pRow[1]);
retPack << (INT64)Msgid;
}
m_pSQLConnection->ResetQuery();
}
else
{
retPack << (BYTE)reDbErr ;
}
}
flushProtoPacket(retPack);
}
//邮件相关接口
void CLogicDBReqestHandler::AddActorOfflineMail(CDataPacketReader & inPacket)
{
unsigned int nActorId = 0, nSrcId = 0, nCreateDt = 0;
byte btState = 0, btIsDel = 0;
int nServerId = 0, nRawServerId = 0;
inPacket >> nRawServerId >> nServerId >> nActorId;
int nErrorCode = reSucc;
if (!m_pSQLConnection->Connect())
{
nErrorCode = reDbNotConnected;
}
else
{
sprintf(m_pHugeSQLBuffer, szSQLSP_SaveMail);
INT64 nMailId = 0;
char sTitle[200], sContent[600], sBuff[1024];
int nCurCount = 0;
strcat(m_pHugeSQLBuffer, "(");
inPacket >> nMailId >> nSrcId;
inPacket.readString(sTitle, ArrayCount(sTitle));
inPacket.readString(sContent, ArrayCount(sContent));
inPacket >> nCreateDt >> btState >> btIsDel;
char sRealContent[700];
mysql_escape_string(sRealContent,sContent,(unsigned long)strlen(sContent));
sprintf(sBuff,"%lld,%u,%u,\"%s\",\"%s\",%d,%d,%d)", nMailId,nActorId,nSrcId,sTitle,sRealContent,nCreateDt,btState,btIsDel);
strcat(m_pHugeSQLBuffer, sBuff);
nErrorCode = m_pSQLConnection->Exec(m_pHugeSQLBuffer);
if (!nErrorCode)
{
m_pSQLConnection->ResetQuery();
}
BYTE nMailAttachCount = 0;
inPacket >> nMailAttachCount;
if (nMailAttachCount > 0)
{
sprintf(m_pHugeSQLBuffer, szSQLSP_SaveMailAttach);
int nValue = 0;BYTE nType = 0;
for (int i = 0; i <nMailAttachCount ; i++)
{
strcat(m_pHugeSQLBuffer," (");
CUserItem data;
inPacket >> nType;
data << inPacket;
sprintf(sBuff,"%lld,%u,%d,%lld,", nMailId,nActorId, nType,data.series.llId); //mailid actotID,guid,type
strcat(m_pHugeSQLBuffer,sBuff);
//ItemId,QUALITY,strong
nValue = MAKELONG( data.wItemId, MAKEWORD( data.btQuality, data.btStrong));
sprintf(sBuff,"%d,%d,",nValue, data.wCount);//MAKELONG(data.wDura,data.wCount));
strcat(m_pHugeSQLBuffer,sBuff);
//wPackageType,btFlag,wHoles
nValue = MAKELONG( MAKEWORD( data.wPackageType, data.btFlag), 0);
sprintf(sBuff," %d,",nValue);
strcat(m_pHugeSQLBuffer,sBuff);
//BYTE bLostStar;BYTE bInSourceType;//铭刻等级WORD bStrongResereLevel;//保留(可使用)
nValue = MAKELONG( MAKEWORD( data.bLostStar, data.bInSourceType), data.wIdentifySlotNum); //bStrongResereLevel->wIdentifySlotNum
sprintf(sBuff,"%d,",nValue);
strcat(m_pHugeSQLBuffer,sBuff);
//data reserver
//MAKELONG(A,B) 这里A是低字节B是高字节类似 MAKEWORD
nValue = MAKELONG( data.nDropMonsterId, data.wStar ); //btSmithCount -> nDropMonsterId
sprintf(sBuff,"%d,%d,",data.nCreatetime.tv,nValue);
strcat(m_pHugeSQLBuffer,sBuff);
nValue= MAKELONG( MAKEWORD(data.btSharp, data.btDeportId), MAKEWORD(data.btHandPos, data.btLuck));
sprintf(sBuff,"%d,%d,%d,%d,%d,%d,%d",data.smithAttrs[0],data.smithAttrs[1],data.smithAttrs[2],data.smithAttrs[3],data.smithAttrs[4],nValue,data.nAreaId);
strcat(m_pHugeSQLBuffer,sBuff);
strcat(m_pHugeSQLBuffer," )");
if(i < nMailAttachCount -1)
{
strcat(m_pHugeSQLBuffer,",");
}
}
nErrorCode = m_pSQLConnection->Exec(m_pHugeSQLBuffer);
if (!nErrorCode)
{
m_pSQLConnection->ResetQuery();
}
}
}
}
void CLogicDBReqestHandler::LoadActorMail(CDataPacketReader & inPacket)
{
int nServerId = 0, nRawServerId = 0;
inPacket >> nRawServerId >> nServerId;
unsigned int nActorId = 0;
inPacket >> nActorId;
QueryActorMail(nActorId, nRawServerId, nServerId);
}
void CLogicDBReqestHandler::QueryActorMail(unsigned int nActorId, int nRawServerId, int nServerId)
{
int nErrorCode = 0;
if (!m_pSQLConnection->Connected())
{
nErrorCode = reDbNotConnected;
}
else
{
nErrorCode = m_pSQLConnection->Query(szSQLSP_LoadMail, nActorId);
if (!nErrorCode)
{
MYSQL_ROW pRow = m_pSQLConnection->CurrentRow();
int nRowCount = m_pSQLConnection->GetRowCount();
if(nRowCount > 0)
{
for (int i=0,packetCount = 1; i < nRowCount; i++)
{
WORD wMailCount = 0;
CDataPacket & outPacket = allocProtoPacket(dcLoadMail);
outPacket << nRawServerId << nServerId << nActorId << (byte)nErrorCode;
outPacket << (BYTE)packetCount++;//第几个包
size_t wMailCountPos = outPacket.getPosition();
outPacket << (WORD)wMailCount;//邮件数量,读完再修改这个值
BYTE nMailAttachCount = 0; //记录每封邮件附件数量
size_t mailAttachCountPos = 0;
INT64 nLastMailId = 0;
while(pRow)
{
INT64 nCurMailId = (INT64)StrToInt64(pRow[0]);
if (nLastMailId != nCurMailId)
{
wMailCount++;
mailAttachCountPos = 0;
nMailAttachCount = 0;
nLastMailId = nCurMailId;
outPacket << nCurMailId; //mailid
outPacket << (unsigned int)atoi(pRow[1]);//srcid
outPacket.writeString(pRow[2]?pRow[2]:"");//title
outPacket.writeString(pRow[3]?pRow[3]:"");//content
outPacket << (unsigned int)atoi(pRow[4]);//createdt
outPacket << (byte)atoi(pRow[5]);//state
mailAttachCountPos = outPacket.getPosition();
outPacket << nMailAttachCount;
}
if (pRow[6] != NULL)//有附件
{
nMailAttachCount++;
int nValue = 0;
WORD wValue = 0;
CUserItem userItem;
memset(&userItem,0,sizeof(userItem));
outPacket << (BYTE)atoi(pRow[6]); //type
userItem.series.llId = StrToInt64(pRow[7]); //itemguid
nValue = atoi(pRow[8]); //itemidquastrong
userItem.wItemId = LOWORD(nValue);
wValue = HIWORD(nValue);
userItem.btQuality = LOBYTE(wValue);
userItem.btStrong = HIBYTE(wValue);
userItem.wCount = atoi(pRow[9]); //wCount
nValue = atoi(pRow[10]); //itemcountflag
wValue = LOWORD(nValue);
userItem.wPackageType = LOBYTE(wValue);
userItem.btFlag = HIBYTE(wValue);
int nCount = HIWORD(nValue);
if(nCount > userItem.wCount)
userItem.wCount = nCount;
nValue = atoi(pRow[11]); //nStrongStar ->bLostStar(BYTE) + bInSourceType(BYTE) + bStrongResereLevel(WORD)
wValue = LOWORD(nValue);
userItem.wIdentifySlotNum = HIWORD(nValue); //bStrongResereLevel->wIdentifySlotNum
userItem.bLostStar = LOBYTE(wValue);
userItem.bInSourceType = HIBYTE(wValue);
userItem.nCreatetime = atoi(pRow[12]); //itemtime
nValue = atoi(pRow[13]); //itemreservs
userItem.nDropMonsterId = LOWORD(nValue); //btSmithCount -> nDropMonsterId
wValue = HIWORD(nValue);
userItem.wStar = wValue;
sscanf(pRow[14], "%d",&userItem.smithAttrs[0]); //smith1-5
sscanf(pRow[15], "%d",&userItem.smithAttrs[1]);
sscanf(pRow[16], "%d",&userItem.smithAttrs[2]);
sscanf(pRow[17], "%d",&userItem.smithAttrs[3]);
sscanf(pRow[18], "%d",&userItem.smithAttrs[4]);
nValue = atoi(pRow[19]); //itemreservs2
wValue = HIWORD(nValue);
userItem.btLuck = HIBYTE(wValue);
userItem.btHandPos = LOBYTE(wValue);
wValue = LOWORD(nValue);
userItem.btDeportId = HIBYTE(wValue);
userItem.btSharp = LOBYTE(wValue);
sscanf(pRow[20], "%d",&userItem.nAreaId);
// outPacket << userItem;
userItem >> outPacket;
}
//附件
if (nMailAttachCount != 0)
{
BYTE* pAttachCount = (BYTE*)outPacket.getPositionPtr(mailAttachCountPos);
*pAttachCount = nMailAttachCount;
}
pRow = m_pSQLConnection->NextRow();
if (pRow && nCurMailId == (INT64)StrToInt64(pRow[0]))
{
//邮件附件没读完
continue;
}
if (/*wMailCount == MAIL_DATA_SEND_COUNT_EACH_TIME ||*/ pRow == NULL)
{
WORD* pMailCount = (WORD*)outPacket.getPositionPtr(wMailCountPos);
*pMailCount = wMailCount;
bool isEnd = pRow == NULL?true:false;
outPacket << isEnd;
flushProtoPacket(outPacket);
break;
}
}
if (!pRow)
{
break;
}
}
}
else
{
CDataPacket & outPacket = allocProtoPacket(dcLoadMail);
outPacket << nRawServerId << nServerId << nActorId << (byte)nErrorCode;
outPacket << (BYTE)0;
outPacket << (WORD)0;
bool isEnd = true;
outPacket << isEnd;
flushProtoPacket(outPacket);
}
m_pSQLConnection->ResetQuery();
}
else
{
OutputMsg(rmTip, _T("%s"), mysql_error(m_pSQLConnection->GetMySql()));
}
}
}
void CLogicDBReqestHandler::SaveNewServerMail(CDataPacketReader & inPacket)
{
int nErrorCode = 0;
int nServerId = 0, nRawServerId = 0;
inPacket >> nRawServerId >> nServerId;
int nServerMailId = 0;
inPacket >> nServerMailId;
if (!m_pSQLConnection->Connected())
{
nErrorCode = reDbNotConnected;
}
else
{
nErrorCode = m_pSQLConnection->Exec(szSQLSP_SaveNewServerMail, nServerMailId);
if (!nErrorCode)
{
m_pSQLConnection->ResetQuery();
}
else
{
OutputMsg(rmError,"szSQLSP_SaveNewServerMail Error,errorCode=%d,sql=%s", nErrorCode,m_pHugeSQLBuffer);
}
}
}
void CLogicDBReqestHandler::AddNewServerMail(CDataPacketReader & inPacket)
{
int nErrorCode = 0;
int nServerId = 0, nRawServerId = 0;
inPacket >> nRawServerId >> nServerId;
if (!m_pSQLConnection->Connected())
{
nErrorCode = reDbNotConnected;
}
else
{
ServerMailDef mail;
inPacket >> mail.nServerMailId;
inPacket >> mail.nActorId;
inPacket.readString(mail.sTitle);
inPacket.readString(mail.sContent);
inPacket >> mail.nMinVipLevel >> mail.nMaxVipLevel >> mail.nMinLevel >> mail.nMaxLevel;
inPacket >> mail.nMinRegisterTime >> mail.nMaxRegisterTime >> mail.nMinLoginTime >> mail.nMaxLoginTime;
inPacket >> mail.btOnline >> mail.btSex >> mail.nWay;
sprintf(m_pHugeSQLBuffer, szSQLSP_SaveServerMail);
INT64 nMailId = 0;
char sBuff[1024];
strcat(m_pHugeSQLBuffer, "(");
sprintf(sBuff,"%u,\"%s\",\"%s\",%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d)",mail.nActorId,mail.sTitle,mail.sContent,
mail.nMinVipLevel, mail.nMaxVipLevel,mail.nMinLevel, mail.nMaxLevel,
mail.nMinRegisterTime, mail.nMaxRegisterTime, mail.nMinLoginTime, mail.nMaxLoginTime,
mail.btOnline, mail.btSex, mail.nWay);
strcat(m_pHugeSQLBuffer, sBuff);
nErrorCode = m_pSQLConnection->Exec(m_pHugeSQLBuffer);
if (!nErrorCode)
{
m_pSQLConnection->ResetQuery();
}
unsigned int nMaxId = 0;
nErrorCode = m_pSQLConnection->Query(szSQLSP_GetMaxMailIdServerMail);
if (!nErrorCode)
{
MYSQL_ROW pRow = m_pSQLConnection->CurrentRow();
if ( pRow && pRow[0])
{
nMaxId = (unsigned int)atoi(pRow[0]);
}
m_pSQLConnection->ResetQuery();
}
BYTE nMailAttachCount = 0;
inPacket >> nMailAttachCount;
if (nMailAttachCount > 0)
{
sprintf(m_pHugeSQLBuffer, szSQLSP_SaveServerMailAttach);
WORD nValue = 0;BYTE nType = 0;
int wCount = 0;
for (int i = 0; i <nMailAttachCount ; i++)
{
strcat(m_pHugeSQLBuffer," (");
inPacket >> nType >> nValue >>wCount;
sprintf(sBuff,"%lld,%d,%d,%d)",nMaxId,nType, nValue,wCount); //mailid type,id,count
strcat(m_pHugeSQLBuffer,sBuff);
if(i < nMailAttachCount -1)
{
strcat(m_pHugeSQLBuffer,",");
}
}
nErrorCode = m_pSQLConnection->Exec(m_pHugeSQLBuffer);
if (!nErrorCode)
{
m_pSQLConnection->ResetQuery();
}
}
}
}
void CLogicDBReqestHandler::LoadNewServerMail(int nServerId, int nRawServerId, int nMaxServerMailId)
{
int nErrorCode = 0;
if (!m_pSQLConnection->Connected())
{
nErrorCode = reDbNotConnected;
}
else
{
nErrorCode = m_pSQLConnection->Query(szSQLSP_LoadNewServerMail, nMaxServerMailId);
if (!nErrorCode)
{
MYSQL_ROW pRow = m_pSQLConnection->CurrentRow();
int nRowCount = m_pSQLConnection->GetRowCount();
if (nRowCount == 0)
{
m_pSQLConnection->ResetQuery();
return;
}
INT_PTR packetCount = (nRowCount-1)/MAIL_DATA_SEND_COUNT_EACH_TIME+1;
INT_PTR nNeedSendCount =0;
int nValue =0;
for (INT_PTR curPacketCount =1; curPacketCount <= packetCount; curPacketCount++)
{
if (curPacketCount* MAIL_DATA_SEND_COUNT_EACH_TIME > nRowCount)
{
nNeedSendCount = nRowCount - (curPacketCount-1)*MAIL_DATA_SEND_COUNT_EACH_TIME;
}
else
{
nNeedSendCount = MAIL_DATA_SEND_COUNT_EACH_TIME;
}
CDataPacket & outPacket = allocProtoPacket(dcLoadNewServerMail);
outPacket << nServerId << nServerId <<nErrorCode;
outPacket << (BYTE)LoadDbTypeServerMail<<(WORD)nNeedSendCount;//这个包里有多少邮件
for (INT_PTR i = (curPacketCount-1)* MAIL_DATA_SEND_COUNT_EACH_TIME; i < curPacketCount* MAIL_DATA_SEND_COUNT_EACH_TIME && i < nRowCount; i++)
{
if (pRow)
{
// pRow[0]?outPacket << (int)atoi(pRow[0]):outPacket <<(int)0;//nServerMailId
int nServerMailId = 0;
if(pRow[0])
{
sscanf(pRow[0], "%d", &nServerMailId);//gid
}
outPacket << nServerMailId;
// pRow[1]?outPacket << (unsigned int)atoi(pRow[1]):outPacket <<(unsigned int)0;//nActorId
unsigned int nActorId = 0;
if(pRow[1])
{
sscanf(pRow[1], "%u", &nActorId);//gid
}
outPacket << nActorId;
// pRow[2]?outPacket.writeString(pRow[2]) :outPacket.writeString("");//sTitle
char sTitle[1024] = "0";
if(pRow[2])
{
sscanf(pRow[2], "%s", &sTitle);//gid
}
outPacket.writeString(sTitle);
pRow[3]?outPacket.writeString(pRow[3]) :outPacket.writeString("");//sContent
// char sContent[1024] = "0";
// if(pRow[3])
// {
// sscanf(pRow[3], "%s", &sContent);//gid
// }
// printf("content:%s",sContent);
// outPacket.writeString(sContent);
// pRow[4]?outPacket << (int)atoi(pRow[4]):outPacket <<(int)0;//
int nMinVipLevel = 0;
if(pRow[4])
{
sscanf(pRow[4], "%d", &nMinVipLevel);//nMinVipLevel
}
outPacket << nMinVipLevel;
// pRow[5]?outPacket << (int)atoi(pRow[5]):outPacket <<(int)0;//
int nMaxVipLevel = 0;
if(pRow[5])
{
sscanf(pRow[5], "%d", &nMaxVipLevel);//gid
}
outPacket << nMaxVipLevel;
// pRow[6]?outPacket << (int)atoi(pRow[6]):outPacket <<(int)0;//nMinLevel
int nMinLevel = 0;
if(pRow[6])
{
sscanf(pRow[6], "%d", &nMinLevel);//gid
}
outPacket << nMinLevel;
// pRow[7]?outPacket << (int)atoi(pRow[7]):outPacket <<(int)0;//nMaxLevel
int nMaxLevel = 0;
if(pRow[7])
{
sscanf(pRow[7], "%d", &nMaxLevel);//gid
}
outPacket << nMaxLevel;
// pRow[8]?outPacket << (unsigned int)atoi(pRow[8]):outPacket <<(unsigned int)0;//nMinRegisterTime
unsigned int nMinRegisterTime = 0;
if(pRow[8])
{
sscanf(pRow[8], "%u", &nMinRegisterTime);//gid
}
outPacket << nMinRegisterTime;
// pRow[9]?outPacket << (unsigned int)atoi(pRow[9]):outPacket <<(unsigned int)0;//nMaxRegisterTime
unsigned int nMaxRegisterTime = 0;
if(pRow[9])
{
sscanf(pRow[9], "%u", &nMaxRegisterTime);//gid
}
outPacket << nMaxRegisterTime;
// pRow[10]?outPacket << (unsigned int)atoi(pRow[10]):outPacket <<(unsigned int)0;//nMinLoginTime
unsigned int nMinLoginTime = 0;
if(pRow[10])
{
sscanf(pRow[10], "%u", &nMinLoginTime);//gid
}
outPacket << nMinLoginTime;
// pRow[11]?outPacket << (unsigned int)atoi(pRow[11]):outPacket <<(unsigned int)0;//nMaxLoginTime
unsigned int nMaxLoginTime = 0;
if(pRow[11])
{
sscanf(pRow[11], "%u", &nMaxLoginTime);//gid
}
outPacket << nMaxLoginTime;
// pRow[12]?outPacket << (BYTE)atoi(pRow[12]):outPacket <<(BYTE)0;//btOnline
int btOnline = 0;
if(pRow[12])
{
sscanf(pRow[12], "%d", &btOnline);//gid
}
outPacket << btOnline;
// pRow[13]?outPacket << (char)atoi(pRow[13]):outPacket <<(char)0;//btSex
int btSex = 0;
if(pRow[13])
{
sscanf(pRow[13], "%d", &btSex);//gid
}
outPacket << btSex;
// pRow[14]?outPacket << (unsigned int)atoi(pRow[14]):outPacket <<(unsigned int)0;//way
int way = 0;
if(pRow[14])
{
sscanf(pRow[14], "%d", &way);//gid
}
outPacket << way;
pRow = m_pSQLConnection->NextRow();
}
}
flushProtoPacket(outPacket);
}
m_pSQLConnection->ResetQuery();
//读附件
nErrorCode = m_pSQLConnection->Query(szSQLSP_LoadNewServerMailAttach, nMaxServerMailId);
if (!nErrorCode)
{
MYSQL_ROW pRow = m_pSQLConnection->CurrentRow();
int nRowCount = m_pSQLConnection->GetRowCount();
INT_PTR packetCount = (nRowCount-1)/MAILATTACH_DATA_SEND_COUNT_EACH_TIME+1;
INT_PTR nNeedSendCount =0;
int nValue =0;
for (INT_PTR curPacketCount =1; curPacketCount <= packetCount; curPacketCount++)
{
if (curPacketCount* MAILATTACH_DATA_SEND_COUNT_EACH_TIME > nRowCount)
{
nNeedSendCount = nRowCount - (curPacketCount-1)*MAILATTACH_DATA_SEND_COUNT_EACH_TIME;
}
else
{
nNeedSendCount = MAILATTACH_DATA_SEND_COUNT_EACH_TIME;
}
CDataPacket & outPacket = allocProtoPacket(dcLoadNewServerMail);
outPacket << nServerId << nServerId <<nErrorCode;
outPacket << (BYTE)LoadDbTypeServerMailAttach<<(WORD)nNeedSendCount;//这个包里有多少附件
for (INT_PTR i = (curPacketCount-1)* MAILATTACH_DATA_SEND_COUNT_EACH_TIME; i < curPacketCount* MAILATTACH_DATA_SEND_COUNT_EACH_TIME && i < nRowCount; i++)
{
if (pRow)
{
pRow[0]?outPacket << (int)atoi(pRow[0]):outPacket <<(int)0;//nServerMailId
pRow[1]?outPacket << (BYTE)atoi(pRow[1]):outPacket <<(BYTE)0;//btType
pRow[2]?outPacket << (WORD)atoi(pRow[2]):outPacket <<(WORD)0;//wId
// pRow[3]?outPacket << (BYTE)atoi(pRow[3]):outPacket <<(BYTE)0;//btQuality
pRow[4]?outPacket << (int)atoi(pRow[4]):outPacket <<(int)0;//数量int支持了资源数量超过word
// pRow[5]?outPacket << (BYTE)atoi(pRow[5]):outPacket <<(BYTE)0;//btBind
// pRow[6]?outPacket << (WORD)atoi(pRow[6]):outPacket <<(WORD)0;//wStar
// pRow[7]?outPacket << (BYTE)atoi(pRow[7]):outPacket <<(BYTE)0;//btStarLost
// pRow[8]?outPacket << (BYTE)atoi(pRow[8]):outPacket <<(BYTE)0;//btInscriptlevel
// pRow[9]?outPacket << (int)atoi(pRow[9]):outPacket <<(int)0;//nIncriptExp
// pRow[10]?outPacket << (BYTE)atoi(pRow[10]):outPacket <<(BYTE)0;//btLuck
// pRow[11]?outPacket << (int)atoi(pRow[11]):outPacket <<(int)0;//smith1
// pRow[12]?outPacket << (int)atoi(pRow[12]):outPacket <<(int)0;//smith2
// pRow[13]?outPacket << (int)atoi(pRow[13]):outPacket <<(int)0;//smith3
// pRow[14]?outPacket << (int)atoi(pRow[14]):outPacket <<(int)0;//smith4
// pRow[15]?outPacket << (int)atoi(pRow[15]):outPacket <<(int)0;//smith5
// pRow[16]?outPacket << (WORD)atoi(pRow[16]):outPacket <<(WORD)0;//identifyslotnum
// pRow[17]?outPacket << (WORD)atoi(pRow[17]):outPacket <<(WORD)0;//identifynum
pRow = m_pSQLConnection->NextRow();
}
}
flushProtoPacket(outPacket);
}
m_pSQLConnection->ResetQuery();
//再发一个包结束
CDataPacket & outPacket = allocProtoPacket(dcLoadNewServerMail);
outPacket << nServerId << nServerId <<nErrorCode;
outPacket << (BYTE)LoadDbTypeServerMailComplete;
flushProtoPacket(outPacket);
}
else
{
OutputMsg(rmError,"szSQLSP_LoadNewServerMail Error,errorCode=%d,sql=%s", nErrorCode,m_pHugeSQLBuffer);
}
}
else
{
OutputMsg(rmError,"szSQLSP_LoadNewServerMail Error,errorCode=%d,sql=%s", nErrorCode,m_pHugeSQLBuffer);
}
}
}
void CLogicDBReqestHandler::SaveActorMail(CDataPacketReader & inPacket, bool bResp)
{
unsigned int nActorId = 0, nSrcId = 0, nCreateDt = 0;
byte btState = 0, btIsDel = 0;
int nServerId = 0, nRawServerId = 0;
BYTE nCurPacketCount=0, nPacketCount = 0, nPacketType=0, nDelType=0;
INT64 nMailId = 0;
inPacket >> nRawServerId >> nServerId >> nActorId ;
inPacket >> nCurPacketCount >> nPacketType >> nDelType;
//nPacketTypee :eMailSaveType
//nDelType: eMailSaveDelType
int nErrorCode = reSucc;
if (!m_pSQLConnection->Connected())
{
nErrorCode = reDbNotConnected; //db没有连接上
}
else
{
if (nCurPacketCount == 1 && nPacketType == 0 && nDelType == 0)
{
nErrorCode = m_pSQLConnection->Exec(szSQLSP_DeleteMail, nActorId);//现在只删除isdel=0的邮件,因为loadmail只读了isdel=0,。
if(!nErrorCode)
{
m_pSQLConnection->ResetQuery();
}
}
if (nPacketType == 0)//每个包单独执行保存
{
BYTE nMailCount = 0;
inPacket >> nMailCount;
if (nMailCount > 0)
{
char sTitle[200], sContent[600], sBuff[1024];
sprintf(m_pHugeSQLBuffer, szSQLSP_SaveMail);
for (int i = 0; i < nMailCount; i++)
{
strcat(m_pHugeSQLBuffer, "(");
inPacket >> nMailId >> nSrcId;
inPacket.readString(sTitle, ArrayCount(sTitle));
inPacket.readString(sContent, ArrayCount(sContent));
inPacket >> nCreateDt >> btState >> btIsDel;
char sRealContent[700];
mysql_escape_string(sRealContent,sContent,(unsigned long)strlen(sContent));
sprintf(sBuff,"%lld,%u,%u,\"%s\",\"%s\",%d,%d,%d)", nMailId,nActorId,nSrcId,sTitle,sRealContent,nCreateDt,btState, btIsDel);
strcat(m_pHugeSQLBuffer, sBuff);
if (i < nMailCount -1)
{
strcat(m_pHugeSQLBuffer, ",");
}
}
// printf("%s\n", m_pHugeSQLBuffer);
nErrorCode = m_pSQLConnection->Exec(m_pHugeSQLBuffer);
if (!nErrorCode)
{
m_pSQLConnection->ResetQuery();
}
}
}
else if (nPacketType == 1)
{
WORD nMailAttachCount = 0;
inPacket >> nMailAttachCount;
if (nMailAttachCount > 0)
{
sprintf(m_pHugeSQLBuffer, szSQLSP_SaveMailAttach);
int nValue = 0;
BYTE nType = 0;
char sBuff[1024];
for (int i = 0; i <nMailAttachCount ; i++)
{
CUserItem data;
inPacket >> nMailId >> nType;
data << inPacket;
strcat(m_pHugeSQLBuffer, "(");
sprintf(sBuff,"%lld,%u,%d,%lld,", nMailId,nActorId,nType,data.series.llId); //mailid actotID,guid,type
strcat(m_pHugeSQLBuffer,sBuff);
//ItemId,QUALITY,strong
nValue = MAKELONG( data.wItemId, MAKEWORD( data.btQuality, data.btStrong));
sprintf(sBuff,"%d,%d,",nValue, data.wCount);//MAKELONG(data.wDura,data.wCount));
strcat(m_pHugeSQLBuffer,sBuff);
//wPackageType,btFlag,wHoles
nValue = MAKELONG( MAKEWORD( data.wPackageType, data.btFlag), 0);
sprintf(sBuff," %d, ",nValue);
strcat(m_pHugeSQLBuffer,sBuff);
//BYTE bLostStar;BYTE bInSourceType;//铭刻等级WORD bStrongResereLevel;//保留(可使用)
nValue = MAKELONG( MAKEWORD( data.bLostStar, data.bInSourceType), data.wIdentifySlotNum); //bStrongResereLevel->wIdentifySlotNum
sprintf(sBuff,"%d,",nValue);
strcat(m_pHugeSQLBuffer,sBuff);
//data reserver
//MAKELONG(A,B) 这里A是低字节B是高字节类似 MAKEWORD
nValue = MAKELONG( data.nDropMonsterId, data.wStar ); //btSmithCount -> nDropMonsterId
sprintf(sBuff,"%d,%d,",data.nCreatetime.tv,nValue);
strcat(m_pHugeSQLBuffer,sBuff);
nValue= MAKELONG( MAKEWORD(data.btSharp, data.btDeportId), MAKEWORD(data.btHandPos, data.btLuck));
sprintf(sBuff,"%d,%d,%d,%d,%d,%d,%d)",data.smithAttrs[0],data.smithAttrs[1],data.smithAttrs[2],data.smithAttrs[3],data.smithAttrs[4],nValue,data.nAreaId);
strcat(m_pHugeSQLBuffer,sBuff);
if ((i>0 && i%200 == 0) || i == nMailAttachCount-1)
{
nErrorCode = m_pSQLConnection->Exec(m_pHugeSQLBuffer);
if(!nErrorCode)
{
m_pSQLConnection->ResetQuery();
strcpy(m_pHugeSQLBuffer,szSQLSP_SaveMailAttach);
}
else
{
OutputMsg(rmError,"SaveActorMailAttach Error,errorCode=%d,sql=%s", nErrorCode,m_pHugeSQLBuffer);
}
}
else if(i < nMailAttachCount -1)
{
strcat(m_pHugeSQLBuffer,",");
}
}
}
}
}
}

View File

@@ -0,0 +1,149 @@
#include "StdAfx.h"
#define LIMIT_TOPRANK_COUNT 100
void CLogicDBReqestHandler::SaveBaseRank(CDataPacketReader &inPacket)
{
DECLARE_FUN_TIME_PROF()
int nRawServerIdx = 0, nLoginServerId = 0;
inPacket >> nRawServerIdx >> nLoginServerId;
CDataPacket &retPack = allocProtoPacket((WORD)dcSaveBaseRank);
retPack << nRawServerIdx << nLoginServerId;
if (!m_pSQLConnection->Connected())
{
retPack << (BYTE)reDbErr;
}
else
{
int nError = m_pSQLConnection->Exec(szSQL_SaveTopRank, nRawServerIdx);
if (!nError)
{
retPack << (BYTE)reSucc;
m_pSQLConnection->ResetQuery();
}
else
{
retPack << (BYTE)reDbErr;
}
}
flushProtoPacket(retPack);
}
void CLogicDBReqestHandler::SaveBaseRankCS(CDataPacketReader &inPacket)
{
DECLARE_FUN_TIME_PROF()
int nRawServerIdx = 0, nLoginServerId = 0;
inPacket >> nRawServerIdx >> nLoginServerId;
unsigned int now_time;
inPacket >> now_time;
CDataPacket &retPack = allocProtoPacket((WORD)dcSaveBaseRankCS);
retPack << nRawServerIdx << nLoginServerId;
if (!m_pSQLConnection->Connected())
{
retPack << (BYTE)reDbErr;
}
else
{
SYSTEMTIME sysTime;
CMiniDateTime nStartTime(now_time);
nStartTime.decode(sysTime);
// CMiniDateTime now_time = CMiniDateTime::now();
// int nNowTime = time(NULL);
// SYSTEMTIME sysTime;
// now_time.decode(sysTime);
//GetLocalTime( &sysTime );
static char buf[20]={0};
memset(&buf, 0, sizeof(buf));
sprintf(buf,"%04d-%02d-%02d %02d:%02d:%02d",sysTime.wYear,sysTime.wMonth,sysTime.wDay,sysTime.wHour,sysTime.wMinute,sysTime.wSecond);
int nError = m_pSQLConnection->Exec(szSQL_SaveTopRankCS, nRawServerIdx, buf);
if (!nError)
{
retPack << (BYTE)reSucc;
m_pSQLConnection->ResetQuery();
}
else
{
retPack << (BYTE)reDbErr;
}
}
flushProtoPacket(retPack);
}
void CLogicDBReqestHandler::LoadBaseRank(CDataPacketReader &inPacket)
{
DECLARE_FUN_TIME_PROF()
int nRawServerId = 0, nLoginServerId = 0;
inPacket >> nRawServerId >> nLoginServerId;
CDataPacket& retPack = allocProtoPacket((WORD)dcLoadBaseRank);
retPack << nRawServerId << nLoginServerId;
if (!m_pSQLConnection->Connected())
{
retPack << (BYTE)reDbErr;
}
else
{
int nError = m_pSQLConnection->Query(szSQL_LoadTopRank, LIMIT_TOPRANK_COUNT, nRawServerId);
if (!nError)
{
retPack << (BYTE)nError;
MYSQL_ROW pRow = m_pSQLConnection->CurrentRow();
int nCount = m_pSQLConnection->GetRowCount();
retPack << (int)nCount;
int nValue = 0;
while (pRow)
{
sscanf(pRow[0], "%d", &nValue);
retPack << (unsigned int)nValue;
sscanf(pRow[1], "%d", &nValue);
retPack << (int)nValue;
sscanf(pRow[2], "%d", &nValue);
retPack << (int)nValue;
sscanf(pRow[3], "%d", &nValue);
retPack << (int)nValue;
sscanf(pRow[4], "%d", &nValue);
retPack << (int)nValue;
ACTORNAME sName = {0};
if (pRow[5])
{
sscanf(pRow[5], "%s", &sName);
}
retPack.writeString(sName);
sscanf(pRow[6], "%d", &nValue);
retPack << (int)nValue;
sscanf(pRow[7], "%d", &nValue);
retPack << (int)nValue;
sscanf(pRow[8], "%d", &nValue);//yy
retPack << (int)nValue;
ACTORNAME sguildName = {0};
if (pRow[9])
{
sscanf(pRow[9], "%s", &sguildName);
}
retPack.writeString(sguildName);
sscanf(pRow[10], "%d", &nValue);//特权
retPack << (int)nValue;
pRow = m_pSQLConnection->NextRow();
}
m_pSQLConnection->ResetQuery(); //函数调用里没有重置数据的
}
else
{
OutputMsg(rmError,_T("%s装载排行榜数据失败"),__FUNCTION__);
retPack << (BYTE)nError;
}
}
flushProtoPacket(retPack);
}

View File

@@ -0,0 +1 @@
#include "StdAfx.h"

145
server/DBServer/StdAfx.h Normal file
View File

@@ -0,0 +1,145 @@
#include <stdio.h>
#include <stdlib.h>
#ifdef WIN32
#include <crtdbg.h>
#include <tchar.h>
#include <Windows.h>
#endif
#include <signal.h>
#include <_ast.h>
#include <_memchk.h>
#include <Thread.h>
#include <CustomSocket.h>
#include <Lock.h>
#include <Tick.h>
#include <QueueList.h>
#include"Define.h"
#define StrToInt _StrToInt
#include "ShareUtil.h"
#include "BufferAllocator.h"
#include "AppItnMsg.h"
//#include "db/SqlHelper.h"
#include "DataPacket.hpp"
#include "DataPacketReader.hpp"
#include "SendPackPool.h"
#include "CustomWorkSocket.h"
#include "CustomClientSocket.h"
#include "CustomServerClientSocket.h"
#include "CustomServerClientSocketEx.h"
#include "CustomServerSocket.h"
#include "ServerDef.h"
#include "ServerMailDef.h"
#include "CustomJXClientSocket.h"
#include "GateProto.h"
#include "../../LogicServer/script/interface/PropertyIDDef.h"
#include "../../LogicServer/property/PropertyDef.h"
#include "../../LogicServer/property/PropertySet.h"
#include "ActorOfflineMsg.h"
#include "QuestData.h"
#include "LoadString.h"
#include "SQL.h"
#include "ObjectCounter.h"
#include "TimeStat.h"
#include "../../LogicServer/script/interface/SystemParamDef.h"
#include "CustomServerGateUser.h"
#include "CustomServerGate.h"
#include "CustomGateManager.h"
#include "CustomGlobalSession.h"
#include "CustomSessionClient.h"
#include "InterServerComm.h"
#include "ActorCacheDef.h"
#include "DBSessionClient.h"
#include "DBProto.h"
#include "JobZyCountMgr.h"
#include "EsqlMgr.h"
#include "GateDBRequestHandler.h"
#include "DBGateUser.h"
#include "DBGate.h"
#include "DBGateManager.h"
#include <Stream.h>
#include <MBCSDef.h> //关键字过滤用的
#include "DBDataServer.h"
#include "DBServer.h"
#include "../../LogicServer/attr/AttrDef.h"
#include "DBNSClient.h"
#include "CustomJXServerClientSocket.h"
#include "LinkedList.h"
#include "HandleStat.h"
#include "HandleMgr.h"
#include "LogicDBRequestHostInterface.h"
#include "LogicDBRequestHandler.h"
#include "DBDataCache.h"
#include "DBDataClientHandler.h"
#include "DBDataClient.h"
#include "MiniDateTime.h" //时间用的
using namespace jxSrvDef;
#include "PropertyDef.h"
#include "ActorDbData.h"
#include "SkillDbData.h"
#include "UserItem.h"
#include "PetData.h"
#include "HeroData.h"
#include "HallowsDef.h"
#include "GameSets.h"
#include "GhostDef.h"
//#include "encrypt/CRC.h"
//#include "encrypt/Encrypt.h"
//#include "dataProcess/NetworkDataHandler.h"
#include "FileLogger.h"
#include "LogSender.h"
#include "LogType.h"
#include "DBCenterClient.h"
#include <RefClass.hpp>
#include <RefString.hpp>
#include <time.h>
//#include "EDPass.h"
using namespace wylib::stream;
using namespace wylib::string;
using namespace jxInterSrvComm::DbServerProto;
using namespace jxInterSrvComm::NameServerProto;
extern "C"
{
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>
}
#include "CustomLuaMyLoad.h"
#include "CustomLuaScript.h"
#include "CustomLuaConfig.h"
#include "DBConfig.h"
#include "StackWalker.h"
#include "DefExceptHander.h"
#include "CustomExceptHander.h"
//#include "WinService.h"
#ifdef _DEBUG
#else
/*
#ifndef _USE_TRY_CATCH
#define _USE_TRY_CATCH   
#endif
*/
#endif
//#include "./misc/AllocForSTL.hpp"

14
server/DBServer/build.sh Normal file
View File

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

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,298 @@
#include "StdAfx.h"
/************************************************************************/
/* 本文件实现了职业宗师数据的查询和保存 */
/* 函数申明在LogicDBRequestHandler.h文件。 */
/************************************************************************/
VOID CLogicDBReqestHandler::LoadActorCombatRank(CDataPacketReader &inPacket)
{
}
VOID CLogicDBReqestHandler::LoadActorCombatGameInfo(CDataPacketReader &inPacket)
{
}
VOID CLogicDBReqestHandler::SaveActorCombatGameInfo(CDataPacketReader &inPacket)
{
}
VOID CLogicDBReqestHandler::LoadCombatRecord(CDataPacketReader &inPacket)
{
}
VOID CLogicDBReqestHandler::SaveCombatRecordToDb(CDataPacketReader &inPacket)
{
}
VOID CLogicDBReqestHandler::UpdateActorCombatAward(CDataPacketReader &inPacket)
{
}
VOID CLogicDBReqestHandler::LoadActorCombatBaseInfo(CDataPacketReader &inPacket)
{
DECLARE_FUN_TIME_PROF()
int nRawServerId, nLoginServerId;
inPacket >> nRawServerId >> nLoginServerId;
unsigned int nActorId = 0;
inPacket >> nActorId;
int nErrorCode = reDbErr;
CDataPacket& retPack = allocProtoPacket((WORD)dcLoadCmobatGameInfo);
if (!m_pSQLConnection->Connected())
{
nErrorCode = reDbNotConnected;
retPack << (BYTE)nErrorCode;
}
else
{
nErrorCode = m_pSQLConnection->Query(szSQLSP_LoadActorCombatBaseInfo, nActorId);
if (!nErrorCode)
{
MYSQL_ROW pRow = m_pSQLConnection->CurrentRow();
if ( pRow)
{
retPack << nRawServerId;
retPack << nLoginServerId;
retPack << (unsigned int)nActorId;
retPack << (BYTE)reSucc;
int currank = 0;
int maxrank = 0;
int lastrank = 0;
int combatscore = 0;
int challegenum = 0;
int picknum = 0;
int cleartime = 0;
int cdflag = 0;
sscanf(pRow[0], "%d", &currank);
sscanf(pRow[1], "%d", &maxrank);
sscanf(pRow[2], "%d", &lastrank);
sscanf(pRow[3], "%d", &combatscore);
sscanf(pRow[4], "%d", &challegenum);
sscanf(pRow[5], "%d", &picknum);
sscanf(pRow[6], "%d", &cleartime);
sscanf(pRow[7], "%d", &cdflag);
retPack << currank;
retPack << maxrank;
retPack << lastrank;
retPack << combatscore;
retPack << challegenum;
retPack << picknum;
retPack << cleartime;
retPack << cdflag;
m_pSQLConnection->ResetQuery();
}
else
{
m_pSQLConnection->ResetQuery();
nErrorCode = m_pSQLConnection->Exec(szSQLSP_AddActorCombatBaseInfo, nActorId);
if (!nErrorCode)
{
m_pSQLConnection->ResetQuery();
}
retPack << (BYTE)reDbErr;
}
}
else
{
retPack << (BYTE)reDbErr;
}
}
flushProtoPacket(retPack);
}
VOID CLogicDBReqestHandler::SaveActorCombatBaseInfo(CDataPacketReader &inPacket)
{
DECLARE_FUN_TIME_PROF()
int nRawServerId, nLoginServerId;
inPacket >> nRawServerId >> nLoginServerId;
unsigned int nActorId = 0;
inPacket >> nActorId;
//预防数据错乱处理
if(nActorId <= 0) return;
int currank = 0;
int maxrank = 0;
int lastrank = 0;
int combatscore = 0;
int challegenum = 0;
int picknum = 0;
int cleartime = 0;
int cdflag = 0;
inPacket >> currank;
inPacket >> maxrank;
inPacket >> lastrank;
inPacket >> combatscore;
inPacket >> challegenum;
inPacket >> picknum;
inPacket >> cleartime;
inPacket >> cdflag;
int nErrorCode = reDbErr;
if (!m_pSQLConnection->Connected())
{
nErrorCode = reDbNotConnected;
}
else
{
nErrorCode = m_pSQLConnection->Exec(szSQLSP_SaveActorCombatBaseInfo, currank, maxrank, lastrank, combatscore, challegenum, picknum, cleartime, cdflag, nActorId);
if (!nErrorCode)
{
m_pSQLConnection->ResetQuery();
}
}
}
VOID CLogicDBReqestHandler::LoadActorCombatLog(CDataPacketReader &inPacket)
{
DECLARE_FUN_TIME_PROF()
int nRawServerId, nLoginServerId;
inPacket >> nRawServerId >> nLoginServerId;
unsigned int nActorId = 0;
inPacket >> nActorId;
int nErrorCode = reDbErr;
CDataPacket& retPack = allocProtoPacket((WORD)dcLoadCombatRecord);
if (!m_pSQLConnection->Connected())
{
nErrorCode = reDbNotConnected;
retPack << (BYTE)nErrorCode;
}
else
{
nErrorCode = m_pSQLConnection->Query(szSQLSP_LoadActorCombatLogInfo, nActorId);
if (!nErrorCode)
{
MYSQL_ROW pRow = m_pSQLConnection->CurrentRow();
int nRowCount = m_pSQLConnection->GetRowCount();
retPack << nRawServerId << nLoginServerId;
retPack << (unsigned int)nActorId;
retPack << (BYTE)reSucc;
retPack << nRowCount;
int type = 0;
int result = 0;
int targetid = 0;
int targetname = 0;
int rank = 0;
while (pRow)
{
sscanf(pRow[0], "%d", &type);
retPack << type;
sscanf(pRow[1], "%d", &result);
retPack << result;
sscanf(pRow[2], "%d", &targetid);
retPack << targetid;
pRow[3]?retPack.writeString(pRow[3]):retPack.writeString("");
sscanf(pRow[4], "%d", &rank);
retPack << rank;
pRow = m_pSQLConnection->NextRow();
}
m_pSQLConnection->ResetQuery();
}
}
flushProtoPacket(retPack);
}
VOID CLogicDBReqestHandler::SaveActorCombatLog(CDataPacketReader &inPacket)
{
DECLARE_FUN_TIME_PROF()
int nRawServerId, nLoginServerId;
inPacket >> nRawServerId >> nLoginServerId;
unsigned int nActorId = 0;
inPacket >> nActorId;
int nCount = 0;
inPacket >> nCount;
if(nCount <= 0)
return;
int nErrorCode = reDbErr;
if (!m_pSQLConnection->Connected())
{
nErrorCode = reDbNotConnected;
}
else
{
nErrorCode = m_pSQLConnection->Exec(szSQLSP_DeleteActorCombatLogInfo, nActorId);
if (!nErrorCode)
{
m_pSQLConnection->ResetQuery();
}
char buff[1024];
strcpy(m_pHugeSQLBuffer, szSQLSP_SaveActorCombatLogInfo); //表头放这里
int type = 0;
int result = 0;
int targetid = 0;
char targetname[32];
int rank = 0;
for(int i = 0; i < nCount; ++i)
{
inPacket >> type;
inPacket >> result;
inPacket >> targetid;
inPacket.readString(targetname, ArrayCount(targetname));
inPacket >> rank;
strcat(m_pHugeSQLBuffer, " (");
sprintf(buff, "%d,%d,%d,%d,\"%s\",%d", nActorId, type, result, targetid, targetname, rank);
strcat(m_pHugeSQLBuffer, buff);
strcat(m_pHugeSQLBuffer, " )");
if(i < nCount -1)
{
strcat(m_pHugeSQLBuffer,",");
}
}
nErrorCode = m_pSQLConnection->Exec(m_pHugeSQLBuffer);
if(!nErrorCode)
{
m_pSQLConnection->ResetQuery();
}
}
}

View File

@@ -0,0 +1,501 @@
#include "StdAfx.h"
#define CONSIGN_SEND_COUNT_EACH_TIME 300 //寄卖数据,每个包发送的物品数
#define INCOME_SEND_COUNT_EACH_TIME 1000 //收益数据,每个包发送数量
void CLogicDBReqestHandler::SaveActorConsignment(CDataPacketReader &inPacket)
{
unsigned int nActorId = 0, nSellTime = 0, nPrice = 0,nIncome = 0, nItemId = 0, nCount = 0;
int nServerId = 0, nRawServerId = 0;
// CUserItem data;
BYTE nState= 0;
WORD wItemCount = 0;
int nAutoId = 0;
inPacket >> nRawServerId >> nServerId ;
inPacket >> nActorId;
int nErrorCode = reSucc;
if (!m_pSQLConnection->Connected())
{
nErrorCode = reDbNotConnected; //db没有连接上
}
else
{
//保存收益
inPacket >> nIncome;
nErrorCode = m_pSQLConnection->Exec(szSQLSP_DeleteConsignmentIncome, nActorId,nServerId);
if (!nErrorCode)
{
m_pSQLConnection->ResetQuery();
if (nIncome > 0)
{
char buff[256];
sprintf(m_pHugeSQLBuffer, szSQLSP_AddCharConsignmentIncome);
sprintf(buff,"(%u,%u,%d)",nActorId,nIncome,nServerId);
strcat(m_pHugeSQLBuffer,buff);
nErrorCode = m_pSQLConnection->Exec(m_pHugeSQLBuffer);
if (!nErrorCode)
{
m_pSQLConnection->ResetQuery();
}
else
{
OutputMsg(rmError,"szSQLSP_AddCharConsignmentIncome Error,errorCode=%d,sql=%s", nErrorCode,m_pHugeSQLBuffer);
}
}
}
else
{
OutputMsg(rmError,"szSQLSP_DeleteConsignmentIncome Error,errorCode=%d,sql=%s", nErrorCode,m_pHugeSQLBuffer);
}
//保存物品
nErrorCode = m_pSQLConnection->Exec(szSQLSP_DeleteConsignmentItem, nActorId,nServerId);
if (!nErrorCode)
{
m_pSQLConnection->ResetQuery();
}
else
{
OutputMsg(rmError,"szSQLSP_DeleteConsignmentItem Error,errorCode=%d,sql=%s", nErrorCode,m_pHugeSQLBuffer);
}
inPacket >> wItemCount;
if (wItemCount > 0)
{
int nValue = 0;
char buff[1024];
sprintf(m_pHugeSQLBuffer, szSQLSP_AddCharConsignmentItem);
for (int i = 1; i <= wItemCount; i++)
{
// memset(&data,0,sizeof(data));
strcat(m_pHugeSQLBuffer, "(");
inPacket >> nItemId >> nCount;
inPacket >> nSellTime >> nPrice >> nActorId >> nState >> nAutoId;
char cBestAttr[50];//极品属性
memset(cBestAttr, 0, sizeof(cBestAttr));
inPacket.readString(cBestAttr, ArrayCount(cBestAttr));
cBestAttr[sizeof(cBestAttr)-1] = 0;
nValue = MAKELONG( nItemId, nCount);
sprintf(buff,"%u,%d,",nActorId,nValue); //actotID,//itemid, itemcount
strcat(m_pHugeSQLBuffer,buff);
sprintf(buff,"%u,%d,%d,%d,%d,", nSellTime, nPrice, nState,nServerId,nAutoId);
strcat(m_pHugeSQLBuffer,buff);
sprintf(buff,"\"%s\"",cBestAttr);
strcat(m_pHugeSQLBuffer, ")");
if (i != wItemCount)
{
strcat(m_pHugeSQLBuffer, ",");
}
}
nErrorCode = m_pSQLConnection->Exec(m_pHugeSQLBuffer);
if (!nErrorCode)
{
m_pSQLConnection->ResetQuery();
}
else
{
OutputMsg(rmError,"szSQLSP_AddCharConsignmentItem Error,errorCode=%d,sql=%s", nErrorCode,m_pHugeSQLBuffer);
}
}
}
}
//分包保存,只保存系统的
void CLogicDBReqestHandler::SaveConsignmentItem(CDataPacketReader &inPacket)
{
DECLARE_FUN_TIME_PROF()
unsigned int nActorId = 0;
unsigned int nSellTime = 0;
unsigned int nPrice = 0;
unsigned int nItemId = 0;
unsigned int nCount = 0;
int nServerId = 0, nRawServerId = 0;
WORD wStar = 0;
int nAutoId = 0;
int nCurPacketCount=0;
CUserItem data;
BYTE nState= 0;
inPacket >> nRawServerId >> nServerId ;
inPacket >> nCurPacketCount;
int nErrorCode = reSucc;
if (!m_pSQLConnection->Connected())
{
nErrorCode = reDbNotConnected; //db没有连接上
}
else
{
if (nCurPacketCount == 1)
{
nErrorCode = m_pSQLConnection->Exec(szSQLSP_DeleteConsignmentItem, 0,nServerId);//nactorid=0
}
if (!nErrorCode)
{
m_pSQLConnection->ResetQuery();
WORD nItemCount = 0;
inPacket >> nItemCount;
if (nItemCount > 0)
{
int nValue = 0;
char buff[1024];
sprintf(m_pHugeSQLBuffer, szSQLSP_AddCharConsignmentItem);
for (int i = 1; i <= nItemCount; i++)
{
memset(&data,0,sizeof(data));
data << inPacket; //装载入物品的数据
inPacket >> nSellTime >> nPrice >> nActorId >> nState>> nAutoId;;
strcat(m_pHugeSQLBuffer," (");
sprintf(buff,"%u,%lld,",nActorId,data.series.llId); //actotID,guid
strcat(m_pHugeSQLBuffer,buff);
//ItemId,QUALITY,strong
nValue = MAKELONG( data.wItemId, MAKEWORD( data.btQuality, data.btStrong));
sprintf(buff,"%d,%d,",nValue, 0);//MAKELONG(data.wDura,data.wDuraMax));
strcat(m_pHugeSQLBuffer,buff);
//wPackageType,btFlag,wHoles
nValue = MAKELONG( MAKEWORD( data.wPackageType, data.btFlag), data.wCount);
sprintf(buff," %d,",nValue);
strcat(m_pHugeSQLBuffer,buff);
//BYTE bCurbLostStarStrongMax;BYTE bInSourceType;//铭刻等级WORD bStrongResereLevel;//保留(可使用)
nValue = MAKELONG( MAKEWORD( data.bLostStar, data.bInSourceType), data.wIdentifySlotNum); //bStrongResereLevel->wIdentifySlotNum
sprintf(buff,"%d,",nValue);
strcat(m_pHugeSQLBuffer,buff);
//data reserver
//MAKELONG(A,B) 这里A是低字节B是高字节类似 MAKEWORD
nValue = MAKELONG( data.nDropMonsterId, data.wStar ); //btSmithCount -> nDropMonsterId
sprintf(buff,"%d,%d,",data.nCreatetime.tv,nValue);
strcat(m_pHugeSQLBuffer,buff);
nValue= MAKELONG( MAKEWORD(data.btSharp, data.btDeportId), MAKEWORD(data.btHandPos, data.btLuck));
sprintf(buff,"%d,%d,%d,%d,%d,%d,%d,",data.smithAttrs[0],data.smithAttrs[1],data.smithAttrs[2],data.smithAttrs[3],data.smithAttrs[4],nValue,data.nAreaId);
strcat(m_pHugeSQLBuffer,buff);
sprintf(buff,"\"%s\",\"%s\"",data.cBestAttr, data.cSourceName);
strcat(m_pHugeSQLBuffer,buff);
strcat(m_pHugeSQLBuffer,",");
sprintf(buff,"%d,%d,%d,%d,%d",nSellTime, nPrice, nState, nServerId,nAutoId); //actotID, //itemid, itemcount
strcat(m_pHugeSQLBuffer,buff);
strcat(m_pHugeSQLBuffer," )");
if(i <= nItemCount -1)
{
strcat(m_pHugeSQLBuffer,",");
}
}
nErrorCode = m_pSQLConnection->Exec(m_pHugeSQLBuffer);
if (!nErrorCode)
{
m_pSQLConnection->ResetQuery();
}
else
{
OutputMsg(rmError,"szSQLSP_AddCharConsignmentItem Error,errorCode=%d,sql=%s", nErrorCode,m_pHugeSQLBuffer);
}
}
}
else
{
OutputMsg(rmError,"szSQLSP_DeleteConsignmentItem Error,errorCode=%d,sql=%s", nErrorCode,m_pHugeSQLBuffer);
}
}
}
void CLogicDBReqestHandler::LoadConsignmentItem(CDataPacketReader &inPacket)
{
DECLARE_FUN_TIME_PROF()
int nServerId = 0, nRawServerId = 0;
inPacket >> nRawServerId >> nServerId;
int nErrorCode = 0;
CUserItem data;
if (!m_pSQLConnection->Connected())
{
nErrorCode = reDbNotConnected;
}
else
{
nErrorCode = m_pSQLConnection->Query(szSQLSP_LoadConsignmentItem, nServerId);
if (!nErrorCode)
{
MYSQL_ROW pRow = m_pSQLConnection->CurrentRow();
int nRowCount = m_pSQLConnection->GetRowCount();
INT_PTR packetCount = (nRowCount-1)/CONSIGN_SEND_COUNT_EACH_TIME+1;
INT_PTR nNeedSendItemCount =0;
int nValue =0; WORD wValue = 0;
bool isEnd = false;
for (INT_PTR curPacketCount =1; curPacketCount <= packetCount; curPacketCount++)
{
if (curPacketCount* CONSIGN_SEND_COUNT_EACH_TIME > nRowCount)
{
nNeedSendItemCount = nRowCount - (curPacketCount-1)*CONSIGN_SEND_COUNT_EACH_TIME;
}
else
{
nNeedSendItemCount = CONSIGN_SEND_COUNT_EACH_TIME;
}
if (curPacketCount == packetCount)
{
isEnd = true;
}
CDataPacket & outPacket = allocProtoPacket(dcLoadConsignmentItem);
outPacket << nServerId << nServerId <<nErrorCode;
outPacket << (WORD)nNeedSendItemCount << isEnd;
for (INT_PTR i = (curPacketCount-1)* CONSIGN_SEND_COUNT_EACH_TIME; i < curPacketCount* CONSIGN_SEND_COUNT_EACH_TIME && i < nRowCount; i++)
{
if (pRow)
{
memset(&data,0,sizeof(data));
data.series.llId= StrToInt64(pRow[0]);
//itemID,Quality,strong
sscanf(pRow[1], "%d",&nValue);//itemIdQuaStrong
data.wItemId = LOWORD(nValue);
wValue = HIWORD(nValue);
data.btQuality = LOBYTE(wValue);
data.btStrong = HIBYTE(wValue);
//背包类型与flag,镶嵌的的第1字节
sscanf(pRow[3], "%d",&nValue);
wValue = LOWORD(nValue);
data.wPackageType = LOBYTE(wValue);
data.btFlag = HIBYTE(wValue);
data.wCount = HIWORD(nValue);
//镶嵌的2,3个word
sscanf(pRow[4], "%d",&nValue);
wValue = LOWORD(nValue);
data.wIdentifySlotNum = HIWORD(nValue); //bStrongResereLevel->wIdentifySlotNum
data.bLostStar = LOBYTE(wValue);
data.bInSourceType = HIBYTE(wValue);
//时间
sscanf(pRow[5], "%d",&data.nCreatetime.tv);
//reserverd
sscanf(pRow[6], "%d",&nValue);
data.nDropMonsterId = LOWORD(nValue); //btSmithCount -> nDropMonsterId
wValue = HIWORD(nValue);
data.wStar= wValue;
//smith1
sscanf(pRow[7], "%d",&data.smithAttrs[0]);
//smith2
sscanf(pRow[8], "%d",&data.smithAttrs[1]);
//smith3
sscanf(pRow[9], "%d",&data.smithAttrs[2]);
sscanf(pRow[10], "%d",&data.smithAttrs[3]);
//smith3
sscanf(pRow[11], "%d",&data.smithAttrs[4]);
sscanf(pRow[12], "%d",&nValue);
wValue = HIWORD(nValue);
data.btLuck = HIBYTE(wValue);
data.btHandPos = LOBYTE(wValue);
wValue = LOWORD(nValue);
data.btDeportId = HIBYTE(wValue);
data.btSharp = LOBYTE(wValue);
if(pRow[13]) {
sscanf(pRow[13], "%d",&data.nAreaId);
}
memset(&data.cBestAttr, 0 ,sizeof(data.cBestAttr));
std::string str = "";
if(pRow[14]) {
str = pRow[14];
}
if(str != "") {
strcpy(data.cBestAttr, str.c_str());
}
data.cBestAttr[sizeof(data.cBestAttr)-1] = '0';
memset(&data.cSourceName, 0 ,sizeof(data.cSourceName));
str = "";
if(pRow[19]) {
str = pRow[19];
}
if(str != "") {
strcpy(data.cSourceName, str.c_str());
}
data.cSourceName[sizeof(data.cSourceName)-1] = '0';
data >> outPacket;
outPacket << (unsigned int)atoi(pRow[15]); //actorid
outPacket << (unsigned int)atoi(pRow[16]); //selltime
outPacket << (unsigned int)atoi(pRow[17]); //price
outPacket << (BYTE)atoi(pRow[18]); //state
outPacket << (int)atoi(pRow[20]); //autoid
// memset(&data.cSourceName, 0 ,sizeof(data.cSourceName));
// str = "";
// if(pRow[19]) {
// str = pRow[19];
// }
// if(str != "") {
// strcpy(data.cSourceName, str.c_str());
// }
// data.cSourceName[sizeof(data.cSourceName)-1] = '0';
pRow = m_pSQLConnection->NextRow();
}
}
flushProtoPacket(outPacket);
}
m_pSQLConnection->ResetQuery();
}
else
{
OutputMsg(rmError,"szSQLSP_LoadConsignmentItem Error,errorCode=%d,sql=%s", nErrorCode,m_pHugeSQLBuffer);
}
}
}
void CLogicDBReqestHandler::LoadConsignmentIncome(CDataPacketReader &inPacket)
{
DECLARE_FUN_TIME_PROF()
int nServerId = 0, nRawServerId = 0;
inPacket >> nRawServerId >> nServerId;
int nErrorCode = 0;
if (!m_pSQLConnection->Connected())
{
nErrorCode = reDbNotConnected;
}
else
{
nErrorCode = m_pSQLConnection->Query(szSQLSP_LoadConsignmentIncome,nServerId);
if (!nErrorCode)
{
MYSQL_ROW pRow = m_pSQLConnection->CurrentRow();
int nRowCount = m_pSQLConnection->GetRowCount();
INT_PTR packetCount = (nRowCount-1)/INCOME_SEND_COUNT_EACH_TIME+1;
INT_PTR nNeedSendCount =0;
int nValue =0;
for (INT_PTR curPacketCount =1; curPacketCount <= packetCount; curPacketCount++)
{
if (curPacketCount* INCOME_SEND_COUNT_EACH_TIME > nRowCount)
{
nNeedSendCount = nRowCount - (curPacketCount-1)*INCOME_SEND_COUNT_EACH_TIME;
}
else
{
nNeedSendCount = INCOME_SEND_COUNT_EACH_TIME;
}
CDataPacket & outPacket = allocProtoPacket(dcLoadConsignmentIncome);
outPacket << nServerId << nServerId <<nErrorCode;
outPacket << (WORD)nNeedSendCount;//这个包里有多少邮件
for (INT_PTR i = (curPacketCount-1)* INCOME_SEND_COUNT_EACH_TIME; i < curPacketCount* INCOME_SEND_COUNT_EACH_TIME && i < nRowCount; i++)
{
if (pRow)
{
outPacket <<(unsigned int)atoi(pRow[0]);
outPacket <<(unsigned int)atoi(pRow[1]);
pRow = m_pSQLConnection->NextRow();
}
}
flushProtoPacket(outPacket);
}
m_pSQLConnection->ResetQuery();
}
else
{
OutputMsg(rmError,"szSQLSP_LoadConsignmentIncome Error,errorCode=%d,sql=%s", nErrorCode,m_pHugeSQLBuffer);
}
}
}
//旧的保存方式
//void CLogicDBReqestHandler::SaveConsignmentIncome(CDataPacketReader &inPacket)
//{
// DECLARE_FUN_TIME_PROF()
// unsigned int nActorId = 0, nSellTime = 0, nPrice = 0;
// int nServerId = 0, nRawServerId = 0;
// BYTE nCurPacketCount=0;
// CUserItem data;
//
// BYTE nState= 0;
// inPacket >> nRawServerId >> nServerId ;
// inPacket >> nCurPacketCount;
// int nErrorCode = reSucc;
// if (!m_pSQLConnection->Connected())
// {
// nErrorCode = reDbNotConnected; //db没有连接上
// }
// else
// {
// if (nCurPacketCount == 1)
// {
// nErrorCode = m_pSQLConnection->Exec(szSQLSP_DeleteConsignmentIncome, nActorId);
// }
// if (!nErrorCode)
// {
// m_pSQLConnection->ResetQuery();
//
// WORD nIncomeCount = 0;
// inPacket >> nIncomeCount;
// if (nIncomeCount > 0)
// {
// char buff[256];
// sprintf(m_pHugeSQLBuffer, szSQLSP_AddCharConsignmentIncome);
// for (int i = 1; i <= nIncomeCount; i++)
// {
// unsigned int nActorId =0, nIncome = 0;
// inPacket >> nActorId >> nIncome;
// sprintf(buff,"(%u,%u)",nActorId,nIncome);
// strcat(m_pHugeSQLBuffer,buff);
// if (i != nIncomeCount)
// {
// strcat(m_pHugeSQLBuffer, ",");
// }
// }
// nErrorCode = m_pSQLConnection->Exec(m_pHugeSQLBuffer);
// if (!nErrorCode)
// {
// m_pSQLConnection->ResetQuery();
// }
// else
// {
// OutputMsg(rmError,"szSQLSP_AddCharConsignmentIncome Error,errorCode=%d,sql=%s", nErrorCode,m_pHugeSQLBuffer);
// }
// }
// }
// else
// {
// OutputMsg(rmError,"szSQLSP_DeleteConsignmentIncome Error,errorCode=%d,sql=%s", nErrorCode,m_pHugeSQLBuffer);
// }
// }
//}
void DealSaveItemInfoToMysql(char* buff, unsigned int nActorID, CUserItem& data)
{
sprintf(buff,"%u,%lld,",nActorID,data.series.llId); //actotID,guid
//ItemId,QUALITY,strong
int nValue = MAKELONG( data.wItemId, MAKEWORD( data.btQuality, data.btStrong));
sprintf(buff,"%d,%d,",nValue, 0);//MAKELONG(data.wDura,data.wDuraMax));
//wPackageType,btFlag,wHoles
nValue = MAKELONG( MAKEWORD( data.wPackageType, data.btFlag), data.wCount);
sprintf(buff," %d,",nValue);
//BYTE bCurbLostStarStrongMax;BYTE bInSourceType;//铭刻等级WORD bStrongResereLevel;//保留(可使用)
nValue = MAKELONG( MAKEWORD( data.bLostStar, data.bInSourceType), data.wIdentifySlotNum); //bStrongResereLevel->wIdentifySlotNum
sprintf(buff,"%d,",nValue);
//MAKELONG(A,B) 这里A是低字节B是高字节类似 MAKEWORD
nValue = MAKELONG( data.nDropMonsterId, data.wStar ); //btSmithCount -> nDropMonsterId
sprintf(buff,"%d,%d,",data.nCreatetime.tv,nValue);
nValue= MAKELONG( MAKEWORD(data.btSharp, data.btDeportId), MAKEWORD(data.btHandPos, data.btLuck));
sprintf(buff,"%d,%d,%d,%d,%d,%d,%d,",data.smithAttrs[0],data.smithAttrs[1],data.smithAttrs[2],data.smithAttrs[3],data.smithAttrs[4],nValue,data.nAreaId);
sprintf(buff,"\"%s\"",data.cBestAttr);
}

Some files were not shown because too many files have changed in this diff Show More