首    页 界面/窗口 网络/通讯 数据库 组件开发 图像/多媒体 NET/Web 其它技术 源码下载 资料下载 软件共享 软件外包 曲艺杂谈
栏目导航:  首    页  |  网络/通讯  |  棋牌游戏


发布GameHall 2.0 a测试版本源码


原作者:包建强    源出处:博客园    发布者:施昌权    发布类型:转载    发布日期:2009-03-21


  

代码下载:http://files.cnblogs.com/Jax/GameHall-2.0-a.rar(含DB)

我申请的CodePlex:http://www.codeplex.com/GameHall(还来不及把源码放上去)

 

这个版本只实现了大厅,不包括任何游戏。用户可以同时进入多个大厅,但是只能在一个大厅的桌子坐下,进行游戏。

目前仍基于Winform开发,只使用到了.NET 3.5中的LINQ技术处理数据,并大量使用了C# 3.0中的语法糖。

使用了泛型事件和函数式编程,从而完全消除了对Delegate的依赖。

使用TCP Socket通信,抽象出了通信层,为以后版本更换通信方式做准备。

使用了HandShake模式,Client是主动的,Server端是被动的。也就是说,有Request才会有Response。所有38个自定义协议请参见Protocol.txt文件。

在桌子的选择上(4人桌打牌、2人桌下棋)实现了面向接口编程,从而将来能够灵活地增加3人桌和5人桌。这只是一个小的尝试,将来游戏也会采用这套机制。

对非法退出进行了精确地控制。

这个项目有很大的扩展性。一是通讯上的扩展,可以轻松更换TCP连接、UDP连接、HTTP连接等等。二是易于加载新游戏,也就是插件技术,而不用改动大厅程序。

不要怪我很少捕获异常。我是有苦衷的,尤其是Server端的处理要考虑到性能,不能加太多。

附带两个小程序。一个是NAT打洞技术的实现(为以后使用局域网的用户开发);另一个是WPF+WCF版本的简易聊天室(在Jacob老兄的一个源码上进行了重构,是接下来升级WCF的测试程序)。

所有代码我都进行了多轮阶段性测试。但还是要请大家为我挑毛病(尤其是测试人员)。主要集中在Client端。

 

部分界面如下:

Server端:只是一个CUI程序

image

Client端:

1)登陆成功,从Server端得到游戏列表并绑定到左边的Treeview。由于未联系到广告商,只好放美女照片。

image

2)进入“棋类”大厅(2人桌),左边是用户列表和聊天信息

image

3)进入“牌类”大厅(4人桌)

image

4)放大了看:

a

 

话说,我写这套开源项目,就是为了向世人展现.NET的所有新技术,而并不注重实用性和太复杂的业务逻辑。因此,把原先“只能进入一个大厅”改为“可以同时进入多个大厅”,所增加的逻辑复杂度,是我没有预料到的。为此我在大年初一熬了一个通宵修改数据结构,这也是我很后悔的一件事情。“不要把逻辑搞得很复杂”,将是我接下来的宗旨。但是,安全性和性能,我还是会很在意的。

实战中遇到了很多平时做研究时没有遇到的问题,解决起来煞费周折,我会把这些经验发布到blog上,以飨后人。

 

重头戏在接下来半个月的开发。WPF、WCF、WF和SilverLight还没出场呢!其中WCF与WF的整合是关键。WPF则主要用来展示Data Binding技术(这门技术决对比WInform好很多很多)。SilverLight用于用户注册。


发表评论
  回复  引用  查看    
#1楼 2009-02-08 04:02 | xiaotie      
赞一下,这么晚了还没睡
  回复  引用  查看    
#2楼 2009-02-08 08:32 | 侯垒      
支持一把.
  回复  引用  查看    
#3楼 2009-02-08 08:51 | gqzhao      
佩服楼主的恒心和毅力
  回复  引用  查看    
#4楼 2009-02-08 09:51 | Leepy      
关注!
  回复  引用  查看    
