superzmy edited this page Mar 3, 2016 · 16 revisions

此章节整理开发中碰到问题总结的FAQ

在使用Scut中有碰到的问题尽量提交到论坛中,更方便我们整理。

##Scut开发问题

  • Scut同时在线人数能达到多少?

同时在线人数跟CPU,内存,带宽都有关系的,具体性能见负载测试报告

服务器配置计量方法:

  • CPU:依据业务的运算量,较大可配置高些,8核基本应该够用;
  • 内存:以1个用户占1M计算;
  • 带宽:以1个用户按60K计算,这个是每秒并发人数,不是在线人数;
  • 启动时提示"NIC is not connected or no network"出错?

说明本机机器的网络有问题

  • 检查127.0.0.1是否能Ping通,并且关掉防火墙试试;
  • 检测网卡是否是正确版本,不正确需要升级;
  • 检查是否有多个网卡或外接wifi,禁用再试试。
  • 启动时提示"Redis Server is using Ip game server, it's path..."或"Server failed to start error:The game server is using Redis at host nam e "oneHostName" path D:\xxx\xxx."

说明Redis服务被其它的程序使用了,进入命令行窗口,使用redis-cli客户端删除"__RedisInfo"的键; 脚本如下:

> redis-cli -h 127.0.0.1 -p 6379
# 切换使用的Redis.DB
> select 0;
> del __RedisInfo;
select 0的0根据你的游戏redis数据库序号填写

一般的服务器是 一个Server对应一个Redis部署, 再扩新服时,会需要copy配置文件,由于人为原因可以会漏改配置文件,造成新服与旧服共用了一个存储区域,数据混乱掉;因此增加限制;如果不是这种一个Server对应一个Redis的架构, 可以增加配置键:

<add key="Slave.MessageQueue" value="Slave" />

6.7.9.10版本调整为使用机器名+路径绑定

  • Csscript目录下的脚本文件在VS中没有智能提示?

检查脚本文件的属性,是否是编译的方式;另外注意在Game项目中的Script目录下的文件不能设置编译的方式,因为它是以动态运行的,不能把这些脚本编译在exe中,会与动态编译的冲突。

  • 如何在项目中调试SCUT FRAMEWORK?

首先.net调试是需要*.pdb文件的,打开Scut 的Framework解决方案,编译Source, 接着双击“发布处理.bat”批处理文件将dll发布到上一级的Release目录下(需要xcopy命令支持); 接着将Release/Lib目录下的dll复制到项目中即可;要调试Source的某个文件, 只需要将文件拖到项目中并设置断点,再按F5运行当前项目;断点有生成显示的是实心的红色圆点, 如果是穿心圆点说明文件与dll里的版本不一致,需要重新按以上步骤替换dll。

  • 打开SCUT项目编译USING错误?

Scut要求是在.Net Framework 4.5.1以上版本运行的,检查是否有安装VS2013或.Net Framework 4.5.1运行时环境;在项目属性的生成选项以“.Net Framework 4.5.1”编译。

  • 代码中如何查USING的命名空间?

在VS中将鼠标移到需要增加using命名空间的类上,会在旁边显示一个小图标,下拉选中using的命名空间,VS会自动帮助你加到文件using部分;或者安装一个代码生成工具VS插件ReSharper(QQ群文件有提供),提高编码效率。

  • 是否有实现同一个帐号再次登录挤掉的功能?

使用AuthorizeAction类判断GameSession对象的OldSessionId属性来识别。

  • 渠道登录中间件配置的ID如何设置?

配置的ID是通过客户端上传的RetailID参数来区分的,可以自己分配, 与客户端对应上就可以。

  • 实体属性修改后没有保存到Redis和DB中?

Model是否是独立另一个项目,需要使用IL打开Model.dll检查Entity的Set属性代码是否有调用BindAndNotify或BindAndChangeProperty方法,没有需要在项目.csproj配置注入脚本;Model是以脚本方式,需要检查Entity的SchemaTable配置,只读或只写属性不会触发Changed事件。

  • 游戏服的缓存数据是如何更新的?

每个实体的属性都绑定有Changed事件,当属性发现设置值,新增和删除实体时时会触发事件,所有Change事件会提交到Redis的消息队列中(Key以“__”开头); 由另一线程监控这个消息队列(每100毫秒),当有新消息时会将数据更新到Redis的Model存储区中(key以“$”开头),更新失败将存储到Redis的Error消息队列;根据config配置中的“EnableWriteToDb”键和实体SchemaTable属性的“IsStoreInDb”值判断是否要更新到数据库,为了降低数据库的IO高,需要更新数据库的实体先放到等待消息队列中,间隔(每五分钟)一段时间将实体转换成sql语句放入Sql执行消息队列中,Sql执行消息队列启动线程(配置10个线程)每100毫秒执行写入到数据库,如果执行出错将Sql语句存储到Redis的Sql Error消息队列。

  • 为什么数据库表里的数据修改了在游戏服缓存中没有?

原因是游戏服从数据库或Redis取出数据后会缓存在游戏服中,不会每次从数据库或Redis中取了,当游戏服的数据改变时会更新到数据库或Redis,在数据库或Redis修改数据是会被覆盖;当游戏服关掉重启时才会再次从数据库或Redis取数据;另外配置实体是只读类型的才会从数据库取数据,其它的只从Redis取数据,原因Scut是以Redis作为主要存储。

  • REDIS客户端查看存储的数据是否能显示JSON的格式?

可以在项目的Config配置中增加键“Cache.Serializer”值为“Json”,使用Json序列化的方式存储,设置前需要将Redis的数据清除,不能混合使用;建议在开发阶段使用Json,发布时使用“Protobuf”序列化的存储,减少Redis内存使用量。

  • 日志表增长比较大如何处理?

日志表比较大时,可以对表以日期水平方式分割,减小单张表的存储容量;在Model中定义一个Log类型的实体模型,并设置表名以“年月”或“年月日”的规则生成表,;设置EntityTable的“TableNameFormat”属性为“Log$date[yyyyMM]_{0}”(ex: Log201408_TableName)。

  • Model实体设计如何返回GetIdentity方法的值?

GetIdentity是对实体数据分类的ID,如:背包数据它的主键是ItemID(自增的),UserId(归属玩家),那么可以用UserId分类,GetIdentity返回UserId属性值,而不能用主键ItemID,如果一定要用ItemID,那么可以使用Share类型的结构(ShareEntity); 使用new PersonalCacheStruct().FindKey(参数1),参数1就是GetIdentity()的值。

  • 使用GameHttpHost时提示Httplistener监听启动拒绝问题?

检查GameServer.exe启动是否使用管理员帐号运行

  • 玩家离线怎么通知应用层和断线重连怎么处理?

当Socket断线时会调用MainClass类中有OnDisconnected方法,这此处理业务层逻辑;断线重连根据sid参数自动恢复连接,不需要自己处理。

  • 如何在游戏服内调用WebService服务?

首先右击项目的“引用”,选择“添加服务引用”,在弹出的窗口地址输入WebService服务地址后,点“确定”;VS会自动生成的调用WebService服务的调用代码和配置文件,需要将Reference.cs文件Copy到Script/CsScript/References目录下;另外找到“app.config”配置文件,将“system.serviceModel”结点的配置复制到“GameServer.exe.config”中。

  • 在线用户如何获取?

所有的会话都是由GameSession管理的,GameSession.GetOnlineAll方法可以获取在线玩家。

  • 传输过程有没有对数据加密?

没有对数据加密,有对请求数据做签名较验,可以在Config配置“Product.SignKey”,注意需要跟客户端的签名Key一致。

  • 不需要身份较验访问ACTION如何处理?

在Action类中重写IgnoreActionId属性,并返回false。

  • 请求的身份认证如何处理?

客户端请求时服务器会分配一个GameSession对象,登陆时较验用户帐号与密码,成功后调用GameSession对象Bind方法绑定身份。

  • SCUT的二进制协议流粘包如何处理?

在包的前面增加一个int的长度表示包的字节大小,拆包时先读取4位字节转换成int类型的长度(L),接着判断剩余包的长度大于等于L时,说明包已经全部接收完,读取L长度的字节;如果长度小于L时,则继续等待。

  • 通讯协议的头部ST字段的作用是什么?

头部St字段是一个时间缀(预留字段),表示这次的请求有效期多久,防止请求被拦截后发起恶意的请求,增加安全性,目前只使用签名较验,这个字段暂时未启用。

  • 通讯协议的头部SID和UID如何获取值?

Sid表示请求的会话ID,在客户连接成功后由服务器自己产生;Uid是用户登录成功后的身份标识,由帐号中心分配唯一的编号,在未登录前的请求客户端给sid的值空串,Uid的值0;登录成功后服务器下发sid和Uid,客户接收到需要存储起来,下一请求时上传sid和uid的值。

  • ACTION协议的方法执行顺序?

调用顺序是GetUrlElement (获取请求参数处理)->TakeAction(处理逻辑)->BuildPacket(封包下发)。

  • Scut Socket的IO是阻塞还是非阻塞模型?

接收数据是异步阻塞模型,IO使用的缓冲区是复用的。

  • SCUT支持HTTP短连接吗?

