sqlite3LoggerPlugin设置
概览
RakNet的sqlLite日志系统允许任何支持TCP的系统向远端服务器发送日志。日志自动包含了源文件和行,以及日志发送的时间,发送者的IP地址。日志系统支持实时时间DXT1压缩,允许游戏会话的视频重放。记录日志并不需要sql知识,事实上通过RakNet记录日志就和通过printf发送一样简单。在编译时间,各种类型是系统自动检测的。
特别有价值的一点是它具有将多人游戏会话记录到一个单独日志文件的功能。这功能使得开发者可以通过LAN查看多人游戏会话,仅仅在一台机子上就可以实现。与自动数据报记录和网络统计功能结合,这个功能使得高精确度的多人会话分析变得可能。
sqliteServerLoggerPlugin
sqliteServerLoggerPlugin从sqliteLogger派生而来,增加了将从sqliteClientLogger发来的日志写到日志文件的功能。启动这个插件,可以运行工程DependentExtensions\sqlite3Plugin\ServerOnly\sqliteServerLoggerSample.cpp。在VS2005解决方案中,可以在Samples/sqlite3Plugin/sqliteServerLogger。
新的sql日志文件可以手动指定,或者自动创建。手动指定log文件,需要创建和注册这些文件,方法与sqliteLogger相同。例如,如下代码是创建一个内存数据库。
if (sqlite3_open_v2(":memory:",&database,sqlITE_OPEN_READWRITE | sqlITE_OPEN_CREATE,0)!=sqlITE_OK)
{
return 1;
}
static const char* DATABASE_IDENTIFIER="ConnectionStateDBInMemory";
sqlite3ServerPlugin.AddDBHandle(DATABASE_IDENTIFIER,database);
基于新的客户端会话自动创建日志文件,使用CREATE_EACH_NAMED_DB_HANDLE 或者CREATE_SHARED_NAMED_DB_HANDLE 作为参数调用方法sqliteServerLoggerPlugin::SetSessionManagementMode()实现。CREATE_EACH_NAMED_DB_HANDLE会为每一个发送日志的新的连接创建一个日志文件。CREATE_SHARED_NAMED_DB_HANDLE参数指定每一次新的连接发送日志在工作目录下创建一个新的日志文件,如果所有的连接都断开了,关闭该文件。参考sqliteServerLoggerPlugin.h获得更多设置的详细信息。
使用TCP最小化服务器设置
PacketizedTCP packetizedTCP;
RakNet::sqliteServerLoggerPlugin loggerPlugin;
loggerPlugin.SetSessionManagementMode(RakNet::sqliteServerLoggerPlugin::CREATE_SHARED_NAMED_DB_HANDLE,true,"");
packetizedTCP.AttachPlugin(&loggerPlugin);
packetizedTCP.Start(38123,8);
当原始图像数据发送到服务器时,如果客户端(更多关于客户端的信息参考下面的客户端部分)指定了要压缩,服务器会自动压缩该图片。如果图片的数量或大小太频繁保持cpu使用率很高,服务器可以开启基于DXT压缩的硬件支持。使用sqliteServerLoggerPlugin::SetEnableDXTCompression(true)方法开启这个设置。这要求服务器有一个硬件的3D加速卡。如果设置失败,服务器自动使用JPEG压缩代替。JPEG压缩生成更小的文件,那么如果cpu持续利用率很高,这也是一个不错的选择。
sqliteClientLoggerPlugin
客户端的源码与你的应用程序集成。你需要将目录DependentExtensions\sqlite3Plugin\ClientOnly下的所有的文件加入到应用程序中,除了文件sqliteClientLogger_PacketLogger.h/.cpp 和 sqliteClientLogger_RNSLogger.h/cpp等是可选的。他们是用于记录所有数据报日志的的插件,和RakNet统计。此外你的程序中还必须要加入DependentExtensions\sqlite3Plugin\sqliteLoggerCommon.h/.cpp文件。
如果你的应用程序并没有使用RakNet,也需要加入/Sources目录下的RakNet源码文件。如果需要,可以参考Compiler Setup一节。
此节也有一个视频教程。
使用TCP最小化客户端的设置
PacketizedTCP packetizedTCP;
RakNet::sqliteClientLoggerPlugin loggerPlugin;
packetizedTCP.AttachPlugin(&loggerPlugin);
packetizedTCP.Start(0,0);
SystemAddress serverAddress = packetizedTCP.Connect("127.0.0.1",38123,true);
// 假设连接完成了,参考TCPInterface::HasNewIncomingConnection()方法
loggerPlugin.SetServerParameters(serverAddress,"functionLog.sqlite");
在这种情况下,我们假设服务器位于本地(127.0.0.1)的38123端口上。这个端口可以任意选择,它是你的服务器所选择的端口号。
“functionLog.sqlite”是传递给sqlite3ServerPlugin::AddDBHandle()方法的第一个参数的名字。然而,如果在服务器使用的是CREATE_EACH_NAMED_DB_HANDLE 或者CREATE_SHARED_NAMED_DB_HANDLE参数,这个会被创建。对于应用程序使用相同的名字没有问题,因为这些文件是在不同的目录下存储的。事实上,对于多人游戏,你希望所有的系统使用相同的名字,那么所有的日志存进了相同的文件,可以按照时间相关进行对比。
要限制系统使用的内存的数量,调用函数sqliteClientLoggerPlugin::SetMemoryConstraint(unsigned int constraint)进行设置。如果发送的数据非常多,对内存的限制设置很有必要。否则,如果服务器崩溃,应用程序会消耗很多内存,直到得到服务器崩溃的通知。
记录日志(Logging)
所有的函数调用记录日志,记录到一个单独表中,然而函数调用的参数列表记录进入另外一个数据表。表的名称在sqliteServerLoggerPlugin.cpp的顶部进行了定义。
#define FUNCTION_CALL_TABLE 'functionCalls'
#define FUNCTION_CALL_PARAMETERS_TABLE 'functionCallParameters'
所有的参数按照字符串存储。
记录一个函数调用,可以使用定义rakFnLog("function name",(parameterList));。
例如:
RakNet::sqlLogResult res;
int x=1;
unsigned short y=2;
float c=3;
double d=4;
char *e="HI";
res = rakFnLog("My func",(x,y,c,d,e));
RakAssert(res==RakNet::sqlLR_OK);
注意参数列表旁边的括号。对于宏自动记录在C++中使用的__FILE__和__LINE__文件这是必须的。
返回值不是必须进行检验,但是你第一次使用该系统检验是非常好的习惯。如果没有适当地设置系统,该调用会失败。
所有其他类型的日志:
记录日志使用宏定义raksqlLog("table name","column1,column2,column3...",(parameterList));
例如:
raksqlLog("sqlLog","handle,mapName,positionX,positionY,positionZ,gameMode,connectedPlayers",("handle1","mapname1",1,2,3,"",4));
raksqlLog("sqlLog",("handle2","mapname2",5,6,7,"gameMode2",8));
raksqlLog("sqlLog","x",(999));
第一行代码会在数据库sqlLog中创建一个新的数据表。数据表有7列:handle,connectedPlayers。列的类型是基于参数列表类型的,在这种情况下,两个字符串,紧跟着3个数字,后面是另外一个字符串,以及另外一个数字。
第二行会增加一行到数据表中。注意—如果在参数列表中的类型没有符合这点,例如,如果第一个参数想要发送一个数字而不是一个字符串,那么在服务器端的调用会失败。
第三行会增加一列’x’到数据表,类型是整形,值是999。
通过宏,__FILE__和__LINE__的值也自动发送到服务器。
Tick计数
多数的游戏通过离散的ticks更新仿真。在客户端的Tick是随着日志数据自动发送到服务器。通过调用sqliteClientLoggerPlugin::IncrementAutoTickCount()更新tick计数。在用于简单步进动画Echo Chamber中支持Ticks。
二进制数据:
使用BlobDescriptor结构体将两个参数封装整合到一个值中。
raksqlLog("blobTable","blobColumn",( &RakNet::BlobDescriptor(bytes,byteLength) ));
图象数据:
使用RGBImageBlob结构体将相关的参数封装整合进参数列表的一个值中。
RGBImageBlob(void *_data,uint16_t _imageWidth,uint16_t _imageHeight,uint16_t _linePitch,unsigned char _input_components,ImageBlobCompressionMode mode=DXT);
第一个参数是要发送的数据。第二个和第三个参数是图象维数。_linePitch参数是_data每行的字节数。_input_components参数对于RGB文件应该设置为3,如果是RGBA文件则设置为4。mode,ImageBlobCompressionMode的值,应该是首选的编码模式。如果制定了DXT,但是不支持或在服务器设置失败,那么使用JPEG代替。
如下是一个来自sqliteClientLoggerSample.cpp的例子。
raksqlLog("gradient","gradientImage",( &RakNet::RGBImageBlob(bytes,4096,4096*4,4) ));
By 北洋小郭
转载请注明出处,请勿用于商业用途,谢谢!
原文链接:https://www.f2er.com/sqlite/202047.html