#5楼 2009-02-08 09:58 | Angel Lucifer      
如果要展示新技术,不用拿这种需要高性能的领域开刀吧。
老实说,这些新技术用在这里完全是用错了地方。
不但不实用,而且误导初学者。

建议包兄或许可以在合适的领域尝试使用这些技术?

PS : 佩服包兄的精神。
  回复  引用  查看    
#6楼 2009-02-08 10:50 | chegan      
真高人
  回复  引用  查看    
#7楼 2009-02-08 10:59 | 韦恩卑鄙      
支持支持
  回复  引用  查看    
#8楼 2009-02-08 11:34 | AlexChen      
支持您....

  回复  引用    
#9楼 2009-02-08 12:13 | game [未注册用户]
有为技术而使用技术的了,
  回复  引用  查看    
#10楼 2009-02-08 12:57 | 哥哥.Net      
--引用--------------------------------------------------
Angel Lucifer: 如果要展示新技术,不用拿这种需要高性能的领域开刀吧。
老实说,这些新技术用在这里完全是用错了地方。
不但不实用,而且误导初学者。

建议包兄或许可以在合适的领域尝试使用这些技术?

PS : 佩服包兄的精神。
--------------------------------------------------------
佩服包兄的精神,但新技术也不代表低性能----
  回复  引用  查看    
#11楼 2009-02-08 14:54 | Jeffrey Zhao      
异常对性能的影响没有那么大,我估计你的游戏的性能主要在于通信,完全不在运行上。
  回复  引用  查看    
#12楼 2009-02-08 15:03 | Jeffrey Zhao      
--引用--------------------------------------------------
Angel Lucifer: 如果要展示新技术,不用拿这种需要高性能的领域开刀吧。
老实说,这些新技术用在这里完全是用错了地方。
不但不实用,而且误导初学者。

建议包兄或许可以在合适的领域尝试使用这些技术?

PS : 佩服包兄的精神。
--------------------------------------------------------
同意一半。
不同意,是因为新技术也可以高性能。
同意,是因为为了展示技术而展示技术,不可取。
  回复  引用  查看    
#13楼 2009-02-08 16:50 | Angel Lucifer      
@Jeffrey Zhao
很遗憾,在游戏开发领域,无论是 WPF 还是 WCF 根本没有用武之地。
它或许可以跟 .NET Remoting 进行评测,但是要跟 C++ 等游戏开发库比,死的会很惨。

提高性能的话,还是要看场合,分情况。游戏开发,尤其是网络游戏开发领域针对 .NET 3.0 的新技术非常不适合。
  回复  引用  查看    
#14楼 2009-02-08 17:24 | Jeffrey Zhao      
@Angel Lucifer
误会,我说的“新技术”是泛指,并不是说包子用的那些,呵呵。
所以我说,我不同意说高性能领域不能用新技术,但是我同意你说包子现在这么用是错误的。
  回复  引用  查看    
#15楼 2009-02-08 17:29 | Jeffrey Zhao      
@包子
还有就是,函数式编程是指什么?C#中使用函数式编程完全是在自找麻烦,只能用来表现特点,而不应该用于实际项目。
我估计你是指你用了不少Lambda表达式?附Functional Programming的定义:http://en.wikipedia.org/wiki/Functional_programming
  回复  引用  查看    
