一日一点RakNet(51)--SQLite3LoggerPlugin设置

SQLite3LoggerPlugin设置

概览

RakNetSQLLite日志系统允许任何支持TCP的系统向远端服务器发送日志。日志自动包含了源文件和行,以及日志发送的时间,发送者的IP地址。日志系统支持实时时间DXT1压缩,允许游戏会话的视频重放。记录日志并不需要SQL知识,事实上通过RakNet记录日志就和通过printf发送一样简单。在编译时间,各种类型是系统自动检测的。

特别有价值的一点是它具有将多人游戏会话记录到一个单独日志文件的功能。这功能使得开发者可以通过LAN查看多人游戏会话,仅仅在一台机子上就可以实现。与自动数据报记录和网络统计功能结合,这个功能使得高精确度的多人会话分析变得可能。

SQLiteServerLoggerPlugin

SQLiteServerLoggerPluginSQLiteLogger派生而来,增加了将从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文件则设置为4modeImageBlobCompressionMode的值,应该是首选的编码模式。如果制定了DXT,但是不支持或在服务器设置失败,那么使用JPEG代替。

如下是一个来自SQLiteClientLoggerSample.cpp的例子。

rakSqlLog("gradient","gradientImage",( &RakNet::RGBImageBlob(bytes,4096,4096*4,4) ));

By 北洋小郭

转载请注明出处,请勿用于商业用途,谢谢!

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


SQLite架构简单,又有Json计算能力,有时会承担Json文件/RESTful的计算功能,但SQLite不能直接解析Json文件/RESTful,需要用Java代码硬写,或借助第三方类库,最后再拼成insert语句插入数据表,代码非常繁琐,这里就不展示了。参考前面的代码可知,入库的过程比较麻烦,不能只用SQL,还要借助Java或命令行。SPL是现代的数据计算语言,属于简化的面向对象的语言风格,有对象的概念,可以用点号访问属性并进行多步骤计算,但没有继承重载这些内容,不算彻底的面向对象语言。...
使用Python操作内置数据库SQLite以及MySQL数据库。
破解微信数据库密码,用python导出微信聊天记录
(Unity)SQLite 是一个软件库,实现了自给自足的、无服务器的、零配置的、事务性的 SQL 数据库引擎。SQLite 是在世界上最广泛部署的 SQL 数据库引擎。SQLite 源代码不受版权限制。本教程将告诉您如何使用 SQLite 编程,并让你迅速上手。.................................
安卓开发,利用SQLite实现登陆注册功能
相比大多数数据库而言,具有等优势,广泛应用于、等领域。
有时候,一个项目只有一个数据库,比如只有SQLite,或者MySQL数据库,那么我们只需要使用一个固定的数据库即可。但是一个项目如果写好了,有多个用户使用,但是多个用户使用不同的数据库,这个时候,我们就需要把软件设计成可以连接多个数据库的模式,用什么数据库,就配置什么数据库即可。4.Users实体类,这个实体类要和数据库一样的,形成一一对应的关系。11.Sqlite数据库,需要在代码里面创建数据库,建立表,再建立数据。8.我们开启MySQL数据库,然后进行调试,看程序的结果。2.安装SqlSugar。
基于Android的背单词软件,功能强大完整。
SQLite,是一款轻型的数据库,是遵守ACID的关系型数据库管理系统。说白了就是使用起来轻便简单,
Android的简单购物车案例
SQLite,是一款轻型的数据库,是遵守ACID的关系型数据库管理系统,它包含在一个相对小的C库中。它是D.RichardHipp建立的公有领域项目。它的设计目标是嵌入式的,而且已经在很多嵌入式产品中使用了它,它占用资源非常的低,在嵌入式设备中,可能只需要几百K的内存就够了。它能够支持Windows/Linux/Unix等等主流的操作系统,同时能够跟很多程序语言相结合,比如 Tcl、C#、PHP、Java等,还有ODBC接口,同样比起Mysql、PostgreSQL这两款开源的世界著名数据库...
Qt设计较为美观好看的登录注册界面(包含SQLite数据库以及TCP通信的应用)
SQLite是用C语言开发的跨平台小型数据库,可嵌入其他开发语言,也可在单机执行。SPL是用Java开发的跨平台的数据计算语言,可嵌入Java,可在单机执行,可以数据计算服务的形式被远程调用。两者的代码都是解释执行的。...
新建库.openDATA_BASE;新建表createtableLIST_NAME(DATA);语法:NAME关键字...<用逗号分割>删除表droptableNAME;查看表.schema查看表信息新建数据insertintoLIST_NAMEvalues();语法:CLASS,PARAMETER...,CLASS是类别,PARAMETER是参数<用逗号分割新建的
importsqlite3classDemo01:def__init__(self):self.conn=sqlite3.connect("sql_demo_001.db")self.cursor1=self.conn.cursor()self.cursor1.execute("select*fromtable_001wherename=?andid=?",('ssss&#0
 在客户端配置文件<configuration>节点下,添加:<connectionStrings>      <add name="localdb" connectionString="Data Source=config/local.db;Version=3;UseUTF16Encoding=True;" providerName="System.Data.SQLite.SQLiteFactory"/&g
提到锁就不得不说到死锁的问题,而SQLite也可能出现死锁。下面举个例子:连接1:BEGIN(UNLOCKED)连接1:SELECT...(SHARED)连接1:INSERT...(RESERVED)连接2:BEGIN(UNLOCKED)连接2:SELECT...(SHARED)连接1:COMMIT(PENDING,尝试获取EXCLUSIVE锁,但还有SHARED锁未释放,返回SQLITE_BUSY)连接2:INSERT...
SQLite是一种嵌入式数据库,它的数据库就是一个文件。由于SQLite本身是C写的,而且体积很小,所以,经常被集成到各种应用程序中,甚至在iOS和Android的App中都可以集成。Python就内置了SQLite3,所以,在Python中使用SQLite,不需要安装任何东西,直接使用。在使用SQLite前,我们先要搞清楚几个概念:表
设计思想————首先要确定有几个页面、和每个页面的大致布局由于是入门,我也是学习了不是很长的时间,所以项目比较low。。。。第一个页面,也就是打开APP的首页面:今天这个博客,先实现添加功能!:首先对主界面进行布局:其中activity_main.xml的代码为<?xmlversion="1.0"encoding="