GitHub 上有哪些不错的python游戏服务器框架架

博客分类:
最近,网易在Github上开源了基于Node.js的游戏服务器框架——。它包括基础的开发框架和相关的扩展组件(库和工具包),可以帮助开发人员省去游戏开发枯燥中的重复劳动和底层逻辑的开发。 pomelo不但适用于游戏服务器开发, 也可用于开发高实时Web应用。
pomelo框架包括三部分:
框架, pomelo的核心, 与以往单进程的游戏框架不同, 它是高性能、分布式的游戏服务器框架,并且使用很简单。
库, 包括了开发游戏的常用工具库, 如人工智能(ai)、寻路、aoi等。
工具包, 包括管理控制台、 命令行工具、压力测试工具等。
pomelo的主要特性:
快速、易上手的游戏开发模型和API。
高可伸缩的多进程架构, 支持MMO的场景分区和其它各类分区策略。
方便的服务器扩展机制,可快速扩展服务器类型和数量。
方便的请求、响应、广播、服务器通讯机制, 无需任何配置。
注重性能,在性能、可伸缩性上做了大量的测试、优化。
提供了较多扩展组件,包括游戏开发常用的库和工具包。
提供了完整的MMO demo代码(客户端html5),可以作为很好的开发参考。
基于socket.io开发,支持socket.io支持的多种语言客户端。
网易pomelo开发团队在项目主页上列举了推荐pomelo的理由:
高并发、高实时的游戏服务器的开发是很复杂的工作。跟Web应用一样,一个好的开源容器或开发框架可以大大减少游戏开发的复杂性,让开发变得更加容易。遗憾的是目前在游戏服务器开发领域一直没有太好的开源解决方案。 pomelo将填补这个空白, 打造一款完全开源的高性能(并发)游戏服务器框架。
pomelo的优势有以下几点:
架构的可伸缩性好。 采用多进程单线程的运行架构,扩展服务器非常方便, Node.js的网络IO优势提供了高可伸缩性。
使用非常容易, 开发模型与Web应用的开发类似,基于convention over configuration的理念, 几乎零配置, API的设计也很精简, 很容易上手。
框架的松耦合和可扩展性好, 遵循Node.js微模块的原则, framework本身只有很少的代码,所有component、库、工具都可以用npm module的形式扩展进来。任何第三方都可以根据自己的需要开发自定义module。
提供完整的开源MMO游戏demo参考(基于HTML 5)。 一个超过1万行代码的游戏demo,使开发者可以随时借鉴demo的设计与开发思路。
pomelo为什么采用Node.js开发?
Node.js自身特点与游戏服务器的特性惊人的吻合。 在Node.js的官方定义中, fast、scalable、realtime、network这几个特性都非常符合游戏服务器的要求。游戏服务器是个网络密集型的应用,对实时性要求极高,而Node.js在网络io上的优势也完全可以满足这点。使用Node.js开发游戏服务器的优势总结:
io与可伸缩性的优势。io密集型的应用采用Node.js是最合适的, 可达到最好的可伸缩性。
多进程单线程的应用架构。Node.js天生采用单线程, 使它在处理复杂逻辑的时候无需考虑线程同步、锁、死锁等一系列问题, 减少了很多逻辑错误。 由多进程Node.js组成的服务器群是最理想的应用架构。
语言优势。使用javascript开发可以实现快速迭代,如果客户端使用HTML 5,更可实现代码共用。
网易pomelo开发团队介绍了游戏服务器的运行架构:
一个真正高可扩展的游戏运行架构必须是多进程的。Google的,、Mozilla的 都采用了Node.js作为游戏服务器开发语言, 但它们都采用了单进程的Node.js服务器,缺乏扩展性,这使它们可以支撑的在线用户数量是很有限的(这两个游戏主要是作为HTML5游戏的 demo)。而多进程的架构可以很好的实现游戏服务器的的扩展性,达到支撑较多在线用户、降低服务器压力等要求。
该游戏运行架构表面上看与web应用运行架构很类似,connector类似于web应用的apache/nginx等web服务器,后端的服务器群类似于web应用中的应用服务器(如tomcat),但实际上存在着很大的差别:
长连接与短连接。web应用使用基于http的短连接以达到最大的可扩展性,游戏应用采用基于socket(websocket)的长连接,以达到最大的实时性。
分区策略不同。web应用的分区可以根据负载均衡自由决定, 而游戏则是基于场景(area)的分区模式, 这使同场景的玩家跑在一个进程内,以达到最少的跨进程调用。
有状态和无状态。web应用是无状态的, 可以达到无限的扩展。 而游戏应用则是有状态的, 由于基于场景的分区策略,它的请求必须路由到指定的服务器, 这也使游戏达不到web应用同样的可扩展性。
广播模式和request/response模式。web应用采用了基于request/response的请求响应模式。而游戏应用则更频繁地使用广播,由于玩家在游戏里的行动要实时地通知场景中的其它玩家, 必须通过广播的模式实时发送。这也使游戏在网络通信上的要求高于web应用。
pomelo framework的组成架构如图所示:
图片来源: Github网易pomelo项目介绍
server management, pomelo是个真正多进程、分布式的游戏服务器。因此各游戏server(进程)的管理是pomelo很重要的部分,框架通过抽象使服务器的管理非常容易。
network, 请求、响应、广播、RPC、session管理等构成了整个游戏框架的脉络,所有游戏流程都构建在这个脉络上。
application, 应用的定义、component管理,上下文配置, 这些使pomelo framework的对外接口很简单,并且具有松耦合、可插拔架构。
pomelo的架构设计目标:
服务器(进程)的抽象与扩展:在web应用中, 每个服务器是无状态、对等的, 开发者无需通过框架或容器来管理服务器。但游戏应用不同, 游戏可能需要包含多种不同类型的服务器,每类服务器在数量上也可能有不同的需求。这就需要框架对服务器进行抽象和解耦,支持服务器类型和数量上的扩展。
客户端的请求、响应、广播:客户端的请求、响应与web应用是类似的, 但框架是基于长连接的, 实现模式与http请求有一定差别。广播是游戏服务器最频繁的操作, 需要方便的API, 并且在性能上达到极致。
服务器间的通讯、调用:尽管框架尽量避免跨进程调用,但进程间的通讯是不可避免的, 因此需要一个方便好用的RPC框架来支撑。
松耦合、可插拔的应用架构:应用的扩展性很重要, pomelo framework支持以component的形式插入任何第三方组件, 也支持加入自定义的路由规则、 自定义的filter等。
浏览: 16374 次
很好的文章!!!!!!!!!!!!
(window.slotbydup=window.slotbydup || []).push({
id: '4773203',
container: s,
size: '200,200',
display: 'inlay-fix'GitHub 上有哪些不错的游戏服务器框架? - 知乎967被浏览<strong class="NumberBoard-itemValue" title="5分享邀请回答张小方:从零学习游戏服务器开发系列(一) 从一款多人联机实时对战游戏开始zhuanlan.zhihu.com最新的文章会首先发表在我的微信公众号『easyserverdev』中,欢迎关注: (二维码自动识别)更新下:最后一战源码技术交流可以加群:。1258 条评论分享收藏感谢收起235 条评论分享收藏感谢收起Scut快速开发(3)
1&&&&&&& 开发环境
需要安装的软件
a)&&&&&&& 消息队列
b)&&&&&&& 数据库,Sql2005以上版本
c)&&&&&&& VS2010开发工具(.Net Framework 4.0以上)
2&&&&&&& 代码框架
项目划分三层:实体层,组件层,业务逻辑层(脚本层);模型层主要是数据实体映射,自定义缓存结构;组件层主要负责实现中层层扩展功能;业务逻辑层主要负责实现游戏功能;
2.1&&&& 数据库创建
游戏划分成三个库:DemoConfig库(负责存储游戏配置数据) 、DemoData库(负责存储游戏玩家数据)和DemoLog库(游戏玩家日志记录数据);如图
&&& & & & & & & & & & &
这里只为每个库建立一张表:
地图信息配置表(MapInfo)DemoConfig库
create table MapInfo
MapId int not null,
MapName varchar(50) not null,
primary key(MapId)
玩家表(GameUser)DemoData库
create table GameUser
UserID int not null,
NickName varchar(50) not null,
varchar(50),
UserStatus int,
CreateDate
primary key(UserID)
--继承BaseUser基类
EXECUTE sp_addextendedproperty N'MS_Description', '玩家信息[:BaseUser]', N'user', N'dbo', N'table', N'GameUser', NULL, NULL
--自定义枚举
EXECUTE sp_addextendedproperty N'MS_Description', '玩家状态[Enum&UserStatus&]', N'SCHEMA', N'dbo',
N'table', N'GameUser', N'column', N'UserStatus'
--自定义实体类
EXECUTE sp_addextendedproperty N'MS_Description', '玩家属性[CacheList&Property&]', N'SCHEMA', N'dbo',
N'table', N'GameUser', N'column', N'Property'
玩家登录日志表(UserLoginLog)
create table UserLoginLog
ID int not null identity(1,1),
UserId varchar(50) not null,
varchar(50),
varchar(50),
CreateDate
primary key(ID)
2.2&&&& 数据实体生成
使用CodeSmith工具制作实体模板()来生成我们需要的实体类;打开EntityBuilding.cst文件,弹出窗口中进行配置相应属性,配置完成后点击&Generate&生成实体类;如图:
Config库配置,设置只读权限
增加数据库连接
Data库配置,设置成读写权限
Log库配置,设置成只写权限
打开F:\GameDemo\Code目录,可查看生成的数据实体类,创建好项目后将实体类文件Copy到项目对应的目录下
2.3&&&& 项目搭建
2.3.1&&&&&&& 创建解决方案
打开VS2010 在菜单上选择 文件 -& 新建 -& 项目;弹出&新建项目&对话窗口,在左则展开&其它项目类型&,选择&Visual Studio解决方案&,选择&.Net Framework 4.0&后,输出项目名称及位置,再点击&确定&;如图:
2.3.2&&&&&&& 创建项目
在&资源管理器&中添加新的几个项目Model、Lang、Com、Bll、HostServer;Model项目:负责从数据库中导出表的数据实体类映射;
Lang项目:负责多语言包;
Com项目:负责中间层组件扩展处理,及中间层业务实体类;
Bll项目:负责业务逻辑处理;
HostServer项目:控制台启动程序,及脚本(Python)业务逻辑处理;
创建项目结果如下:
设置控制台程序&HostServer&属性为&.Net Framework 4.0&
设置成&Release&编译方式
2.3.3&& Model项目
Plugin\Redis\protobuf-net.dll
Framework\V5.1\ZyGames.Framework.Common.dll
Framework\V5.1\ZyGames.Framework.dll
Game\V2.6\ZyGames.Framework.Game.dll
划分配置库(ConfigModel)、玩家信息库(DataModel)、玩家日志库(LogModel)和自定义类型数据实体(Model)目录存储数据实体类;&Enum目录存储自定枚举;
接着将之前使用CodeSmith生成好的实体类复制到相应的ConfigModel、DataModel和LogModel目录下,并在VS Model项目中将其包括在项目中;
接着编译Model项目会发现在GameUser类中缺少些命名空间引用,UserStatus枚举和Property类没有定义(注意到没,这些缺少的类和枚举就是在创建表时增加的配置);
在Model项目中分别在Enum目录与Model目录下增加UserStatus自定义枚举和Property自定义类;接收编译就可以成功了。(建议在GameUser类的构造函数中实例化Property属性及其它引用类型属性,在业务层使用中减少判断Null语句)
DbConfig类
在生成实体类时,生成配置ConnectKey项中使用
public class DbConfig
public const string Config = "DemoConfig";
public const string Data = "DemoData";
public const string Log = "DemoLog";
public const int GlobalPeriodTime = 0;
public const int PeriodTime = 0;
public const string PersonalName = "UserId";
//UserId:是玩家库中表的主键字段名称; 红色部分是需要修改的
项目建立完成如图:
2.3.4&& Lang项目
Framework\V5.1\ZyGames.Framework.Common.dll
Game\V2.6\ZyGames.Framework.Game.Lang.dll
负责处理多语言包配置,需要实现中层提供的语言包;以下是定义类
LanguageManager类
public class LanguageManager
private static object thisLock = new object();
private static Dictionary&LangEnum, IGameLanguage& _langTable = new Dictionary&LangEnum, IGameLanguage&();
private static LangEnum _langE
static LanguageManager()
_langEnum = (ConfigUtils.GetSetting("LanguageType", "0")).ToEnum&LangEnum&();
LanguageHelper.SetLang(_langEnum);
public static IGameLanguage GetLang()
return GetLang(_langEnum);
public static IGameLanguage GetLang(LangEnum langEnum)
IGameLanguage lang = null;
if (!_langTable.ContainsKey(langEnum))
lock (thisLock)
if (!_langTable.ContainsKey(langEnum))
switch (langEnum)
case LangEnum.ZH_CN:
_langTable.Add(langEnum, new GameZhLanguage());
throw new Exception("Language is error.");
lang = _langTable[langEnum];
IGameLanguage接口
public interface IGameLanguage : ILanguage
/// &summary&
/// 君主帐号
/// &/summary&
int SystemUserId { get; }
/// &summary&
/// 玩家名称
/// &/summary&
string KingName { get; }
string Date_Yesterday { get; }
string Date_BeforeYesterday { get; }
string Date_Day { get; }
string St1002_GetRegisterPassportIDError { get; }
string St1005_NickNameOutRange { get; }
string St1005_NickNameExistKeyword { get; }
string St1005_NickNameExist { get; }
string St1006_PasswordTooLong { get;}
string St1006_ChangePasswordError { get;}
string St1006_PasswordError { get;}
string St1066_PayError { get; }
#endregion
GameZhLanguage类
class GameZhLanguage : BaseZHLanguage, IGameLanguage
public int SystemUserId
get { return 1000000; }
public string KingName
get { return "系统"; }
public string Date_Yesterday { get { return "昨天"; } }
public string Date_BeforeYesterday { get { return "前天"; } }
public string Date_Day { get { return "{0}天前"; } }
public string St1002_GetRegisterPassportIDError { get { return "获取注册通行证ID失败!"; } }
public string St1005_NickNameOutRange { get { return "您的昵称输入有误,请重新输入!"; } }
public string St1005_NickNameExistKeyword { get { return "您输入的昵称存在非法字符,请重新输入!"; } }
public string St1005_NickNameExist { get { return "您输入的昵称已存在,请重新输入!"; } }
public string St1006_PasswordTooLong { get { return "输入错误,请输入4-12位数字或字母!"; } }
public string St1006_ChangePasswordError { get { return "修改密码失败!"; } }
public string St1006_PasswordError { get { return "密码格式错误!"; } }
public string St1066_PayError { get { return "充值失败"; } }
2.3.5&& Com项目
Plugin\Redis\protobuf-net.dll
Framework\V5.1\ZyGames.Framework.Common.dll
Framework\V5.1\ZyGames.Framework.dll
Game\V2.6\ZyGames.Framework.Game.Lang.dll
Game\V2.6\ZyGames.Framework.Game.dll
划分中间件业务实体(Model),聊天组件(Chat)与排行榜(Rank)等目录,如图:
需要使用中间层的功能,请参考《中间层使用文档》
2.3.6&&&Bll项目
Plugin\Newtonsoft.Json.dll
Plugin&\Python\IronPython.dll
Framework\V5.1\ZyGames.Framework.Common.dll
Framework\V5.1\ZyGames.Framework.dll & Framework\V5.1\ZyGames.Framework.Plugin.dll
Framework\V5.1\ZyGames.Framework.RPC.dll
Game\V2.6\ZyGames.Framework.Game.Lang.dll
Game\V2.6\ZyGames.Framework.Game.dll
Game\V2.6\ZyGames.Framework.Game.Contract.dll
创建Action目录划分接口协议处理逻辑;主要提供中间层定义的固定协议接口,如:登录(1004)与建角(1005)及充值中间层接口
ActionIDDefine类
public class ActionIDDefine
///&summary&
///客户端注册Socket
///&/summary&
public const Int16 Cst_Action100 = 100;
///&summary&
///错误日志
///&/summary&
public const Int16 Cst_Action404 = 404;
///&summary&
///注册通行证ID获取接口
///&/summary&
public const Int16 Cst_Action1002 = 1002;
///&summary&
///用户注册
///&/summary&
public const Int16 Cst_Action1003 = 1003;
///&summary&
///用户登录
///&/summary&
public const Int16 Cst_Action1004 = 1004;
///&summary&
///创建角色
///&/summary&
public const Int16 Cst_Action1005 = 1005;
&BaseAction类
public abstract class BaseAction : AuthorizeAction
protected BaseAction(short actionID, HttpGet httpGet)
: base(actionID, httpGet)
protected override bool IgnoreActionId
//排除不需要登录授权的协议接口
return actionId == ActionIDDefine.Cst_Action404;
2.3.7&& HostServer项目
HostServer
Plugin\Newtonsoft.Json.dll
Plugin\NLog.dll
Plugin\Redis\protobuf-net.dll
Plugin&\Python\IronPython.dll
Plugin&\Python\IronPython.Modules.dll
Plugin&\Python\Microsoft.Dynamic.dll
Plugin&\Python\Microsoft.Scripting.dll
Plugin\Redis\ServiceStack.dll
Plugin\Redis\&ServiceStack.Common.dll
Plugin\Redis\&ServiceStack.Interfaces.dll &
Plugin\Redis\&ServiceStack.Redis.dll
Plugin\Redis\&ServiceStack.Text.dll
Framework\V5.1\ZyGames.Framework.Common.dll
Framework\V5.1\ZyGames.Framework.dll & Framework\V5.1\ZyGames.Framework.Plugin.dll
Framework\V5.1\ZyGames.Framework.RPC.dll
Game\V2.6\ZyGames.Framework.Game.Lang.dll
Game\V2.6\ZyGames.Framework.Game.dll
Game\V2.6\ZyGames.Framework.Game.Contract.dll
划分PyScript目录,存放Python脚本文件;层次如图:
Action目录:处理请求与响应的脚本,可以协议生成器工具中Copy部分模板;
Lib目录:Python中间层脚本,复制Scut开发包中的PythonLib目录;
Remote:应用程序之间内通讯,访问时有IP访问限制;
Route.config.xml:是请求路由配置表,格式如下:
&?xml version="1.0" encoding="utf-8" ?&
&!--Python安装类库路径--&
&lib path="D:\Python\Lib" /&
&route-list&
&!--配置Action路由
action:映射的Action代码
path:指定执行的脚本路径
ignoreAuthorize:是否不需要登录授权,true:不需要登录授权
&route action="404" path="Action\action404.py"/&
&route action="1009" path="Action\action1009.py"/&
&/route-list&
&GameHostApp类
public class GameHostApp : GameHost
//public override void Listen()
//这里处理请求与响应模式,设置连接超时等些参数
//ServiceProxy.Listen(IpAddress, Port, conn, recv, inacv, connectCount);
//ListenAfter();
protected override void DoBindAfter()
//这里处理程序启动时逻辑
protected override void OnRequested(HttpGet httpGet, IGameResponse response)
//这里处理请求与响应模式
protected override void OnCallRemote(string route, HttpGet httpGet, MessageHead head, MessageStructure structure)
//这里处理服务器应用程序间通信
protected override void OnClosed(ChannelContext context, string remoteaddress)
//这里处理服务被关闭逻辑
protected override void OnSocketClosed(ChannelContext context, string remoteaddress)
//这里处理Socket服务被关闭逻辑
protected override void OnServiceStop(object sender, EventArgs eventArgs)
//这里处理服务被停止逻辑
class Program
static void Main(string[] args)
GameHost.Start();
宿主程序Config配置
&?xml version="1.0"?&
&configuration&
&configSections&
&section name="zyGameBaseBll" type="ZyGames.Framework.Game.Configuration.ZyGameBaseBllSection,ZyGames.Framework.Game"/&
&section name="zyGameBase-GM" type="ZyGames.Framework.Game.Command.GmSection,ZyGames.Framework.Game"/&
&section name="sdkChannel" type="ZyGames.Framework.Game.Sns.Section.SdkChannelSection,ZyGames.Framework.Game"/&
&/configSections&
&appSettings&
&!--消息队列异步写库配置--&
&add key="MessageQueuePath" value=".\private$\DemoCmdSql"&&/add&
&add key="MessageQueueNum" value="10"&&/add&
&!--宿主程序启动配置--&
&add key="Game.Host.TypeName" value="Demo.HostServer.GameHostApp,Demo.HostServer"/&
&add key="Game.Action.TypeName" value="Demo.Bll.Action.Action{0},Demo.Bll"/&
&!--Port:接收请求的端口
connectTimeout:建立连接和传送数据的超时间(默认10秒)
receiveTimeout:保持连接的情况下,空闲超时触发Closing事件,尽量最大,默认10分钟
inactivityTimeout:连接断开的情况下,空闲超时触发Faulted事件,要小于receiveTimeout时间间隔(默认5秒)
connectCount:允许连接的并发数,默认100
&add key="Game.Port" value="9001" /&
&add key="Game.wcf.ConnectTimeout" value="10" /&
&add key="Game.wcf.ReceiveTimeout" value="1800" /&
&add key="Game.wcf.InactivityTimeout" value="5" /&
&add key="Game.wcf.ConnectCount" value="1000"/&
&!--Code:游戏代码;ServerId:游戏分区代码--&
&add key="Product.Code" value="1"/&
&add key="Product.Name" value="游戏名称"/&
&add key="Product.ServerId" value="1"/&
&!-- 配置语言版本,ZH_CN:简体,EN_US:英文,BIG5_TW:繁体 --&
&add key="LanguageType" value="ZH_CN"/&
&!--发布的版本类型,Debug:测试,Release:正式--&
&add key="PublishType" value="Debug"&&/add&
&!--GM功能是否开启,true:开启--&
&add key="EnableGM" value="true"&&/add&
&!--协议接口请求超时监控,单位毫秒--&
&add key="ActionTimeOut" value="600"&&/add&
&!--Python脚本配置
Python_IsDebug:是否开启调试功能
PythonRootPath:脚本路径,相对于程序运行目录
&add key="Python_IsDebug" value="true"/&
&add key="PythonRootPath" value="..\..\PyScript"/&
&!--游戏缓存配置
global.period:全局缓存生命周期24小时
user.period:玩家缓存生命周期8小时
CacheManager_Interval:缓存监控时间间隔
&add key="Cache.global.period" value="86400"/&
&add key="Cache.user.period" value="28800"/&
&add key="CacheManager_Interval" value="6000"/&
&!--通用组件配置开始--&
&add key="PayDB_ConnectionString" value="Data Source={0};Database=PayDB;{1}; Pooling="/&
&add key="PayDB_Server" value="."/&
&add key="PayDB_Acount" value="加密密码"/&
&add key="Snscenter_ConnectionString" value="Data Source={0};Database={1}; Pooling="/&
&add key="Snscenter_Server" value="."/&
&add key="Snscenter_Acount" value="加密密码"/&
&!--通用组件配置结束--&
&/appSettings&
&connectionStrings&
&add name="DemoConfig" providerName="" connectionString="Data Source=.;Database=DemoCUid=;Pwd=; Pooling="/&
&add name="DemoData" providerName="" connectionString="Data Source=.;Database=DemoDUid=;Pwd=; Pooling="/&
&add name="DemoLog" providerName="" connectionString="Data Source=.;Database=DemoLUid=;Pwd=; Pooling="/&
&/connectionStrings&
&!--业务层自定义配置--&
&zyGameBaseBll&
&login defaultType="ZyGames.Framework.Game.Sns.Login36you,ZyGames.Framework.Game"&
&retailList&
&add id="0000" type="ZyGames.Framework.Game.Sns.Login36you,ZyGames.Framework.Game" args="Pid,Pwd,DeviceID"/&
&/retailList&
&/zyGameBaseBll&
&zyGameBase-GM&
&!--GM:cache--&
&/command&
&/zyGameBase-GM&
&supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/&
&/startup&
&/configuration&
2.4&&&& 定义协议
打开协议生成器工具,增加一个&Demo&项目方案,接着在增加协议(或从现有项目中Copy相同的接口协议),接着定义客户端提供的请求参数和服务器下发的参数(支持多行的格式,字段类型:Record与End组合);定义好客户端与服务器之前通讯的接口后,使用自动生成的服务端Python代码(客户端使用Lua脚本代码)复制到已创建的Python接口文件,如图:
2.5&&&& 项目部署
需要架设Socket方式的分发器(或Http方式的分发器,两都可一起架设),将客户端请求先通过Socket或Http分发器再转发到游戏服务器(HostServer程序)上;
2.6&&&& Socket分发器
使用OA部署功能架设分发器;在本机使用批处理文件,如下:
C:\Windows\System32\schtasks.exe /Create /RU system /TN DemoSocketApp /SC ONSTART /TR " F:\Demo Socket\Doudizhu\ZyGames.Framework.Game.SocketServer.exe" /F
2.7&&&& HostServer程序
使用OA部署功能架设游戏服;在本机使用批处理文件,加在任务计划中启动,如下:
C:\Windows\System32\schtasks.exe /Create /RU system /TN DemoHostApp /SC ONSTART /TR "F:\Demo\Demo.HostServer.exe" /F
开源地址GitHub地址:
来园子已经两年了,每次都是看,这次咱也写一次。
说一下今天遇到的Linq问题:
每一次插入流水表时,都需要查找表中最大的流水号+1,并且将该流水号返回,但是在同一个SubmitChange之内插入多条时,流水号就一直是表中实际最大的,而不是我上一次插入的最大的。不描述了 贴代码:
这个是DataContext
&View Code
&两个公用方法:
&View Code
&View Code
第一种情况:修改提交前可以重新查询获得已经更新的内容,读取的是内存中的&未使用隐式事务
&View Code
第二种情况:添加后未提交前取得的最大的Number值永远是数据表中真实的值,不是内存中的&未使用隐式事务
&View Code
第三种情况:开启隐式事务,添加后提交前取得的最大的Number值是我想要的值,最后再Commit
&View Code
这就是今天遇到的问题,现在没办法只能开启隐式事务了,不过为什么第二种情况达不到我想要的结果呢?求大神解。
阅读(...) 评论()
随笔 - 16608
评论 - 1579

我要回帖

更多关于 java游戏服务器框架 的文章

 

随机推荐