#16楼 2009-02-08 18:14 | Jeffrey Zhao      
@Angel Lucifer
对了,话说我想到了一些东西,讨论一下啊。
你说WCF的性能不足以XXYYZZ,我想了一下,确切地说,应该是指WCF自带的Binding性能不足,但是自带的Binding主要是为了实现工业界的“应用协议”,并且因为需要满足很多特殊的需求造成了性能下降。
但是WCF其实很多情况下是构成了一个“框架”,而并不仅仅是一个“实现”,如果在WCF的框架下定义一个自己的通信方式,是否就会让性能得到很大的提高?通信最终基于的是“通信协议”,而这一块往往还是由操作系统的实现来决定的,如果一个应用的性能关键在于通信,我猜想只要实现正确,C++也好.NET也罢,性能应该是差不多的。
至于WPF,我不了解。但是我听说WPF大都也是在封装DirectX,我想在Windows下不会有人去离开DirectX或OpenGL这种去实现一种新的引擎,因此如果要有性能差居,还是体现在使用方式上。如果.NET和C++实现的有性能差距,那么差距是因为什么造成的?因为托管代码和本地代码?我觉得这个站不住脚。例如,虽然Managed DirectX不成功,但是其缺点在于“几乎没有解决任何问题”,而不是托管代码的性能问题。以前看到过一片Managed DirectX Team的人写的文章,他谈到,虽然很多人的逻辑是“因为托管代码性能差,所以Managed DirectX性能差”,但是这是在“想当然”,从性能相关的多个真实case上来看,造成性能差距的是“用错了(例如使用思维没有转过来)”,而不是Managed DirectX本身的性能问题。
那么,WPF/WCF是否真的,肯定,一定不适合“不能直接适合”的领域吗?
  回复  引用  查看    
#17楼 2009-02-08 21:11 | Angel Lucifer      
@Jeffrey Zhao
前提 : 不谈 C++ 与 C# 之间的性能差距和使用新技术带来的成本(比如学习成本等)。

俺同意造成性能差距的主要原因是“用错了”。Managed DirectX 是个很好的示例。根据 Microsoft 官方资料显示,Managed DirectX 的性能达到原生 DirectX 的 98% 以上,唯一的损失就在托管封装消耗上。

但是对于 WCF 和 WPF ,俺还是持慎重的态度。特别是在那些严格要求性能的领域。下面是俺的看法(纯粹探讨,没有实际数据,可能不正确)。

以俺的理解,WCF 实际上是 Microsoft 推出的统一 Windows 平台混乱的 RPC 解决方案,特别是针对现在流行的 SOA 。WCF 很大程度上脱胎于 .NET Remoting,而 .NET Remoting 很大程度上脱胎于 DCOM(这几个技术经常被比较)。性能受架构设计的影响很大。即使我们遵守规范,协议实现一个 UDP 通道,它跟直接使用 Socket 还是有着不可忽视的性能差距。

至于 WPF ,俺认为它在很多方面超越了 Windows Form 技术。但是,它非常受限于 GPU 硬件架构。它现在封装的是 Direct3D 9。Direct3D 9 跟 Direct3D 10 架构上就有很大不同。10 比 9 无论在 3D 图形渲染还是在通用计算上都更进了一步(看,新技术高性能)。拿包兄的游戏客户端来说,可以尝试。但是在更普遍的亟需图形渲染的游戏客户端来说,完全不适合。我们可以看一下使用图形渲染的途径。首先通过 CPU 告知 GPU,然后 GPU 进行渲染。这是个非常密集型计算,CPU 和 GPU 都很繁忙。大家可能觉得图形渲染都交给 GPU 去做了,CPU 还忙啥?CPU 忙着与 GPU 交互通信和业务逻辑处理。WPF 本身就不是为此密集计算设计的,它中间要走好几层才能从 CPU 到达 GPU(要做平台带来的副作用)。在如此频繁的计算中,还要再加上中间这几层,至少以现在的 CPU 和 GPU 还难以应付。

俺的看法很简单 : 使用新技术要分场合。

PS : 我仔细查看了我的评论,并没有发表新技术不能应用在高性能领域的言论啊。不知道老赵和哥哥.NET是怎么得出这样的结论的?郁闷。
  回复  引用  查看    
#18楼 [楼主]2009-02-08 21:45 | 包建强      
新技术上,其实性能瓶颈在Server端.Client再怎么折腾都无所谓.
这就有问题了.Server只使用了LINQ和WF.WF肯定是瓶颈,不去说它(游戏大厅中使用完全是附庸风雅). LINQ平白无故的搞出N多小对象出来(相比原先用DataTable而言),使得我的GC很频繁.1万人在线,这才是最大的问题.
LINQ美,但在这里不实用。

  回复  引用  查看    
