网络在线游戏开发心得(服务器端、java)

上传人:kms****20 文档编号:41228952 上传时间:2018-05-28 格式:DOC 页数:8 大小:31.50KB
返回 下载 相关 举报
网络在线游戏开发心得(服务器端、java)_第1页
第1页 / 共8页
网络在线游戏开发心得(服务器端、java)_第2页
第2页 / 共8页
网络在线游戏开发心得(服务器端、java)_第3页
第3页 / 共8页
网络在线游戏开发心得(服务器端、java)_第4页
第4页 / 共8页
网络在线游戏开发心得(服务器端、java)_第5页
第5页 / 共8页
点击查看更多>>
资源描述

《网络在线游戏开发心得(服务器端、java)》由会员分享,可在线阅读,更多相关《网络在线游戏开发心得(服务器端、java)(8页珍藏版)》请在金锄头文库上搜索。

1、网络在线游戏开发心得网络在线游戏开发心得( (服务器端、服务器端、Java)Java)这个项目的一个特别之处是,客户端是手机,用户通过移动网络与服务器通信。和 PC 相比,手机的处理能力极弱,而且网络流量费用昂贵。因为除了要考虑普通网络游戏的一些问题之外,这两点也需要在设计中充分考虑。首先是开发语言的选择,由于服务器是 Linux 的环境,MS 的技术直接排除,至于 MONO 嘛,我实在不放心。可供选择的是 C+和Java,Java 胜在网络能力强大,开发周期短,有众多框架和开源库的支持,要写出烂得不可接受的代码也不容易;C+则胜在速度快。综合各方面因素,C+更容易把这个项目变成一堆代码噩梦,

2、我们选择了 Java。一、网络网络游戏,首先面临的问题当然是如何进行网络通信。首先考虑的是 HTTP 协议,因为所有的 J2ME 手机都支持这个,我们当然想尽可能的兼容用户。而且 HTTP 协议封装程度已经非常高了,不用去考虑线程、同步、状态管理、连接池,不过 HTTP 协议有两个不爽的地方: 协议无状态,这个问题已经困扰过很多人很多次了。我曾考虑过的解决办法是改造 HTTP 协议,在数据传输完成之后不关闭socket,但是这样做工作量非常大,在项目周期中,基本上就是Mission impossible,不予考虑。那么客户也就只能通过轮询的方式向服务器请求数据。 网络流量过大。就这个项目来说,

3、网络间传递的只是指令,但是每次传递都要加上一堆毫无用处的 HTTP Head,再加上客户端需要做轮询,这个流量对于手机来说简直恐怖,经简单测试,按照0.03 元/K 的 GPRS 网络费用计算,一局牌居然要消耗 1 元多的费用(每秒轮询) ,实在不可接受。也许我们可以采用流量费包月的资费方式,不过这个话题与技术无关。以上问题导致我们选择了 Socket,这意味着我们将没有一个web 环境,很多东西都要靠自己去实现:线程管理、客户状态监控、对象池、控制台.网络部分打算采用 Java NIO 来实现,这是一种新的网络监听方式,基于事件的异步通信,可以提高性能。每个客户端连接之后,会有一个独立的 S

4、ocketChannel 与它通信,这个 SocketChannel 会在用户的整个生存周期中存在。用户如果断开连接,服务器会得到-1,并且会抛出 Connection reset 异常,通过捕获这两个特征,可以在用户意外断开连接后清理相关的资源。由于 NIO 是异步通信的,所以没有复杂的线程管理。二、通信协议这个项目并没有复杂的通信指令,命令数量很有限,但是还是有个关键问题需要关注:流量。为了尽量减小流量,我们使用字节代替字符串来保存系统指令,这样可以使流量减少一半,比如使用一个字节来保存一张扑克int m=0;int n=3;byte card=(byte)(m) (24 - i * 8)

5、;return b;将四个字节转回来的操作如下:public static long translateByte(byte b)int mask = 0xff;int temp = 0;int res = 0;for (int i = 0; i 4; i+)res = 8;temp = bi res |= temp;return res;三、数据库连接池由于没有一个 web 环境,所以我们需要自己实现一个数据库连接池,apache 有一个项目叫做 commons DBCP,这是一个基于apache 自己的对象池(apache commons pool)实现的数据库连接池,我们可以直接拿来使用,

6、apache 的软件未必是最好的,但是极大可能比我们自己写的要好。Commons DBCP 需要三个.jar:commons-collections-3.1.jar、commons-dbcp-1.2.1.jar、commons-pool-1.2.jar这三个文件都可以在 apache Jakarta commons 项目下下载,加入到工程中即可。构造一个数据库连接池的代码如下:import java.sql.*;import com.gwnet.games.antiLord.util.*;import mons.dbcp.ConnectionFactory;import mons.dbcp.B