使用Consele控制台开启Http监听,在config配置中设置"Game.Http.Host"为"127.0.0.1",在IE中访问[http://127.0.0.1:8080/Service.aspx] ,(注: 6.7.9.0以上版本去掉对IIS部署的支持)

  • SCUT支持WebSocket连接吗?

支持,在6.7.9.5以上版本对WebSocket提供支持。

  • 如何配置Game.Script.DecodeFunc.Typename脚本加密发布?

Scut有提供一个加密脚本类库(ScutSecurity),它的密钥写在代码里,可以自己根据需要更换,使用时需要在Config中配置值为"ScutSecurity.ScriptDes,ScutSecurity",并从Release\Lib目录复制ScutSecurity.dll到项目中;在开发阶段可以注释掉这个配置,在发布时自己写工具批量加密脚本文件,并启用此配置。

  • 提示找不到相应的Action,报10000错误码怎么处理?

检查Script目录下是否有这个Action文件,检查Action文件的命名空间与GameServer.exe.config配置文件中"Game.Action.Script.TypeName"的是否一致

##Scut Sample问题

  • 客户端登陆没有反应或连接不上问题?

客户端在代码中设置的服务器地址是以域名(ddz.scutgame.com)的方式访问的,需要在本机Host文件中设置ddz.scutgame.com的域名转向,使用命令“telnet ddz.scutgame.com 9001”检测,或者客户端的请求连接地址改为本机IP(NetHelper.lua文件里配置);如果连接是成功的,检查服务器的Log\Exception目录是否有异常日志,有提示“SQL server error 40”错误的是服务器的连接字符串配置有问题。

##协议工具问题

协议工具需要部署在IIS7.0以上版本上,需要安装.NET 4.0以上版本;生成代码功能并不是生成可执行的代码,有些上方需要手动修改。

  • 协议工具部署完成后,打开页面显示iframe错误?

检查Web.config的配置;检查C:\windows\Temp目录给everyone用户加上读写目录的权限;IIS网站根目录“功能视图”的“ISAPI和CGI限制”中“ASP.NET V4.0”是否配置有允许。

  • 页面按钮点击没有反应?

检查Log目录下的是否有异常,如果是数据库出错检查下连接字串符串的配置是否正确;使用Mysql数据库时要注意下server配置使用“.”号的问题,换成“localhost”试试。

  • 协议工具有没有说明文档?

如何使用协议工具平台

##客户端SDK使用问题

  • 服务器推送Unity3d的消息怎么接收?

Unity请求的与推送的消息都是由线程监听,通过SocketConnect类的CheckReceive方法检测是否有消息,如果是推送的消息MsgId为0,转向到注册的OnPushCallback回调方法处理,Net类中处理回调会将消息分发到指定的Action协议处理。

Clone this wiki locally

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content
superzmy edited this page Mar 3, 2016 · 16 revisions

此章节整理开发中碰到问题总结的FAQ

在使用Scut中有碰到的问题尽量提交到论坛中,更方便我们整理。

##Scut开发问题

  • Scut同时在线人数能达到多少?

同时在线人数跟CPU,内存,带宽都有关系的,具体性能见负载测试报告

服务器配置计量方法:

  • CPU:依据业务的运算量,较大可配置高些,8核基本应该够用;
  • 内存:以1个用户占1M计算;
  • 带宽:以1个用户按60K计算,这个是每秒并发人数,不是在线人数;
  • 启动时提示"NIC is not connected or no network"出错?

说明本机机器的网络有问题

  • 检查127.0.0.1是否能Ping通,并且关掉防火墙试试;
  • 检测网卡是否是正确版本,不正确需要升级;
  • 检查是否有多个网卡或外接wifi,禁用再试试。
  • 启动时提示"Redis Server is using Ip game server, it's path..."或"Server failed to start error:The game server is using Redis at host nam e "oneHostName" path D:\xxx\xxx."

说明Redis服务被其它的程序使用了,进入命令行窗口,使用redis-cli客户端删除"__RedisInfo"的键; 脚本如下:

> redis-cli -h 127.0.0.1 -p 6379
# 切换使用的Redis.DB
> select 0;
> del __RedisInfo;
select 0的0根据你的游戏redis数据库序号填写

一般的服务器是 一个Server对应一个Redis部署, 再扩新服时,会需要copy配置文件,由于人为原因可以会漏改配置文件,造成新服与旧服共用了一个存储区域,数据混乱掉;因此增加限制;如果不是这种一个Server对应一个Redis的架构, 可以增加配置键:

<add key="Slave.MessageQueue" value="Slave" />

6.7.9.10版本调整为使用机器名+路径绑定

  • Csscript目录下的脚本文件在VS中没有智能提示?

检查脚本文件的属性,是否是编译的方式;另外注意在Game项目中的Script目录下的文件不能设置编译的方式,因为它是以动态运行的,不能把这些脚本编译在exe中,会与动态编译的冲突。

  • 如何在项目中调试SCUT FRAMEWORK?

首先.net调试是需要*.pdb文件的,打开Scut 的Framework解决方案,编译Source, 接着双击“发布处理.bat”批处理文件将dll发布到上一级的Release目录下(需要xcopy命令支持); 接着将Release/Lib目录下的dll复制到项目中即可;要调试Source的某个文件, 只需要将文件拖到项目中并设置断点,再按F5运行当前项目;断点有生成显示的是实心的红色圆点, 如果是穿心圆点说明文件与dll里的版本不一致,需要重新按以上步骤替换dll。

  • 打开SCUT项目编译USING错误?

Scut要求是在.Net Framework 4.5.1以上版本运行的,检查是否有安装VS2013或.Net Framework 4.5.1运行时环境;在项目属性的生成选项以“.Net Framework 4.5.1”编译。

  • 代码中如何查USING的命名空间?

在VS中将鼠标移到需要增加using命名空间的类上,会在旁边显示一个小图标,下拉选中using的命名空间,VS会自动帮助你加到文件using部分;或者安装一个代码生成工具VS插件ReSharper(QQ群文件有提供),提高编码效率。

  • 是否有实现同一个帐号再次登录挤掉的功能?

使用AuthorizeAction类判断GameSession对象的OldSessionId属性来识别。

  • 渠道登录中间件配置的ID如何设置?

配置的ID是通过客户端上传的RetailID参数来区分的,可以自己分配, 与客户端对应上就可以。

  • 实体属性修改后没有保存到Redis和DB中?

Model是否是独立另一个项目,需要使用IL打开Model.dll检查Entity的Set属性代码是否有调用BindAndNotify或BindAndChangeProperty方法,没有需要在项目.csproj配置注入脚本;Model是以脚本方式,需要检查Entity的SchemaTable配置,只读或只写属性不会触发Changed事件。

  • 游戏服的缓存数据是如何更新的?

每个实体的属性都绑定有Changed事件,当属性发现设置值,新增和删除实体时时会触发事件,所有Change事件会提交到Redis的消息队列中(Key以“__”开头); 由另一线程监控这个消息队列(每100毫秒),当有新消息时会将数据更新到Redis的Model存储区中(key以“$”开头),更新失败将存储到Redis的Error消息队列;根据config配置中的“EnableWriteToDb”键和实体SchemaTable属性的“IsStoreInDb”值判断是否要更新到数据库,为了降低数据库的IO高,需要更新数据库的实体先放到等待消息队列中,间隔(每五分钟)一段时间将实体转换成sql语句放入Sql执行消息队列中,Sql执行消息队列启动线程(配置10个线程)每100毫秒执行写入到数据库,如果执行出错将Sql语句存储到Redis的Sql Error消息队列。

  • 为什么数据库表里的数据修改了在游戏服缓存中没有?

原因是游戏服从数据库或Redis取出数据后会缓存在游戏服中,不会每次从数据库或Redis中取了,当游戏服的数据改变时会更新到数据库或Redis,在数据库或Redis修改数据是会被覆盖;当游戏服关掉重启时才会再次从数据库或Redis取数据;另外配置实体是只读类型的才会从数据库取数据,其它的只从Redis取数据,原因Scut是以Redis作为主要存储。

  • REDIS客户端查看存储的数据是否能显示JSON的格式?

可以在项目的Config配置中增加键“Cache.Serializer”值为“Json”,使用Json序列化的方式存储,设置前需要将Redis的数据清除,不能混合使用;建议在开发阶段使用Json,发布时使用“Protobuf”序列化的存储,减少Redis内存使用量。

  • 日志表增长比较大如何处理?

日志表比较大时,可以对表以日期水平方式分割,减小单张表的存储容量;在Model中定义一个Log类型的实体模型,并设置表名以“年月”或“年月日”的规则生成表,;设置EntityTable的“TableNameFormat”属性为“Log$date[yyyyMM]_{0}”(ex: Log201408_TableName)。

  • Model实体设计如何返回GetIdentity方法的值?

GetIdentity是对实体数据分类的ID,如:背包数据它的主键是ItemID(自增的),UserId(归属玩家),那么可以用UserId分类,GetIdentity返回UserId属性值,而不能用主键ItemID,如果一定要用ItemID,那么可以使用Share类型的结构(ShareEntity); 使用new PersonalCacheStruct().FindKey(参数1),参数1就是GetIdentity()的值。

  • 使用GameHttpHost时提示Httplistener监听启动拒绝问题?

检查GameServer.exe启动是否使用管理员帐号运行

  • 玩家离线怎么通知应用层和断线重连怎么处理?

当Socket断线时会调用MainClass类中有OnDisconnected方法,这此处理业务层逻辑;断线重连根据sid参数自动恢复连接,不需要自己处理。

  • 如何在游戏服内调用WebService服务?

首先右击项目的“引用”,选择“添加服务引用”,在弹出的窗口地址输入WebService服务地址后,点“确定”;VS会自动生成的调用WebService服务的调用代码和配置文件,需要将Reference.cs文件Copy到Script/CsScript/References目录下;另外找到“app.config”配置文件,将“system.serviceModel”结点的配置复制到“GameServer.exe.config”中。

  • 在线用户如何获取?

所有的会话都是由GameSession管理的,GameSession.GetOnlineAll方法可以获取在线玩家。

  • 传输过程有没有对数据加密?

没有对数据加密,有对请求数据做签名较验,可以在Config配置“Product.SignKey”,注意需要跟客户端的签名Key一致。

  • 不需要身份较验访问ACTION如何处理?

在Action类中重写IgnoreActionId属性,并返回false。

  • 请求的身份认证如何处理?

客户端请求时服务器会分配一个GameSession对象,登陆时较验用户帐号与密码,成功后调用GameSession对象Bind方法绑定身份。

  • SCUT的二进制协议流粘包如何处理?

在包的前面增加一个int的长度表示包的字节大小,拆包时先读取4位字节转换成int类型的长度(L),接着判断剩余包的长度大于等于L时,说明包已经全部接收完,读取L长度的字节;如果长度小于L时,则继续等待。

  • 通讯协议的头部ST字段的作用是什么?

头部St字段是一个时间缀(预留字段),表示这次的请求有效期多久,防止请求被拦截后发起恶意的请求,增加安全性,目前只使用签名较验,这个字段暂时未启用。

  • 通讯协议的头部SID和UID如何获取值?

Sid表示请求的会话ID,在客户连接成功后由服务器自己产生;Uid是用户登录成功后的身份标识,由帐号中心分配唯一的编号,在未登录前的请求客户端给sid的值空串,Uid的值0;登录成功后服务器下发sid和Uid,客户接收到需要存储起来,下一请求时上传sid和uid的值。

  • ACTION协议的方法执行顺序?

调用顺序是GetUrlElement (获取请求参数处理)->TakeAction(处理逻辑)->BuildPacket(封包下发)。

  • Scut Socket的IO是阻塞还是非阻塞模型?

接收数据是异步阻塞模型,IO使用的缓冲区是复用的。

  • SCUT支持HTTP短连接吗?

使用Consele控制台开启Http监听,在config配置中设置"Game.Http.Host"为"127.0.0.1",在IE中访问[http://127.0.0.1:8080/Service.aspx] ,(注: 6.7.9.0以上版本去掉对IIS部署的支持)

  • SCUT支持WebSocket连接吗?

支持,在6.7.9.5以上版本对WebSocket提供支持。

  • 如何配置Game.Script.DecodeFunc.Typename脚本加密发布?

Scut有提供一个加密脚本类库(ScutSecurity),它的密钥写在代码里,可以自己根据需要更换,使用时需要在Config中配置值为"ScutSecurity.ScriptDes,ScutSecurity",并从Release\Lib目录复制ScutSecurity.dll到项目中;在开发阶段可以注释掉这个配置,在发布时自己写工具批量加密脚本文件,并启用此配置。

  • 提示找不到相应的Action,报10000错误码怎么处理?

检查Script目录下是否有这个Action文件,检查Action文件的命名空间与GameServer.exe.config配置文件中"Game.Action.Script.TypeName"的是否一致

##Scut Sample问题

  • 客户端登陆没有反应或连接不上问题?

客户端在代码中设置的服务器地址是以域名(ddz.scutgame.com)的方式访问的,需要在本机Host文件中设置ddz.scutgame.com的域名转向,使用命令“telnet ddz.scutgame.com 9001”检测,或者客户端的请求连接地址改为本机IP(NetHelper.lua文件里配置);如果连接是成功的,检查服务器的Log\Exception目录是否有异常日志,有提示“SQL server error 40”错误的是服务器的连接字符串配置有问题。

##协议工具问题

协议工具需要部署在IIS7.0以上版本上,需要安装.NET 4.0以上版本;生成代码功能并不是生成可执行的代码,有些上方需要手动修改。

  • 协议工具部署完成后,打开页面显示iframe错误?

检查Web.config的配置;检查C:\windows\Temp目录给everyone用户加上读写目录的权限;IIS网站根目录“功能视图”的“ISAPI和CGI限制”中“ASP.NET V4.0”是否配置有允许。

  • 页面按钮点击没有反应?

检查Log目录下的是否有异常,如果是数据库出错检查下连接字串符串的配置是否正确;使用Mysql数据库时要注意下server配置使用“.”号的问题,换成“localhost”试试。

  • 协议工具有没有说明文档?

如何使用协议工具平台

##客户端SDK使用问题

  • 服务器推送Unity3d的消息怎么接收?

Unity请求的与推送的消息都是由线程监听,通过SocketConnect类的CheckReceive方法检测是否有消息,如果是推送的消息MsgId为0,转向到注册的OnPushCallback回调方法处理,Net类中处理回调会将消息分发到指定的Action协议处理。

Clone this wiki locally

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
superzmy edited this page Mar 3, 2016 · 16 revisions

此章节整理开发中碰到问题总结的FAQ

在使用Scut中有碰到的问题尽量提交到论坛中,更方便我们整理。

##Scut开发问题

  • Scut同时在线人数能达到多少?

同时在线人数跟CPU,内存,带宽都有关系的,具体性能见负载测试报告

服务器配置计量方法:

  • CPU:依据业务的运算量,较大可配置高些,8核基本应该够用;
  • 内存:以1个用户占1M计算;
  • 带宽:以1个用户按60K计算,这个是每秒并发人数,不是在线人数;
  • 启动时提示"NIC is not connected or no network"出错?

说明本机机器的网络有问题

  • 检查127.0.0.1是否能Ping通,并且关掉防火墙试试;
  • 检测网卡是否是正确版本,不正确需要升级;
  • 检查是否有多个网卡或外接wifi,禁用再试试。
  • 启动时提示"Redis Server is using Ip game server, it's path..."或"Server failed to start error:The game server is using Redis at host nam e "oneHostName" path D:\xxx\xxx."

说明Redis服务被其它的程序使用了,进入命令行窗口,使用redis-cli客户端删除"__RedisInfo"的键; 脚本如下:

> redis-cli -h 127.0.0.1 -p 6379
# 切换使用的Redis.DB
> select 0;
> del __RedisInfo;
select 0的0根据你的游戏redis数据库序号填写

一般的服务器是 一个Server对应一个Redis部署, 再扩新服时,会需要copy配置文件,由于人为原因可以会漏改配置文件,造成新服与旧服共用了一个存储区域,数据混乱掉;因此增加限制;如果不是这种一个Server对应一个Redis的架构, 可以增加配置键:

<add key="Slave.MessageQueue" value="Slave" />

6.7.9.10版本调整为使用机器名+路径绑定

  • Csscript目录下的脚本文件在VS中没有智能提示?

检查脚本文件的属性,是否是编译的方式;另外注意在Game项目中的Script目录下的文件不能设置编译的方式,因为它是以动态运行的,不能把这些脚本编译在exe中,会与动态编译的冲突。

  • 如何在项目中调试SCUT FRAMEWORK?

首先.net调试是需要*.pdb文件的,打开Scut 的Framework解决方案,编译Source, 接着双击“发布处理.bat”批处理文件将dll发布到上一级的Release目录下(需要xcopy命令支持); 接着将Release/Lib目录下的dll复制到项目中即可;要调试Source的某个文件, 只需要将文件拖到项目中并设置断点,再按F5运行当前项目;断点有生成显示的是实心的红色圆点, 如果是穿心圆点说明文件与dll里的版本不一致,需要重新按以上步骤替换dll。

  • 打开SCUT项目编译USING错误?

Scut要求是在.Net Framework 4.5.1以上版本运行的,检查是否有安装VS2013或.Net Framework 4.5.1运行时环境;在项目属性的生成选项以“.Net Framework 4.5.1”编译。

  • 代码中如何查USING的命名空间?

在VS中将鼠标移到需要增加using命名空间的类上,会在旁边显示一个小图标,下拉选中using的命名空间,VS会自动帮助你加到文件using部分;或者安装一个代码生成工具VS插件ReSharper(QQ群文件有提供),提高编码效率。

  • 是否有实现同一个帐号再次登录挤掉的功能?

使用AuthorizeAction类判断GameSession对象的OldSessionId属性来识别。

  • 渠道登录中间件配置的ID如何设置?

配置的ID是通过客户端上传的RetailID参数来区分的,可以自己分配, 与客户端对应上就可以。

  • 实体属性修改后没有保存到Redis和DB中?

Model是否是独立另一个项目,需要使用IL打开Model.dll检查Entity的Set属性代码是否有调用BindAndNotify或BindAndChangeProperty方法,没有需要在项目.csproj配置注入脚本;Model是以脚本方式,需要检查Entity的SchemaTable配置,只读或只写属性不会触发Changed事件。

  • 游戏服的缓存数据是如何更新的?

每个实体的属性都绑定有Changed事件,当属性发现设置值,新增和删除实体时时会触发事件,所有Change事件会提交到Redis的消息队列中(Key以“__”开头); 由另一线程监控这个消息队列(每100毫秒),当有新消息时会将数据更新到Redis的Model存储区中(key以“$”开头),更新失败将存储到Redis的Error消息队列;根据config配置中的“EnableWriteToDb”键和实体SchemaTable属性的“IsStoreInDb”值判断是否要更新到数据库,为了降低数据库的IO高,需要更新数据库的实体先放到等待消息队列中,间隔(每五分钟)一段时间将实体转换成sql语句放入Sql执行消息队列中,Sql执行消息队列启动线程(配置10个线程)每100毫秒执行写入到数据库,如果执行出错将Sql语句存储到Redis的Sql Error消息队列。

  • 为什么数据库表里的数据修改了在游戏服缓存中没有?

原因是游戏服从数据库或Redis取出数据后会缓存在游戏服中,不会每次从数据库或Redis中取了,当游戏服的数据改变时会更新到数据库或Redis,在数据库或Redis修改数据是会被覆盖;当游戏服关掉重启时才会再次从数据库或Redis取数据;另外配置实体是只读类型的才会从数据库取数据,其它的只从Redis取数据,原因Scut是以Redis作为主要存储。

  • REDIS客户端查看存储的数据是否能显示JSON的格式?

可以在项目的Config配置中增加键“Cache.Serializer”值为“Json”,使用Json序列化的方式存储,设置前需要将Redis的数据清除,不能混合使用;建议在开发阶段使用Json,发布时使用“Protobuf”序列化的存储,减少Redis内存使用量。

  • 日志表增长比较大如何处理?

日志表比较大时,可以对表以日期水平方式分割,减小单张表的存储容量;在Model中定义一个Log类型的实体模型,并设置表名以“年月”或“年月日”的规则生成表,;设置EntityTable的“TableNameFormat”属性为“Log$date[yyyyMM]_{0}”(ex: Log201408_TableName)。

  • Model实体设计如何返回GetIdentity方法的值?

GetIdentity是对实体数据分类的ID,如:背包数据它的主键是ItemID(自增的),UserId(归属玩家),那么可以用UserId分类,GetIdentity返回UserId属性值,而不能用主键ItemID,如果一定要用ItemID,那么可以使用Share类型的结构(ShareEntity); 使用new PersonalCacheStruct().FindKey(参数1),参数1就是GetIdentity()的值。

  • 使用GameHttpHost时提示Httplistener监听启动拒绝问题?

检查GameServer.exe启动是否使用管理员帐号运行

  • 玩家离线怎么通知应用层和断线重连怎么处理?

当Socket断线时会调用MainClass类中有OnDisconnected方法,这此处理业务层逻辑;断线重连根据sid参数自动恢复连接,不需要自己处理。

  • 如何在游戏服内调用WebService服务?

首先右击项目的“引用”,选择“添加服务引用”,在弹出的窗口地址输入WebService服务地址后,点“确定”;VS会自动生成的调用WebService服务的调用代码和配置文件,需要将Reference.cs文件Copy到Script/CsScript/References目录下;另外找到“app.config”配置文件,将“system.serviceModel”结点的配置复制到“GameServer.exe.config”中。

  • 在线用户如何获取?

所有的会话都是由GameSession管理的,GameSession.GetOnlineAll方法可以获取在线玩家。

  • 传输过程有没有对数据加密?

没有对数据加密,有对请求数据做签名较验,可以在Config配置“Product.SignKey”,注意需要跟客户端的签名Key一致。

  • 不需要身份较验访问ACTION如何处理?

在Action类中重写IgnoreActionId属性,并返回false。

  • 请求的身份认证如何处理?

客户端请求时服务器会分配一个GameSession对象,登陆时较验用户帐号与密码,成功后调用GameSession对象Bind方法绑定身份。

  • SCUT的二进制协议流粘包如何处理?

在包的前面增加一个int的长度表示包的字节大小,拆包时先读取4位字节转换成int类型的长度(L),接着判断剩余包的长度大于等于L时,说明包已经全部接收完,读取L长度的字节;如果长度小于L时,则继续等待。

  • 通讯协议的头部ST字段的作用是什么?

头部St字段是一个时间缀(预留字段),表示这次的请求有效期多久,防止请求被拦截后发起恶意的请求,增加安全性,目前只使用签名较验,这个字段暂时未启用。

  • 通讯协议的头部SID和UID如何获取值?

Sid表示请求的会话ID,在客户连接成功后由服务器自己产生;Uid是用户登录成功后的身份标识,由帐号中心分配唯一的编号,在未登录前的请求客户端给sid的值空串,Uid的值0;登录成功后服务器下发sid和Uid,客户接收到需要存储起来,下一请求时上传sid和uid的值。

  • ACTION协议的方法执行顺序?

调用顺序是GetUrlElement (获取请求参数处理)->TakeAction(处理逻辑)->BuildPacket(封包下发)。

  • Scut Socket的IO是阻塞还是非阻塞模型?

接收数据是异步阻塞模型,IO使用的缓冲区是复用的。

  • SCUT支持HTTP短连接吗?

使用Consele控制台开启Http监听,在config配置中设置"Game.Http.Host"为"127.0.0.1",在IE中访问[http://127.0.0.1:8080/Service.aspx] ,(注: 6.7.9.0以上版本去掉对IIS部署的支持)

  • SCUT支持WebSocket连接吗?

支持,在6.7.9.5以上版本对WebSocket提供支持。

  • 如何配置Game.Script.DecodeFunc.Typename脚本加密发布?

Scut有提供一个加密脚本类库(ScutSecurity),它的密钥写在代码里,可以自己根据需要更换,使用时需要在Config中配置值为"ScutSecurity.ScriptDes,ScutSecurity",并从Release\Lib目录复制ScutSecurity.dll到项目中;在开发阶段可以注释掉这个配置,在发布时自己写工具批量加密脚本文件,并启用此配置。

  • 提示找不到相应的Action,报10000错误码怎么处理?

检查Script目录下是否有这个Action文件,检查Action文件的命名空间与GameServer.exe.config配置文件中"Game.Action.Script.TypeName"的是否一致

##Scut Sample问题

  • 客户端登陆没有反应或连接不上问题?

客户端在代码中设置的服务器地址是以域名(ddz.scutgame.com)的方式访问的,需要在本机Host文件中设置ddz.scutgame.com的域名转向,使用命令“telnet ddz.scutgame.com 9001”检测,或者客户端的请求连接地址改为本机IP(NetHelper.lua文件里配置);如果连接是成功的,检查服务器的Log\Exception目录是否有异常日志,有提示“SQL server error 40”错误的是服务器的连接字符串配置有问题。

##协议工具问题

协议工具需要部署在IIS7.0以上版本上,需要安装.NET 4.0以上版本;生成代码功能并不是生成可执行的代码,有些上方需要手动修改。

  • 协议工具部署完成后,打开页面显示iframe错误?

检查Web.config的配置;检查C:\windows\Temp目录给everyone用户加上读写目录的权限;IIS网站根目录“功能视图”的“ISAPI和CGI限制”中“ASP.NET V4.0”是否配置有允许。

  • 页面按钮点击没有反应?

检查Log目录下的是否有异常,如果是数据库出错检查下连接字串符串的配置是否正确;使用Mysql数据库时要注意下server配置使用“.”号的问题,换成“localhost”试试。

  • 协议工具有没有说明文档?

如何使用协议工具平台

##客户端SDK使用问题

  • 服务器推送Unity3d的消息怎么接收?

Unity请求的与推送的消息都是由线程监听,通过SocketConnect类的CheckReceive方法检测是否有消息,如果是推送的消息MsgId为0,转向到注册的OnPushCallback回调方法处理,Net类中处理回调会将消息分发到指定的Action协议处理。

Clone this wiki locally

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
superzmy edited this page Mar 3, 2016 · 16 revisions

此章节整理开发中碰到问题总结的FAQ

在使用Scut中有碰到的问题尽量提交到论坛中,更方便我们整理。

##Scut开发问题

  • Scut同时在线人数能达到多少?

同时在线人数跟CPU,内存,带宽都有关系的,具体性能见负载测试报告

服务器配置计量方法:

  • CPU:依据业务的运算量,较大可配置高些,8核基本应该够用;
  • 内存:以1个用户占1M计算;
  • 带宽:以1个用户按60K计算,这个是每秒并发人数,不是在线人数;
  • 启动时提示"NIC is not connected or no network"出错?

说明本机机器的网络有问题

  • 检查127.0.0.1是否能Ping通,并且关掉防火墙试试;
  • 检测网卡是否是正确版本,不正确需要升级;
  • 检查是否有多个网卡或外接wifi,禁用再试试。
  • 启动时提示"Redis Server is using Ip game server, it's path..."或"Server failed to start error:The game server is using Redis at host nam e "oneHostName" path D:\xxx\xxx."

说明Redis服务被其它的程序使用了,进入命令行窗口,使用redis-cli客户端删除"__RedisInfo"的键; 脚本如下:

> redis-cli -h 127.0.0.1 -p 6379
# 切换使用的Redis.DB
> select 0;
> del __RedisInfo;
select 0的0根据你的游戏redis数据库序号填写

一般的服务器是 一个Server对应一个Redis部署, 再扩新服时,会需要copy配置文件,由于人为原因可以会漏改配置文件,造成新服与旧服共用了一个存储区域,数据混乱掉;因此增加限制;如果不是这种一个Server对应一个Redis的架构, 可以增加配置键:

<add key="Slave.MessageQueue" value="Slave" />

6.7.9.10版本调整为使用机器名+路径绑定

  • Csscript目录下的脚本文件在VS中没有智能提示?

检查脚本文件的属性,是否是编译的方式;另外注意在Game项目中的Script目录下的文件不能设置编译的方式,因为它是以动态运行的,不能把这些脚本编译在exe中,会与动态编译的冲突。

  • 如何在项目中调试SCUT FRAMEWORK?

首先.net调试是需要*.pdb文件的,打开Scut 的Framework解决方案,编译Source, 接着双击“发布处理.bat”批处理文件将dll发布到上一级的Release目录下(需要xcopy命令支持); 接着将Release/Lib目录下的dll复制到项目中即可;要调试Source的某个文件, 只需要将文件拖到项目中并设置断点,再按F5运行当前项目;断点有生成显示的是实心的红色圆点, 如果是穿心圆点说明文件与dll里的版本不一致,需要重新按以上步骤替换dll。

  • 打开SCUT项目编译USING错误?

Scut要求是在.Net Framework 4.5.1以上版本运行的,检查是否有安装VS2013或.Net Framework 4.5.1运行时环境;在项目属性的生成选项以“.Net Framework 4.5.1”编译。

  • 代码中如何查USING的命名空间?

在VS中将鼠标移到需要增加using命名空间的类上,会在旁边显示一个小图标,下拉选中using的命名空间,VS会自动帮助你加到文件using部分;或者安装一个代码生成工具VS插件ReSharper(QQ群文件有提供),提高编码效率。

  • 是否有实现同一个帐号再次登录挤掉的功能?

使用AuthorizeAction类判断GameSession对象的OldSessionId属性来识别。

  • 渠道登录中间件配置的ID如何设置?

配置的ID是通过客户端上传的RetailID参数来区分的,可以自己分配, 与客户端对应上就可以。

  • 实体属性修改后没有保存到Redis和DB中?

Model是否是独立另一个项目,需要使用IL打开Model.dll检查Entity的Set属性代码是否有调用BindAndNotify或BindAndChangeProperty方法,没有需要在项目.csproj配置注入脚本;Model是以脚本方式,需要检查Entity的SchemaTable配置,只读或只写属性不会触发Changed事件。

  • 游戏服的缓存数据是如何更新的?

每个实体的属性都绑定有Changed事件,当属性发现设置值,新增和删除实体时时会触发事件,所有Change事件会提交到Redis的消息队列中(Key以“__”开头); 由另一线程监控这个消息队列(每100毫秒),当有新消息时会将数据更新到Redis的Model存储区中(key以“$”开头),更新失败将存储到Redis的Error消息队列;根据config配置中的“EnableWriteToDb”键和实体SchemaTable属性的“IsStoreInDb”值判断是否要更新到数据库,为了降低数据库的IO高,需要更新数据库的实体先放到等待消息队列中,间隔(每五分钟)一段时间将实体转换成sql语句放入Sql执行消息队列中,Sql执行消息队列启动线程(配置10个线程)每100毫秒执行写入到数据库,如果执行出错将Sql语句存储到Redis的Sql Error消息队列。

  • 为什么数据库表里的数据修改了在游戏服缓存中没有?

原因是游戏服从数据库或Redis取出数据后会缓存在游戏服中,不会每次从数据库或Redis中取了,当游戏服的数据改变时会更新到数据库或Redis,在数据库或Redis修改数据是会被覆盖;当游戏服关掉重启时才会再次从数据库或Redis取数据;另外配置实体是只读类型的才会从数据库取数据,其它的只从Redis取数据,原因Scut是以Redis作为主要存储。

  • REDIS客户端查看存储的数据是否能显示JSON的格式?

可以在项目的Config配置中增加键“Cache.Serializer”值为“Json”,使用Json序列化的方式存储,设置前需要将Redis的数据清除,不能混合使用;建议在开发阶段使用Json,发布时使用“Protobuf”序列化的存储,减少Redis内存使用量。

  • 日志表增长比较大如何处理?

日志表比较大时,可以对表以日期水平方式分割,减小单张表的存储容量;在Model中定义一个Log类型的实体模型,并设置表名以“年月”或“年月日”的规则生成表,;设置EntityTable的“TableNameFormat”属性为“Log$date[yyyyMM]_{0}”(ex: Log201408_TableName)。

  • Model实体设计如何返回GetIdentity方法的值?

GetIdentity是对实体数据分类的ID,如:背包数据它的主键是ItemID(自增的),UserId(归属玩家),那么可以用UserId分类,GetIdentity返回UserId属性值,而不能用主键ItemID,如果一定要用ItemID,那么可以使用Share类型的结构(ShareEntity); 使用new PersonalCacheStruct().FindKey(参数1),参数1就是GetIdentity()的值。

  • 使用GameHttpHost时提示Httplistener监听启动拒绝问题?

检查GameServer.exe启动是否使用管理员帐号运行

  • 玩家离线怎么通知应用层和断线重连怎么处理?

当Socket断线时会调用MainClass类中有OnDisconnected方法,这此处理业务层逻辑;断线重连根据sid参数自动恢复连接,不需要自己处理。

  • 如何在游戏服内调用WebService服务?

首先右击项目的“引用”,选择“添加服务引用”,在弹出的窗口地址输入WebService服务地址后,点“确定”;VS会自动生成的调用WebService服务的调用代码和配置文件,需要将Reference.cs文件Copy到Script/CsScript/References目录下;另外找到“app.config”配置文件,将“system.serviceModel”结点的配置复制到“GameServer.exe.config”中。

  • 在线用户如何获取?

所有的会话都是由GameSession管理的,GameSession.GetOnlineAll方法可以获取在线玩家。

  • 传输过程有没有对数据加密?

没有对数据加密,有对请求数据做签名较验,可以在Config配置“Product.SignKey”,注意需要跟客户端的签名Key一致。

  • 不需要身份较验访问ACTION如何处理?

在Action类中重写IgnoreActionId属性,并返回false。

  • 请求的身份认证如何处理?

客户端请求时服务器会分配一个GameSession对象,登陆时较验用户帐号与密码,成功后调用GameSession对象Bind方法绑定身份。

  • SCUT的二进制协议流粘包如何处理?

在包的前面增加一个int的长度表示包的字节大小,拆包时先读取4位字节转换成int类型的长度(L),接着判断剩余包的长度大于等于L时,说明包已经全部接收完,读取L长度的字节;如果长度小于L时,则继续等待。

  • 通讯协议的头部ST字段的作用是什么?

头部St字段是一个时间缀(预留字段),表示这次的请求有效期多久,防止请求被拦截后发起恶意的请求,增加安全性,目前只使用签名较验,这个字段暂时未启用。

  • 通讯协议的头部SID和UID如何获取值?

Sid表示请求的会话ID,在客户连接成功后由服务器自己产生;Uid是用户登录成功后的身份标识,由帐号中心分配唯一的编号,在未登录前的请求客户端给sid的值空串,Uid的值0;登录成功后服务器下发sid和Uid,客户接收到需要存储起来,下一请求时上传sid和uid的值。

  • ACTION协议的方法执行顺序?

调用顺序是GetUrlElement (获取请求参数处理)->TakeAction(处理逻辑)->BuildPacket(封包下发)。

  • Scut Socket的IO是阻塞还是非阻塞模型?

接收数据是异步阻塞模型,IO使用的缓冲区是复用的。

  • SCUT支持HTTP短连接吗?

使用Consele控制台开启Http监听,在config配置中设置"Game.Http.Host"为"127.0.0.1",在IE中访问[http://127.0.0.1:8080/Service.aspx] ,(注: 6.7.9.0以上版本去掉对IIS部署的支持)

  • SCUT支持WebSocket连接吗?

支持,在6.7.9.5以上版本对WebSocket提供支持。

  • 如何配置Game.Script.DecodeFunc.Typename脚本加密发布?

Scut有提供一个加密脚本类库(ScutSecurity),它的密钥写在代码里,可以自己根据需要更换,使用时需要在Config中配置值为"ScutSecurity.ScriptDes,ScutSecurity",并从Release\Lib目录复制ScutSecurity.dll到项目中;在开发阶段可以注释掉这个配置,在发布时自己写工具批量加密脚本文件,并启用此配置。

  • 提示找不到相应的Action,报10000错误码怎么处理?

检查Script目录下是否有这个Action文件,检查Action文件的命名空间与GameServer.exe.config配置文件中"Game.Action.Script.TypeName"的是否一致

##Scut Sample问题

  • 客户端登陆没有反应或连接不上问题?

客户端在代码中设置的服务器地址是以域名(ddz.scutgame.com)的方式访问的,需要在本机Host文件中设置ddz.scutgame.com的域名转向,使用命令“telnet ddz.scutgame.com 9001”检测,或者客户端的请求连接地址改为本机IP(NetHelper.lua文件里配置);如果连接是成功的,检查服务器的Log\Exception目录是否有异常日志,有提示“SQL server error 40”错误的是服务器的连接字符串配置有问题。

##协议工具问题

协议工具需要部署在IIS7.0以上版本上,需要安装.NET 4.0以上版本;生成代码功能并不是生成可执行的代码,有些上方需要手动修改。

  • 协议工具部署完成后,打开页面显示iframe错误?

检查Web.config的配置;检查C:\windows\Temp目录给everyone用户加上读写目录的权限;IIS网站根目录“功能视图”的“ISAPI和CGI限制”中“ASP.NET V4.0”是否配置有允许。

  • 页面按钮点击没有反应?

检查Log目录下的是否有异常,如果是数据库出错检查下连接字串符串的配置是否正确;使用Mysql数据库时要注意下server配置使用“.”号的问题,换成“localhost”试试。

  • 协议工具有没有说明文档?

如何使用协议工具平台

##客户端SDK使用问题

  • 服务器推送Unity3d的消息怎么接收?

Unity请求的与推送的消息都是由线程监听,通过SocketConnect类的CheckReceive方法检测是否有消息,如果是推送的消息MsgId为0,转向到注册的OnPushCallback回调方法处理,Net类中处理回调会将消息分发到指定的Action协议处理。

Clone this wiki locally

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content
superzmy edited this page Mar 3, 2016 · 16 revisions

此章节整理开发中碰到问题总结的FAQ

在使用Scut中有碰到的问题尽量提交到论坛中,更方便我们整理。

##Scut开发问题

  • Scut同时在线人数能达到多少?

同时在线人数跟CPU,内存,带宽都有关系的,具体性能见负载测试报告

服务器配置计量方法:

  • CPU:依据业务的运算量,较大可配置高些,8核基本应该够用;
  • 内存:以1个用户占1M计算;
  • 带宽:以1个用户按60K计算,这个是每秒并发人数,不是在线人数;
  • 启动时提示"NIC is not connected or no network"出错?

说明本机机器的网络有问题

  • 检查127.0.0.1是否能Ping通,并且关掉防火墙试试;
  • 检测网卡是否是正确版本,不正确需要升级;
  • 检查是否有多个网卡或外接wifi,禁用再试试。
  • 启动时提示"Redis Server is using Ip game server, it's path..."或"Server failed to start error:The game server is using Redis at host nam e "oneHostName" path D:\xxx\xxx."

说明Redis服务被其它的程序使用了,进入命令行窗口,使用redis-cli客户端删除"__RedisInfo"的键; 脚本如下:

> redis-cli -h 127.0.0.1 -p 6379
# 切换使用的Redis.DB
> select 0;
> del __RedisInfo;
select 0的0根据你的游戏redis数据库序号填写

一般的服务器是 一个Server对应一个Redis部署, 再扩新服时,会需要copy配置文件,由于人为原因可以会漏改配置文件,造成新服与旧服共用了一个存储区域,数据混乱掉;因此增加限制;如果不是这种一个Server对应一个Redis的架构, 可以增加配置键:

<add key="Slave.MessageQueue" value="Slave" />

6.7.9.10版本调整为使用机器名+路径绑定

  • Csscript目录下的脚本文件在VS中没有智能提示?

检查脚本文件的属性,是否是编译的方式;另外注意在Game项目中的Script目录下的文件不能设置编译的方式,因为它是以动态运行的,不能把这些脚本编译在exe中,会与动态编译的冲突。

  • 如何在项目中调试SCUT FRAMEWORK?

首先.net调试是需要*.pdb文件的,打开Scut 的Framework解决方案,编译Source, 接着双击“发布处理.bat”批处理文件将dll发布到上一级的Release目录下(需要xcopy命令支持); 接着将Release/Lib目录下的dll复制到项目中即可;要调试Source的某个文件, 只需要将文件拖到项目中并设置断点,再按F5运行当前项目;断点有生成显示的是实心的红色圆点, 如果是穿心圆点说明文件与dll里的版本不一致,需要重新按以上步骤替换dll。

  • 打开SCUT项目编译USING错误?

Scut要求是在.Net Framework 4.5.1以上版本运行的,检查是否有安装VS2013或.Net Framework 4.5.1运行时环境;在项目属性的生成选项以“.Net Framework 4.5.1”编译。

  • 代码中如何查USING的命名空间?

在VS中将鼠标移到需要增加using命名空间的类上,会在旁边显示一个小图标,下拉选中using的命名空间,VS会自动帮助你加到文件using部分;或者安装一个代码生成工具VS插件ReSharper(QQ群文件有提供),提高编码效率。

  • 是否有实现同一个帐号再次登录挤掉的功能?

使用AuthorizeAction类判断GameSession对象的OldSessionId属性来识别。

  • 渠道登录中间件配置的ID如何设置?

配置的ID是通过客户端上传的RetailID参数来区分的,可以自己分配, 与客户端对应上就可以。

  • 实体属性修改后没有保存到Redis和DB中?

Model是否是独立另一个项目,需要使用IL打开Model.dll检查Entity的Set属性代码是否有调用BindAndNotify或BindAndChangeProperty方法,没有需要在项目.csproj配置注入脚本;Model是以脚本方式,需要检查Entity的SchemaTable配置,只读或只写属性不会触发Changed事件。

  • 游戏服的缓存数据是如何更新的?

每个实体的属性都绑定有Changed事件,当属性发现设置值,新增和删除实体时时会触发事件,所有Change事件会提交到Redis的消息队列中(Key以“__”开头); 由另一线程监控这个消息队列(每100毫秒),当有新消息时会将数据更新到Redis的Model存储区中(key以“$”开头),更新失败将存储到Redis的Error消息队列;根据config配置中的“EnableWriteToDb”键和实体SchemaTable属性的“IsStoreInDb”值判断是否要更新到数据库,为了降低数据库的IO高,需要更新数据库的实体先放到等待消息队列中,间隔(每五分钟)一段时间将实体转换成sql语句放入Sql执行消息队列中,Sql执行消息队列启动线程(配置10个线程)每100毫秒执行写入到数据库,如果执行出错将Sql语句存储到Redis的Sql Error消息队列。

  • 为什么数据库表里的数据修改了在游戏服缓存中没有?

原因是游戏服从数据库或Redis取出数据后会缓存在游戏服中,不会每次从数据库或Redis中取了,当游戏服的数据改变时会更新到数据库或Redis,在数据库或Redis修改数据是会被覆盖;当游戏服关掉重启时才会再次从数据库或Redis取数据;另外配置实体是只读类型的才会从数据库取数据,其它的只从Redis取数据,原因Scut是以Redis作为主要存储。

  • REDIS客户端查看存储的数据是否能显示JSON的格式?

可以在项目的Config配置中增加键“Cache.Serializer”值为“Json”,使用Json序列化的方式存储,设置前需要将Redis的数据清除,不能混合使用;建议在开发阶段使用Json,发布时使用“Protobuf”序列化的存储,减少Redis内存使用量。

  • 日志表增长比较大如何处理?

日志表比较大时,可以对表以日期水平方式分割,减小单张表的存储容量;在Model中定义一个Log类型的实体模型,并设置表名以“年月”或“年月日”的规则生成表,;设置EntityTable的“TableNameFormat”属性为“Log$date[yyyyMM]_{0}”(ex: Log201408_TableName)。

  • Model实体设计如何返回GetIdentity方法的值?

GetIdentity是对实体数据分类的ID,如:背包数据它的主键是ItemID(自增的),UserId(归属玩家),那么可以用UserId分类,GetIdentity返回UserId属性值,而不能用主键ItemID,如果一定要用ItemID,那么可以使用Share类型的结构(ShareEntity); 使用new PersonalCacheStruct().FindKey(参数1),参数1就是GetIdentity()的值。

  • 使用GameHttpHost时提示Httplistener监听启动拒绝问题?

检查GameServer.exe启动是否使用管理员帐号运行

  • 玩家离线怎么通知应用层和断线重连怎么处理?

当Socket断线时会调用MainClass类中有OnDisconnected方法,这此处理业务层逻辑;断线重连根据sid参数自动恢复连接,不需要自己处理。

  • 如何在游戏服内调用WebService服务?

首先右击项目的“引用”,选择“添加服务引用”,在弹出的窗口地址输入WebService服务地址后,点“确定”;VS会自动生成的调用WebService服务的调用代码和配置文件,需要将Reference.cs文件Copy到Script/CsScript/References目录下;另外找到“app.config”配置文件,将“system.serviceModel”结点的配置复制到“GameServer.exe.config”中。

  • 在线用户如何获取?

所有的会话都是由GameSession管理的,GameSession.GetOnlineAll方法可以获取在线玩家。

  • 传输过程有没有对数据加密?

没有对数据加密,有对请求数据做签名较验,可以在Config配置“Product.SignKey”,注意需要跟客户端的签名Key一致。

  • 不需要身份较验访问ACTION如何处理?

在Action类中重写IgnoreActionId属性,并返回false。

  • 请求的身份认证如何处理?

客户端请求时服务器会分配一个GameSession对象,登陆时较验用户帐号与密码,成功后调用GameSession对象Bind方法绑定身份。

  • SCUT的二进制协议流粘包如何处理?

在包的前面增加一个int的长度表示包的字节大小,拆包时先读取4位字节转换成int类型的长度(L),接着判断剩余包的长度大于等于L时,说明包已经全部接收完,读取L长度的字节;如果长度小于L时,则继续等待。

  • 通讯协议的头部ST字段的作用是什么?

头部St字段是一个时间缀(预留字段),表示这次的请求有效期多久,防止请求被拦截后发起恶意的请求,增加安全性,目前只使用签名较验,这个字段暂时未启用。

  • 通讯协议的头部SID和UID如何获取值?

Sid表示请求的会话ID,在客户连接成功后由服务器自己产生;Uid是用户登录成功后的身份标识,由帐号中心分配唯一的编号,在未登录前的请求客户端给sid的值空串,Uid的值0;登录成功后服务器下发sid和Uid,客户接收到需要存储起来,下一请求时上传sid和uid的值。

  • ACTION协议的方法执行顺序?

调用顺序是GetUrlElement (获取请求参数处理)->TakeAction(处理逻辑)->BuildPacket(封包下发)。

  • Scut Socket的IO是阻塞还是非阻塞模型?

接收数据是异步阻塞模型,IO使用的缓冲区是复用的。

  • SCUT支持HTTP短连接吗?

使用Consele控制台开启Http监听,在config配置中设置"Game.Http.Host"为"127.0.0.1",在IE中访问[http://127.0.0.1:8080/Service.aspx] ,(注: 6.7.9.0以上版本去掉对IIS部署的支持)

  • SCUT支持WebSocket连接吗?

支持,在6.7.9.5以上版本对WebSocket提供支持。

  • 如何配置Game.Script.DecodeFunc.Typename脚本加密发布?

Scut有提供一个加密脚本类库(ScutSecurity),它的密钥写在代码里,可以自己根据需要更换,使用时需要在Config中配置值为"ScutSecurity.ScriptDes,ScutSecurity",并从Release\Lib目录复制ScutSecurity.dll到项目中;在开发阶段可以注释掉这个配置,在发布时自己写工具批量加密脚本文件,并启用此配置。

  • 提示找不到相应的Action,报10000错误码怎么处理?

检查Script目录下是否有这个Action文件,检查Action文件的命名空间与GameServer.exe.config配置文件中"Game.Action.Script.TypeName"的是否一致

##Scut Sample问题

  • 客户端登陆没有反应或连接不上问题?

客户端在代码中设置的服务器地址是以域名(ddz.scutgame.com)的方式访问的,需要在本机Host文件中设置ddz.scutgame.com的域名转向,使用命令“telnet ddz.scutgame.com 9001”检测,或者客户端的请求连接地址改为本机IP(NetHelper.lua文件里配置);如果连接是成功的,检查服务器的Log\Exception目录是否有异常日志,有提示“SQL server error 40”错误的是服务器的连接字符串配置有问题。

##协议工具问题

协议工具需要部署在IIS7.0以上版本上,需要安装.NET 4.0以上版本;生成代码功能并不是生成可执行的代码,有些上方需要手动修改。

  • 协议工具部署完成后,打开页面显示iframe错误?

检查Web.config的配置;检查C:\windows\Temp目录给everyone用户加上读写目录的权限;IIS网站根目录“功能视图”的“ISAPI和CGI限制”中“ASP.NET V4.0”是否配置有允许。

  • 页面按钮点击没有反应?

检查Log目录下的是否有异常,如果是数据库出错检查下连接字串符串的配置是否正确;使用Mysql数据库时要注意下server配置使用“.”号的问题,换成“localhost”试试。

  • 协议工具有没有说明文档?

如何使用协议工具平台

##客户端SDK使用问题

  • 服务器推送Unity3d的消息怎么接收?

Unity请求的与推送的消息都是由线程监听,通过SocketConnect类的CheckReceive方法检测是否有消息,如果是推送的消息MsgId为0,转向到注册的OnPushCallback回调方法处理,Net类中处理回调会将消息分发到指定的Action协议处理。

Clone this wiki locally

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
superzmy edited this page Mar 3, 2016 · 16 revisions

此章节整理开发中碰到问题总结的FAQ

在使用Scut中有碰到的问题尽量提交到论坛中,更方便我们整理。

##Scut开发问题

  • Scut同时在线人数能达到多少?

同时在线人数跟CPU,内存,带宽都有关系的,具体性能见负载测试报告

服务器配置计量方法:

  • CPU:依据业务的运算量,较大可配置高些,8核基本应该够用;
  • 内存:以1个用户占1M计算;
  • 带宽:以1个用户按60K计算,这个是每秒并发人数,不是在线人数;
  • 启动时提示"NIC is not connected or no network"出错?

说明本机机器的网络有问题

  • 检查127.0.0.1是否能Ping通,并且关掉防火墙试试;
  • 检测网卡是否是正确版本,不正确需要升级;
  • 检查是否有多个网卡或外接wifi,禁用再试试。
  • 启动时提示"Redis Server is using Ip game server, it's path..."或"Server failed to start error:The game server is using Redis at host nam e "oneHostName" path D:\xxx\xxx."

说明Redis服务被其它的程序使用了,进入命令行窗口,使用redis-cli客户端删除"__RedisInfo"的键; 脚本如下:

> redis-cli -h 127.0.0.1 -p 6379
# 切换使用的Redis.DB
> select 0;
> del __RedisInfo;
select 0的0根据你的游戏redis数据库序号填写

一般的服务器是 一个Server对应一个Redis部署, 再扩新服时,会需要copy配置文件,由于人为原因可以会漏改配置文件,造成新服与旧服共用了一个存储区域,数据混乱掉;因此增加限制;如果不是这种一个Server对应一个Redis的架构, 可以增加配置键:

<add key="Slave.MessageQueue" value="Slave" />

6.7.9.10版本调整为使用机器名+路径绑定

  • Csscript目录下的脚本文件在VS中没有智能提示?

检查脚本文件的属性,是否是编译的方式;另外注意在Game项目中的Script目录下的文件不能设置编译的方式,因为它是以动态运行的,不能把这些脚本编译在exe中,会与动态编译的冲突。

  • 如何在项目中调试SCUT FRAMEWORK?

首先.net调试是需要*.pdb文件的,打开Scut 的Framework解决方案,编译Source, 接着双击“发布处理.bat”批处理文件将dll发布到上一级的Release目录下(需要xcopy命令支持); 接着将Release/Lib目录下的dll复制到项目中即可;要调试Source的某个文件, 只需要将文件拖到项目中并设置断点,再按F5运行当前项目;断点有生成显示的是实心的红色圆点, 如果是穿心圆点说明文件与dll里的版本不一致,需要重新按以上步骤替换dll。

  • 打开SCUT项目编译USING错误?

Scut要求是在.Net Framework 4.5.1以上版本运行的,检查是否有安装VS2013或.Net Framework 4.5.1运行时环境;在项目属性的生成选项以“.Net Framework 4.5.1”编译。

  • 代码中如何查USING的命名空间?

在VS中将鼠标移到需要增加using命名空间的类上,会在旁边显示一个小图标,下拉选中using的命名空间,VS会自动帮助你加到文件using部分;或者安装一个代码生成工具VS插件ReSharper(QQ群文件有提供),提高编码效率。

  • 是否有实现同一个帐号再次登录挤掉的功能?

使用AuthorizeAction类判断GameSession对象的OldSessionId属性来识别。

  • 渠道登录中间件配置的ID如何设置?

配置的ID是通过客户端上传的RetailID参数来区分的,可以自己分配, 与客户端对应上就可以。

  • 实体属性修改后没有保存到Redis和DB中?

Model是否是独立另一个项目,需要使用IL打开Model.dll检查Entity的Set属性代码是否有调用BindAndNotify或BindAndChangeProperty方法,没有需要在项目.csproj配置注入脚本;Model是以脚本方式,需要检查Entity的SchemaTable配置,只读或只写属性不会触发Changed事件。

  • 游戏服的缓存数据是如何更新的?

每个实体的属性都绑定有Changed事件,当属性发现设置值,新增和删除实体时时会触发事件,所有Change事件会提交到Redis的消息队列中(Key以“__”开头); 由另一线程监控这个消息队列(每100毫秒),当有新消息时会将数据更新到Redis的Model存储区中(key以“$”开头),更新失败将存储到Redis的Error消息队列;根据config配置中的“EnableWriteToDb”键和实体SchemaTable属性的“IsStoreInDb”值判断是否要更新到数据库,为了降低数据库的IO高,需要更新数据库的实体先放到等待消息队列中,间隔(每五分钟)一段时间将实体转换成sql语句放入Sql执行消息队列中,Sql执行消息队列启动线程(配置10个线程)每100毫秒执行写入到数据库,如果执行出错将Sql语句存储到Redis的Sql Error消息队列。

  • 为什么数据库表里的数据修改了在游戏服缓存中没有?

原因是游戏服从数据库或Redis取出数据后会缓存在游戏服中,不会每次从数据库或Redis中取了,当游戏服的数据改变时会更新到数据库或Redis,在数据库或Redis修改数据是会被覆盖;当游戏服关掉重启时才会再次从数据库或Redis取数据;另外配置实体是只读类型的才会从数据库取数据,其它的只从Redis取数据,原因Scut是以Redis作为主要存储。

  • REDIS客户端查看存储的数据是否能显示JSON的格式?

可以在项目的Config配置中增加键“Cache.Serializer”值为“Json”,使用Json序列化的方式存储,设置前需要将Redis的数据清除,不能混合使用;建议在开发阶段使用Json,发布时使用“Protobuf”序列化的存储,减少Redis内存使用量。

  • 日志表增长比较大如何处理?

日志表比较大时,可以对表以日期水平方式分割,减小单张表的存储容量;在Model中定义一个Log类型的实体模型,并设置表名以“年月”或“年月日”的规则生成表,;设置EntityTable的“TableNameFormat”属性为“Log$date[yyyyMM]_{0}”(ex: Log201408_TableName)。

  • Model实体设计如何返回GetIdentity方法的值?

GetIdentity是对实体数据分类的ID,如:背包数据它的主键是ItemID(自增的),UserId(归属玩家),那么可以用UserId分类,GetIdentity返回UserId属性值,而不能用主键ItemID,如果一定要用ItemID,那么可以使用Share类型的结构(ShareEntity); 使用new PersonalCacheStruct().FindKey(参数1),参数1就是GetIdentity()的值。

  • 使用GameHttpHost时提示Httplistener监听启动拒绝问题?

检查GameServer.exe启动是否使用管理员帐号运行

  • 玩家离线怎么通知应用层和断线重连怎么处理?

当Socket断线时会调用MainClass类中有OnDisconnected方法,这此处理业务层逻辑;断线重连根据sid参数自动恢复连接,不需要自己处理。

  • 如何在游戏服内调用WebService服务?

首先右击项目的“引用”,选择“添加服务引用”,在弹出的窗口地址输入WebService服务地址后,点“确定”;VS会自动生成的调用WebService服务的调用代码和配置文件,需要将Reference.cs文件Copy到Script/CsScript/References目录下;另外找到“app.config”配置文件,将“system.serviceModel”结点的配置复制到“GameServer.exe.config”中。

  • 在线用户如何获取?

所有的会话都是由GameSession管理的,GameSession.GetOnlineAll方法可以获取在线玩家。

  • 传输过程有没有对数据加密?

没有对数据加密,有对请求数据做签名较验,可以在Config配置“Product.SignKey”,注意需要跟客户端的签名Key一致。

  • 不需要身份较验访问ACTION如何处理?

在Action类中重写IgnoreActionId属性,并返回false。

  • 请求的身份认证如何处理?

客户端请求时服务器会分配一个GameSession对象,登陆时较验用户帐号与密码,成功后调用GameSession对象Bind方法绑定身份。

  • SCUT的二进制协议流粘包如何处理?

在包的前面增加一个int的长度表示包的字节大小,拆包时先读取4位字节转换成int类型的长度(L),接着判断剩余包的长度大于等于L时,说明包已经全部接收完,读取L长度的字节;如果长度小于L时,则继续等待。

  • 通讯协议的头部ST字段的作用是什么?

头部St字段是一个时间缀(预留字段),表示这次的请求有效期多久,防止请求被拦截后发起恶意的请求,增加安全性,目前只使用签名较验,这个字段暂时未启用。

  • 通讯协议的头部SID和UID如何获取值?

Sid表示请求的会话ID,在客户连接成功后由服务器自己产生;Uid是用户登录成功后的身份标识,由帐号中心分配唯一的编号,在未登录前的请求客户端给sid的值空串,Uid的值0;登录成功后服务器下发sid和Uid,客户接收到需要存储起来,下一请求时上传sid和uid的值。

  • ACTION协议的方法执行顺序?

调用顺序是GetUrlElement (获取请求参数处理)->TakeAction(处理逻辑)->BuildPacket(封包下发)。

  • Scut Socket的IO是阻塞还是非阻塞模型?

接收数据是异步阻塞模型,IO使用的缓冲区是复用的。

  • SCUT支持HTTP短连接吗?

使用Consele控制台开启Http监听,在config配置中设置"Game.Http.Host"为"127.0.0.1",在IE中访问[http://127.0.0.1:8080/Service.aspx] ,(注: 6.7.9.0以上版本去掉对IIS部署的支持)

  • SCUT支持WebSocket连接吗?

支持,在6.7.9.5以上版本对WebSocket提供支持。

  • 如何配置Game.Script.DecodeFunc.Typename脚本加密发布?

Scut有提供一个加密脚本类库(ScutSecurity),它的密钥写在代码里,可以自己根据需要更换,使用时需要在Config中配置值为"ScutSecurity.ScriptDes,ScutSecurity",并从Release\Lib目录复制ScutSecurity.dll到项目中;在开发阶段可以注释掉这个配置,在发布时自己写工具批量加密脚本文件,并启用此配置。

  • 提示找不到相应的Action,报10000错误码怎么处理?

检查Script目录下是否有这个Action文件,检查Action文件的命名空间与GameServer.exe.config配置文件中"Game.Action.Script.TypeName"的是否一致

##Scut Sample问题

  • 客户端登陆没有反应或连接不上问题?

客户端在代码中设置的服务器地址是以域名(ddz.scutgame.com)的方式访问的,需要在本机Host文件中设置ddz.scutgame.com的域名转向,使用命令“telnet ddz.scutgame.com 9001”检测,或者客户端的请求连接地址改为本机IP(NetHelper.lua文件里配置);如果连接是成功的,检查服务器的Log\Exception目录是否有异常日志,有提示“SQL server error 40”错误的是服务器的连接字符串配置有问题。

##协议工具问题

协议工具需要部署在IIS7.0以上版本上,需要安装.NET 4.0以上版本;生成代码功能并不是生成可执行的代码,有些上方需要手动修改。

  • 协议工具部署完成后,打开页面显示iframe错误?

检查Web.config的配置;检查C:\windows\Temp目录给everyone用户加上读写目录的权限;IIS网站根目录“功能视图”的“ISAPI和CGI限制”中“ASP.NET V4.0”是否配置有允许。

  • 页面按钮点击没有反应?

检查Log目录下的是否有异常,如果是数据库出错检查下连接字串符串的配置是否正确;使用Mysql数据库时要注意下server配置使用“.”号的问题,换成“localhost”试试。

  • 协议工具有没有说明文档?

如何使用协议工具平台

##客户端SDK使用问题

  • 服务器推送Unity3d的消息怎么接收?

Unity请求的与推送的消息都是由线程监听,通过SocketConnect类的CheckReceive方法检测是否有消息,如果是推送的消息MsgId为0,转向到注册的OnPushCallback回调方法处理,Net类中处理回调会将消息分发到指定的Action协议处理。

Clone this wiki locally

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
superzmy edited this page Mar 3, 2016 · 16 revisions

此章节整理开发中碰到问题总结的FAQ

在使用Scut中有碰到的问题尽量提交到论坛中,更方便我们整理。

##Scut开发问题

  • Scut同时在线人数能达到多少?

同时在线人数跟CPU,内存,带宽都有关系的,具体性能见负载测试报告

服务器配置计量方法:

  • CPU:依据业务的运算量,较大可配置高些,8核基本应该够用;
  • 内存:以1个用户占1M计算;
  • 带宽:以1个用户按60K计算,这个是每秒并发人数,不是在线人数;
  • 启动时提示"NIC is not connected or no network"出错?

说明本机机器的网络有问题

  • 检查127.0.0.1是否能Ping通,并且关掉防火墙试试;
  • 检测网卡是否是正确版本,不正确需要升级;
  • 检查是否有多个网卡或外接wifi,禁用再试试。
  • 启动时提示"Redis Server is using Ip game server, it's path..."或"Server failed to start error:The game server is using Redis at host nam e "oneHostName" path D:\xxx\xxx."

说明Redis服务被其它的程序使用了,进入命令行窗口,使用redis-cli客户端删除"__RedisInfo"的键; 脚本如下:

> redis-cli -h 127.0.0.1 -p 6379
# 切换使用的Redis.DB
> select 0;
> del __RedisInfo;
select 0的0根据你的游戏redis数据库序号填写

一般的服务器是 一个Server对应一个Redis部署, 再扩新服时,会需要copy配置文件,由于人为原因可以会漏改配置文件,造成新服与旧服共用了一个存储区域,数据混乱掉;因此增加限制;如果不是这种一个Server对应一个Redis的架构, 可以增加配置键:

<add key="Slave.MessageQueue" value="Slave" />

6.7.9.10版本调整为使用机器名+路径绑定

  • Csscript目录下的脚本文件在VS中没有智能提示?

检查脚本文件的属性,是否是编译的方式;另外注意在Game项目中的Script目录下的文件不能设置编译的方式,因为它是以动态运行的,不能把这些脚本编译在exe中,会与动态编译的冲突。

  • 如何在项目中调试SCUT FRAMEWORK?

首先.net调试是需要*.pdb文件的,打开Scut 的Framework解决方案,编译Source, 接着双击“发布处理.bat”批处理文件将dll发布到上一级的Release目录下(需要xcopy命令支持); 接着将Release/Lib目录下的dll复制到项目中即可;要调试Source的某个文件, 只需要将文件拖到项目中并设置断点,再按F5运行当前项目;断点有生成显示的是实心的红色圆点, 如果是穿心圆点说明文件与dll里的版本不一致,需要重新按以上步骤替换dll。

  • 打开SCUT项目编译USING错误?

Scut要求是在.Net Framework 4.5.1以上版本运行的,检查是否有安装VS2013或.Net Framework 4.5.1运行时环境;在项目属性的生成选项以“.Net Framework 4.5.1”编译。

  • 代码中如何查USING的命名空间?

在VS中将鼠标移到需要增加using命名空间的类上,会在旁边显示一个小图标,下拉选中using的命名空间,VS会自动帮助你加到文件using部分;或者安装一个代码生成工具VS插件ReSharper(QQ群文件有提供),提高编码效率。

  • 是否有实现同一个帐号再次登录挤掉的功能?

使用AuthorizeAction类判断GameSession对象的OldSessionId属性来识别。

  • 渠道登录中间件配置的ID如何设置?

配置的ID是通过客户端上传的RetailID参数来区分的,可以自己分配, 与客户端对应上就可以。

  • 实体属性修改后没有保存到Redis和DB中?

Model是否是独立另一个项目,需要使用IL打开Model.dll检查Entity的Set属性代码是否有调用BindAndNotify或BindAndChangeProperty方法,没有需要在项目.csproj配置注入脚本;Model是以脚本方式,需要检查Entity的SchemaTable配置,只读或只写属性不会触发Changed事件。

  • 游戏服的缓存数据是如何更新的?

每个实体的属性都绑定有Changed事件,当属性发现设置值,新增和删除实体时时会触发事件,所有Change事件会提交到Redis的消息队列中(Key以“__”开头); 由另一线程监控这个消息队列(每100毫秒),当有新消息时会将数据更新到Redis的Model存储区中(key以“$”开头),更新失败将存储到Redis的Error消息队列;根据config配置中的“EnableWriteToDb”键和实体SchemaTable属性的“IsStoreInDb”值判断是否要更新到数据库,为了降低数据库的IO高,需要更新数据库的实体先放到等待消息队列中,间隔(每五分钟)一段时间将实体转换成sql语句放入Sql执行消息队列中,Sql执行消息队列启动线程(配置10个线程)每100毫秒执行写入到数据库,如果执行出错将Sql语句存储到Redis的Sql Error消息队列。

  • 为什么数据库表里的数据修改了在游戏服缓存中没有?

原因是游戏服从数据库或Redis取出数据后会缓存在游戏服中,不会每次从数据库或Redis中取了,当游戏服的数据改变时会更新到数据库或Redis,在数据库或Redis修改数据是会被覆盖;当游戏服关掉重启时才会再次从数据库或Redis取数据;另外配置实体是只读类型的才会从数据库取数据,其它的只从Redis取数据,原因Scut是以Redis作为主要存储。

  • REDIS客户端查看存储的数据是否能显示JSON的格式?

可以在项目的Config配置中增加键“Cache.Serializer”值为“Json”,使用Json序列化的方式存储,设置前需要将Redis的数据清除,不能混合使用;建议在开发阶段使用Json,发布时使用“Protobuf”序列化的存储,减少Redis内存使用量。

  • 日志表增长比较大如何处理?

日志表比较大时,可以对表以日期水平方式分割,减小单张表的存储容量;在Model中定义一个Log类型的实体模型,并设置表名以“年月”或“年月日”的规则生成表,;设置EntityTable的“TableNameFormat”属性为“Log$date[yyyyMM]_{0}”(ex: Log201408_TableName)。

  • Model实体设计如何返回GetIdentity方法的值?

GetIdentity是对实体数据分类的ID,如:背包数据它的主键是ItemID(自增的),UserId(归属玩家),那么可以用UserId分类,GetIdentity返回UserId属性值,而不能用主键ItemID,如果一定要用ItemID,那么可以使用Share类型的结构(ShareEntity); 使用new PersonalCacheStruct().FindKey(参数1),参数1就是GetIdentity()的值。

  • 使用GameHttpHost时提示Httplistener监听启动拒绝问题?

检查GameServer.exe启动是否使用管理员帐号运行

  • 玩家离线怎么通知应用层和断线重连怎么处理?

当Socket断线时会调用MainClass类中有OnDisconnected方法,这此处理业务层逻辑;断线重连根据sid参数自动恢复连接,不需要自己处理。

  • 如何在游戏服内调用WebService服务?

首先右击项目的“引用”,选择“添加服务引用”,在弹出的窗口地址输入WebService服务地址后,点“确定”;VS会自动生成的调用WebService服务的调用代码和配置文件,需要将Reference.cs文件Copy到Script/CsScript/References目录下;另外找到“app.config”配置文件,将“system.serviceModel”结点的配置复制到“GameServer.exe.config”中。

  • 在线用户如何获取?

所有的会话都是由GameSession管理的,GameSession.GetOnlineAll方法可以获取在线玩家。

  • 传输过程有没有对数据加密?

没有对数据加密,有对请求数据做签名较验,可以在Config配置“Product.SignKey”,注意需要跟客户端的签名Key一致。

  • 不需要身份较验访问ACTION如何处理?

在Action类中重写IgnoreActionId属性,并返回false。

  • 请求的身份认证如何处理?

客户端请求时服务器会分配一个GameSession对象,登陆时较验用户帐号与密码,成功后调用GameSession对象Bind方法绑定身份。

  • SCUT的二进制协议流粘包如何处理?

在包的前面增加一个int的长度表示包的字节大小,拆包时先读取4位字节转换成int类型的长度(L),接着判断剩余包的长度大于等于L时,说明包已经全部接收完,读取L长度的字节;如果长度小于L时,则继续等待。

  • 通讯协议的头部ST字段的作用是什么?

头部St字段是一个时间缀(预留字段),表示这次的请求有效期多久,防止请求被拦截后发起恶意的请求,增加安全性,目前只使用签名较验,这个字段暂时未启用。

  • 通讯协议的头部SID和UID如何获取值?

Sid表示请求的会话ID,在客户连接成功后由服务器自己产生;Uid是用户登录成功后的身份标识,由帐号中心分配唯一的编号,在未登录前的请求客户端给sid的值空串,Uid的值0;登录成功后服务器下发sid和Uid,客户接收到需要存储起来,下一请求时上传sid和uid的值。

  • ACTION协议的方法执行顺序?

调用顺序是GetUrlElement (获取请求参数处理)->TakeAction(处理逻辑)->BuildPacket(封包下发)。

  • Scut Socket的IO是阻塞还是非阻塞模型?

接收数据是异步阻塞模型,IO使用的缓冲区是复用的。

  • SCUT支持HTTP短连接吗?

使用Consele控制台开启Http监听,在config配置中设置"Game.Http.Host"为"127.0.0.1",在IE中访问[http://127.0.0.1:8080/Service.aspx] ,(注: 6.7.9.0以上版本去掉对IIS部署的支持)

  • SCUT支持WebSocket连接吗?

支持,在6.7.9.5以上版本对WebSocket提供支持。

  • 如何配置Game.Script.DecodeFunc.Typename脚本加密发布?

Scut有提供一个加密脚本类库(ScutSecurity),它的密钥写在代码里,可以自己根据需要更换,使用时需要在Config中配置值为"ScutSecurity.ScriptDes,ScutSecurity",并从Release\Lib目录复制ScutSecurity.dll到项目中;在开发阶段可以注释掉这个配置,在发布时自己写工具批量加密脚本文件,并启用此配置。

  • 提示找不到相应的Action,报10000错误码怎么处理?

检查Script目录下是否有这个Action文件,检查Action文件的命名空间与GameServer.exe.config配置文件中"Game.Action.Script.TypeName"的是否一致

##Scut Sample问题

  • 客户端登陆没有反应或连接不上问题?

客户端在代码中设置的服务器地址是以域名(ddz.scutgame.com)的方式访问的,需要在本机Host文件中设置ddz.scutgame.com的域名转向,使用命令“telnet ddz.scutgame.com 9001”检测,或者客户端的请求连接地址改为本机IP(NetHelper.lua文件里配置);如果连接是成功的,检查服务器的Log\Exception目录是否有异常日志,有提示“SQL server error 40”错误的是服务器的连接字符串配置有问题。

##协议工具问题

协议工具需要部署在IIS7.0以上版本上,需要安装.NET 4.0以上版本;生成代码功能并不是生成可执行的代码,有些上方需要手动修改。

  • 协议工具部署完成后,打开页面显示iframe错误?

检查Web.config的配置;检查C:\windows\Temp目录给everyone用户加上读写目录的权限;IIS网站根目录“功能视图”的“ISAPI和CGI限制”中“ASP.NET V4.0”是否配置有允许。

  • 页面按钮点击没有反应?

检查Log目录下的是否有异常,如果是数据库出错检查下连接字串符串的配置是否正确;使用Mysql数据库时要注意下server配置使用“.”号的问题,换成“localhost”试试。

  • 协议工具有没有说明文档?

如何使用协议工具平台

##客户端SDK使用问题

  • 服务器推送Unity3d的消息怎么接收?

Unity请求的与推送的消息都是由线程监听,通过SocketConnect类的CheckReceive方法检测是否有消息,如果是推送的消息MsgId为0,转向到注册的OnPushCallback回调方法处理,Net类中处理回调会将消息分发到指定的Action协议处理。

Clone this wiki locally

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content
superzmy edited this page Mar 3, 2016 · 16 revisions

此章节整理开发中碰到问题总结的FAQ

在使用Scut中有碰到的问题尽量提交到论坛中,更方便我们整理。

##Scut开发问题

  • Scut同时在线人数能达到多少?

同时在线人数跟CPU,内存,带宽都有关系的,具体性能见负载测试报告

服务器配置计量方法:

  • CPU:依据业务的运算量,较大可配置高些,8核基本应该够用;
  • 内存:以1个用户占1M计算;
  • 带宽:以1个用户按60K计算,这个是每秒并发人数,不是在线人数;
  • 启动时提示"NIC is not connected or no network"出错?

说明本机机器的网络有问题

  • 检查127.0.0.1是否能Ping通,并且关掉防火墙试试;
  • 检测网卡是否是正确版本,不正确需要升级;
  • 检查是否有多个网卡或外接wifi,禁用再试试。
  • 启动时提示"Redis Server is using Ip game server, it's path..."或"Server failed to start error:The game server is using Redis at host nam e "oneHostName" path D:\xxx\xxx."

说明Redis服务被其它的程序使用了,进入命令行窗口,使用redis-cli客户端删除"__RedisInfo"的键; 脚本如下:

> redis-cli -h 127.0.0.1 -p 6379
# 切换使用的Redis.DB
> select 0;
> del __RedisInfo;
select 0的0根据你的游戏redis数据库序号填写

一般的服务器是 一个Server对应一个Redis部署, 再扩新服时,会需要copy配置文件,由于人为原因可以会漏改配置文件,造成新服与旧服共用了一个存储区域,数据混乱掉;因此增加限制;如果不是这种一个Server对应一个Redis的架构, 可以增加配置键:

<add key="Slave.MessageQueue" value="Slave" />

6.7.9.10版本调整为使用机器名+路径绑定

  • Csscript目录下的脚本文件在VS中没有智能提示?

检查脚本文件的属性,是否是编译的方式;另外注意在Game项目中的Script目录下的文件不能设置编译的方式,因为它是以动态运行的,不能把这些脚本编译在exe中,会与动态编译的冲突。

  • 如何在项目中调试SCUT FRAMEWORK?

首先.net调试是需要*.pdb文件的,打开Scut 的Framework解决方案,编译Source, 接着双击“发布处理.bat”批处理文件将dll发布到上一级的Release目录下(需要xcopy命令支持); 接着将Release/Lib目录下的dll复制到项目中即可;要调试Source的某个文件, 只需要将文件拖到项目中并设置断点,再按F5运行当前项目;断点有生成显示的是实心的红色圆点, 如果是穿心圆点说明文件与dll里的版本不一致,需要重新按以上步骤替换dll。

  • 打开SCUT项目编译USING错误?

Scut要求是在.Net Framework 4.5.1以上版本运行的,检查是否有安装VS2013或.Net Framework 4.5.1运行时环境;在项目属性的生成选项以“.Net Framework 4.5.1”编译。

  • 代码中如何查USING的命名空间?

在VS中将鼠标移到需要增加using命名空间的类上,会在旁边显示一个小图标,下拉选中using的命名空间,VS会自动帮助你加到文件using部分;或者安装一个代码生成工具VS插件ReSharper(QQ群文件有提供),提高编码效率。

  • 是否有实现同一个帐号再次登录挤掉的功能?

使用AuthorizeAction类判断GameSession对象的OldSessionId属性来识别。

  • 渠道登录中间件配置的ID如何设置?

配置的ID是通过客户端上传的RetailID参数来区分的,可以自己分配, 与客户端对应上就可以。

  • 实体属性修改后没有保存到Redis和DB中?

Model是否是独立另一个项目,需要使用IL打开Model.dll检查Entity的Set属性代码是否有调用BindAndNotify或BindAndChangeProperty方法,没有需要在项目.csproj配置注入脚本;Model是以脚本方式,需要检查Entity的SchemaTable配置,只读或只写属性不会触发Changed事件。

  • 游戏服的缓存数据是如何更新的?

每个实体的属性都绑定有Changed事件,当属性发现设置值,新增和删除实体时时会触发事件,所有Change事件会提交到Redis的消息队列中(Key以“__”开头); 由另一线程监控这个消息队列(每100毫秒),当有新消息时会将数据更新到Redis的Model存储区中(key以“$”开头),更新失败将存储到Redis的Error消息队列;根据config配置中的“EnableWriteToDb”键和实体SchemaTable属性的“IsStoreInDb”值判断是否要更新到数据库,为了降低数据库的IO高,需要更新数据库的实体先放到等待消息队列中,间隔(每五分钟)一段时间将实体转换成sql语句放入Sql执行消息队列中,Sql执行消息队列启动线程(配置10个线程)每100毫秒执行写入到数据库,如果执行出错将Sql语句存储到Redis的Sql Error消息队列。

  • 为什么数据库表里的数据修改了在游戏服缓存中没有?

原因是游戏服从数据库或Redis取出数据后会缓存在游戏服中,不会每次从数据库或Redis中取了,当游戏服的数据改变时会更新到数据库或Redis,在数据库或Redis修改数据是会被覆盖;当游戏服关掉重启时才会再次从数据库或Redis取数据;另外配置实体是只读类型的才会从数据库取数据,其它的只从Redis取数据,原因Scut是以Redis作为主要存储。

  • REDIS客户端查看存储的数据是否能显示JSON的格式?

可以在项目的Config配置中增加键“Cache.Serializer”值为“Json”,使用Json序列化的方式存储,设置前需要将Redis的数据清除,不能混合使用;建议在开发阶段使用Json,发布时使用“Protobuf”序列化的存储,减少Redis内存使用量。

  • 日志表增长比较大如何处理?

日志表比较大时,可以对表以日期水平方式分割,减小单张表的存储容量;在Model中定义一个Log类型的实体模型,并设置表名以“年月”或“年月日”的规则生成表,;设置EntityTable的“TableNameFormat”属性为“Log$date[yyyyMM]_{0}”(ex: Log201408_TableName)。

  • Model实体设计如何返回GetIdentity方法的值?

GetIdentity是对实体数据分类的ID,如:背包数据它的主键是ItemID(自增的),UserId(归属玩家),那么可以用UserId分类,GetIdentity返回UserId属性值,而不能用主键ItemID,如果一定要用ItemID,那么可以使用Share类型的结构(ShareEntity); 使用new PersonalCacheStruct().FindKey(参数1),参数1就是GetIdentity()的值。

  • 使用GameHttpHost时提示Httplistener监听启动拒绝问题?

检查GameServer.exe启动是否使用管理员帐号运行

  • 玩家离线怎么通知应用层和断线重连怎么处理?

当Socket断线时会调用MainClass类中有OnDisconnected方法,这此处理业务层逻辑;断线重连根据sid参数自动恢复连接,不需要自己处理。

  • 如何在游戏服内调用WebService服务?

首先右击项目的“引用”,选择“添加服务引用”,在弹出的窗口地址输入WebService服务地址后,点“确定”;VS会自动生成的调用WebService服务的调用代码和配置文件,需要将Reference.cs文件Copy到Script/CsScript/References目录下;另外找到“app.config”配置文件,将“system.serviceModel”结点的配置复制到“GameServer.exe.config”中。

  • 在线用户如何获取?

所有的会话都是由GameSession管理的,GameSession.GetOnlineAll方法可以获取在线玩家。

  • 传输过程有没有对数据加密?

没有对数据加密,有对请求数据做签名较验,可以在Config配置“Product.SignKey”,注意需要跟客户端的签名Key一致。

  • 不需要身份较验访问ACTION如何处理?

在Action类中重写IgnoreActionId属性,并返回false。

  • 请求的身份认证如何处理?

客户端请求时服务器会分配一个GameSession对象,登陆时较验用户帐号与密码,成功后调用GameSession对象Bind方法绑定身份。

  • SCUT的二进制协议流粘包如何处理?

在包的前面增加一个int的长度表示包的字节大小,拆包时先读取4位字节转换成int类型的长度(L),接着判断剩余包的长度大于等于L时,说明包已经全部接收完,读取L长度的字节;如果长度小于L时,则继续等待。

  • 通讯协议的头部ST字段的作用是什么?

头部St字段是一个时间缀(预留字段),表示这次的请求有效期多久,防止请求被拦截后发起恶意的请求,增加安全性,目前只使用签名较验,这个字段暂时未启用。

  • 通讯协议的头部SID和UID如何获取值?

Sid表示请求的会话ID,在客户连接成功后由服务器自己产生;Uid是用户登录成功后的身份标识,由帐号中心分配唯一的编号,在未登录前的请求客户端给sid的值空串,Uid的值0;登录成功后服务器下发sid和Uid,客户接收到需要存储起来,下一请求时上传sid和uid的值。

  • ACTION协议的方法执行顺序?

调用顺序是GetUrlElement (获取请求参数处理)->TakeAction(处理逻辑)->BuildPacket(封包下发)。

  • Scut Socket的IO是阻塞还是非阻塞模型?

接收数据是异步阻塞模型,IO使用的缓冲区是复用的。

  • SCUT支持HTTP短连接吗?

使用Consele控制台开启Http监听,在config配置中设置"Game.Http.Host"为"127.0.0.1",在IE中访问[http://127.0.0.1:8080/Service.aspx] ,(注: 6.7.9.0以上版本去掉对IIS部署的支持)

  • SCUT支持WebSocket连接吗?

支持,在6.7.9.5以上版本对WebSocket提供支持。

  • 如何配置Game.Script.DecodeFunc.Typename脚本加密发布?

Scut有提供一个加密脚本类库(ScutSecurity),它的密钥写在代码里,可以自己根据需要更换,使用时需要在Config中配置值为"ScutSecurity.ScriptDes,ScutSecurity",并从Release\Lib目录复制ScutSecurity.dll到项目中;在开发阶段可以注释掉这个配置,在发布时自己写工具批量加密脚本文件,并启用此配置。

  • 提示找不到相应的Action,报10000错误码怎么处理?

检查Script目录下是否有这个Action文件,检查Action文件的命名空间与GameServer.exe.config配置文件中"Game.Action.Script.TypeName"的是否一致

##Scut Sample问题

  • 客户端登陆没有反应或连接不上问题?

客户端在代码中设置的服务器地址是以域名(ddz.scutgame.com)的方式访问的,需要在本机Host文件中设置ddz.scutgame.com的域名转向,使用命令“telnet ddz.scutgame.com 9001”检测,或者客户端的请求连接地址改为本机IP(NetHelper.lua文件里配置);如果连接是成功的,检查服务器的Log\Exception目录是否有异常日志,有提示“SQL server error 40”错误的是服务器的连接字符串配置有问题。

##协议工具问题

协议工具需要部署在IIS7.0以上版本上,需要安装.NET 4.0以上版本;生成代码功能并不是生成可执行的代码,有些上方需要手动修改。

  • 协议工具部署完成后,打开页面显示iframe错误?

检查Web.config的配置;检查C:\windows\Temp目录给everyone用户加上读写目录的权限;IIS网站根目录“功能视图”的“ISAPI和CGI限制”中“ASP.NET V4.0”是否配置有允许。

  • 页面按钮点击没有反应?

检查Log目录下的是否有异常,如果是数据库出错检查下连接字串符串的配置是否正确;使用Mysql数据库时要注意下server配置使用“.”号的问题,换成“localhost”试试。

  • 协议工具有没有说明文档?

如何使用协议工具平台

##客户端SDK使用问题

  • 服务器推送Unity3d的消息怎么接收?

Unity请求的与推送的消息都是由线程监听,通过SocketConnect类的CheckReceive方法检测是否有消息,如果是推送的消息MsgId为0,转向到注册的OnPushCallback回调方法处理,Net类中处理回调会将消息分发到指定的Action协议处理。

Clone this wiki locally