#19楼 2009-02-08 21:46 | Jeffrey Zhao      
@Angel Lucifer
关于WCF:那么我们直接基于Socket开发一个binding会不会好呢?
关于WPF:还是不动WPF,呵呵。

PS:嘿嘿,主要是这句话没有说清楚上下文:“如果要展示新技术,不用拿这种需要高性能的领域开刀吧”,如果加上“这些”就好了。
  回复  引用  查看    
#20楼 [楼主]2009-02-08 22:07 | 包建强      
@ Jeffrey Zhao
目前我就是基于Tcp Socket自己开发的。但还没有封装成WCF,因为要自定义信道、绑定等等很多东西。
  回复  引用  查看    
#21楼 [楼主]2009-02-08 22:08 | 包建强      
@ Jeffrey Zhao WPF强大的数据绑定是难以描述的,远胜于Winform。
  回复  引用  查看    
#22楼 2009-02-08 22:28 | Jeffrey Zhao      
@包建强
你又分不清LINQ和LINQ to SQL了。
还有对象数量,我不觉得会比DataTable对象多,DataTable每一行就是个DataRow,每一格还是个Cell,比LINQ to SQL中单纯的对象数量还多?
  回复  引用  查看    
#23楼 2009-02-08 22:37 | Jeffrey Zhao      
--引用--------------------------------------------------
包建强: @ Jeffrey Zhao
目前我就是基于Tcp Socket自己开发的。但还没有封装成WCF,因为要自定义信道、绑定等等很多东西。
--------------------------------------------------------
我已经不管表现层技术了,我关心表现层向下的,以及纯粹的编码方式上。
  回复  引用  查看    
#24楼 2009-02-08 22:45 | asboy      
佩服楼主的精神,期待看到客户端掉线如何处理,呵呵
这个地方我不太懂,
以前偷懒用FLASH做客户端,掉了直接踢出去 哈哈
  回复  引用  查看    
#25楼 [楼主]2009-02-08 23:48 | 包建强      
@asboy
客户端掉线我已经实现了,而且很完美。TcpSocket接不到消息就认为吊线。你可以仔细看我的代码。
  回复  引用  查看    
#26楼 2009-02-09 09:11 | 蛙蛙池塘      
祝贺一下
  回复  引用  查看    
#27楼 2009-02-09 09:28 | 狼Robot      
学习
  回复  引用  查看    
#28楼 2009-02-09 12:55 | 韦恩卑鄙      
--引用--------------------------------------------------
Jeffrey Zhao: @包建强
你又分不清LINQ和LINQ to SQL了。
还有对象数量,我不觉得会比DataTable对象多,DataTable每一行就是个DataRow,每一格还是个Cell,比LINQ to SQL中单纯的对象数量还多?
--------------------------------------------------------
恩 不过如果还是用 datatable 用linq 2 dataset 还是会多出不少小对象来哦
:P
  回复  引用    
#29楼 2009-02-12 19:39 | 未登录的王亮 [未注册用户]
请问楼主,如果用如下代码重复发送登陆请求,只为了做一些压力测试,发现客户端只有一个成功提示,服务端只有几次获取请求,为什么呢?

如果 在 while 中 让线程等待1s,就可以成功。

难道 socket 通讯,两个请求一定要间隔一定时间?