7、asicDataSource;import mons.dbcp.DataSourceConnectionFactory;private static BasicDataSource bds=new BasicDataSource();private static ConnectionFactory fac=null;/初始化连接池bds.setDriverClassName(“org.postgresql.Driver”); /数据库驱动程序bds.setUrl(“jdbc:postgresql:/localhost:5432/myDB”); /数据库 urlbds.setUsername(“

8、postgres”); /dba 帐号bds.setPassword(“XXXXXXXX”); /密码bds.setInitialSize(100); /初始化连接数量bds.setMaxIdle(10); /最大 idle 数bds.setMaxWait(1000*60); /超时回收时间fac=new DataSourceConnectionFactory(bds); /得到连接工厂Connection conn=fac.createConnection(); /从池中获得连接conn.close(); /释放连接,回到池中/销毁连接池bds.close();bds=null;fac=nu

9、ll;请自行处理操作中的各种异常。四、扑克牌的生成游戏中需要为用户生成随机的扑克牌,首先我们需要初始化一副牌,放到一个 Hashmap 中,每张牌以一个字节表示,高为代表花色,的为代表数字,生成整副牌:private static HashMap cards = new HashMap();int tmp=0;for (int i = 0; i 4; i+) for (int m = 0; m 13; m+) tmp=(byte)(i)4)|(byte)m); /使用位操作构造一张牌cards.put(new Integer(i * 13 + m),new Byte(byte)tmp);car

10、ds.pcards.put(new Integer(54), new Byte(byte)0x4e); /小王如何随机地得到其中的 N 张牌呢?我们的做法是生成一个 0-55 的随机数,用这个随机数作主键从 Hashmap 中获得对象,取得之后,把该对象从队列中删除,以免重复取得。由于 java 中的随机数是根据时间生成的,所以有可能导致用户得到的牌不够散,每个用户都摸到一条龙岂不是笑话?所以在生成随机数的时候我们加入了一个大素数来作运算:long cardId=new Long(Math.round(Math.random() * 87) % 55).intvalue();通过修改这个大素数

11、,可以控制某个用户的牌比较好。五、线程实际上本系统并没有复杂的线程管理,但是我想提供一个控制台让管理员可以管理游戏主线程,可以让它停止、中段、恢复、重启动,本来的设计是管理员通过与线程 A 打交道,通过 A 去管理主线程 B,但是熟悉 java 线程的朋友都知道,线程互相管理基本上就是不实际的,举个最简单的例子,A 如何销毁 B?也许你会说调用 B的 destroy()方法就好了,网上很多讲解 java 线程的资料也确实是这么说的,但是他们都是鬼扯的,自己去看看 java 源代码吧,Thread.destroy()方法的实际代码如下:public void destroy() throw ne

12、w NoSuchMethodError();事实真相是,Thread.destroy()方法自始至终就没有被实现过。所有写文章,教别人用这个方法销毁线程的人,都去撞墙吧,丢人丢大了。最好的办法是 A 负责生成一个 B 并且启动它,然后 B 自己管理生存周期,A 和 B 通过使用可共享的方法来通信,这是 sun 推荐的做法。六、异步消息用户玩牌的过程中,有很多东西需要记录下来,比如记录用户的积分、等级变化,记录玩牌日志供数据统计等,当用户数量很多的时候,在数据库中记录这些信息会很耗费资源,用户玩了一局之后会可能会等待很长时间。解决这个问题的方法是利用 J2EE 的消息bean 来提供异步通信的机

13、制,需要记录数据的时候,系统会封装一个值对象,发送给 J2EE 容器,这个操作是很快的,完成之后就返回,用户可以继续操作,不用关心消息何时被处理。J2EE 的消息框架具备如下特征: 消息一定会被阅读,而且只阅读一次。JMS 框架有自己的算法,把消息缓冲到硬盘,就算 J2EE 服务器死掉,消息也不会丢失。 系统采用点对点的 Queue 消息队列,可以保证同等优先级的消息先进先出。在 Jboss 4.0 中,部署消息 Bean 和 Queue 队列,都比weblogic 8.1 来的容易,只需要在 jboss.xml 中声明消息目的地,如果 jboss 发现该目的地不存在的话,会自动建立一个,实在

14、很简单。七、启动与退出为在数据库连接池的问题上,我们也采用同样的操作,启动的时候初始化 N 个连接。但是如果在关闭进程的时候不做任何操作,会导致 JMS 抛出 socket 异常,虽然没什么大的影响,但总显得不专业,而且池中的连接不被释放的话,也可能导致问题。最好能够让系统像 jboss 等控制台程序一样,ctrl+c 之后能够执行操作,释放资源再退出。我们可以通过给进程/线程加上一个 Hook 来实现,windows程序员应该对这个非常熟悉。Hook 应该是一个线程方法,如下:public class Hook extends Threadpublic void run()/释放数据库连接,销毁连接池/关闭与 JMS 的连接在主线程中加入:Runtime.getRuntime().addShutdownHook(new Hook() ;那么进程/线程会在退出的时候执行 Hook 的 run 方法,清理资源。

展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 生活休闲 > 科普知识

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号