class Program
{
static void Main(string[] args)
{
int i = 0;
while (i < 10)
{
Authenticate();
i++;
}
Console.WriteLine();

}

private void Authenticate()
{
Cursor = Cursors.WaitCursor;
Refresh();

btnOk.Enabled = false;

SocketHelper.Instance().BuildText += OnBuildText;

try
{
SocketHelper.Instance().Listen();

RequestLogin user = new RequestLogin
{
Protocol = "501",
LoginUserId = txtLoginUserId.Text.Trim(),
Password = txtPassword.Text.Trim()
};

SocketHelper.Instance().Send(user);
}
catch
{
SocketHelper.Instance().Disconnect();
MessageBox.Show("Can't connect to Server...");

SocketHelper.Instance().Dispose();

btnOk.Enabled = true;
Cursor = Cursors.Default;
}
}

public void OnBuildText(object sender, EventArgs e)
{
CommonProtocol obj = (CommonProtocol)sender;
string protocol = obj.Protocol;

switch (protocol)
{
case "502.1":
ResponseLoginSuccessfully responseUser = (ResponseLoginSuccessfully)obj;

UserSettings.Initialize();

UserSettings.Instance.LoginUserId = txtLoginUserId.Text.Trim();
UserSettings.Instance.RememberPassword = chkRememberPassword.Checked;
UserSettings.Instance.AutoLogin = chkAutoLogin.Checked;

if (chkAutoLogin.Checked || chkRememberPassword.Checked)
{
UserSettings.Instance.Password = txtPassword.Text.Trim();
UserSettings.Instance.Serialize();
}
else
{
UserSettings.Instance.Serialize();
UserSettings.Instance.Password = txtPassword.Text.Trim();
}

UserSettings.Instance.LoginStatus = true;
UserSettings.Instance.UserId = responseUser.UserId;
UserSettings.Instance.UserName = responseUser.UserName;
UserSettings.Instance.ImageIndex = responseUser.ImageIndex;

SocketHelper.Instance().BuildText -= OnBuildText;

DialogResult = DialogResult.OK;

ConsoleOutput.ShowLogin(responseUser.UserId, responseUser.UserName);

break;
case "502.0":
SocketHelper.Instance().Dispose();
MessageBox.Show("Make sure you UserID and password is right.");

Action method = () => SetFormControl();
this.Invoke(method);

break;
}
}
}
  回复  引用    
#30楼 2009-02-12 19:48 | 未登录的王亮 [未注册用户]
也尝试过 并发10个线程 同样服务端只能获取几个请求,远远不及发送数量
  回复  引用    
#31楼 2009-02-12 20:11 | 未登录的王亮 [未注册用户]
一下是异常信息

IOExceptionwas unhandled

nable to read data from the transport connection: The IAsyncResult object was not returned from the corresponding asynchronous method on this class.
Parameter name: asyncResult.
  回复  引用  查看    
#32楼 [楼主]2009-02-12 21:32 | 包建强      
@王亮
感谢你能测试我的程序。
压力测试的玩法我不了解。
但我对你这样测试抱有怀疑。因为是一个CLient,所以Server只会认为是一个人连了10次。这是为什么报错的原因。
或许压力测试应该模拟不同Client才OK。
有不对的地方请指教。
  回复  引用  查看    
#33楼 2009-02-23 14:25 | 腾云驾雾      
赞一下
  回复  引用    
#34楼 2009-02-24 16:32 | A.Z! [未注册用户]
如果是界面的话我个人的看法是传统的GDI+已经可以满足需求了,WPF也未尝不可作为一种绘制方式,不过在性能比较差的显卡上会出现比较明显的API调用迟缓现象,后期ms对wpf有所改进,但是好像还是没有很大的飞跃。
通讯层使用WCF统一架构也是可以的,但是服务器的代码必须要充分的设计满足小数据量的密集型的请求报文,其中还有客户端的状态设计超时的状态转化和相应的故障时的持久化处理,状态集合的缓存,提供查询接口。真实情况还需要做到可负载均衡。对于协议中可能遇到的请求攻击也要做到合理的预防。
技术可能说不上,其实都是ms的平台,只是一个较为高级的实现。
  回复  引用  查看    
#35楼 [楼主]2009-02-24 16:40 | 包建强      
WPF+WCF的版本我已经写出来了,这几天完善一下,3月1号之前会发布。
WPF的绑定技术真的是很酷。



关于我们 版权声明 广告服务 联系我们 友情链接 加入收藏
站长:施昌权    Email:scq2099yt@163.com    MSN:scq2099yt@live.cn    QQ:14046300    本站QQ群:67202409
Copyright © 2008     卓为VC(www.joyvc.cn)    All Rights Reserved    建议分辨率 1024×768
本站由施昌权制作维护
京ICP备09012297号