找回密码
 注册
楼主: sjinny

网络游戏::服务器端::设计::讨论

[复制链接]
 楼主| 发表于 2003-11-5 20:45:04 | 显示全部楼层
是呀,然而还有个麻烦的地方,当网络上发来一个数据包后,我们怎么知道这个数据包是谁发送的?我们还得知道发送这个数据包的客户端控制着哪个人物~~~总不能每次都要遍历整个场景去查找吧?那可要遍历成百上千的对象啊~~
回复

使用道具 举报

发表于 2003-11-5 20:51:10 | 显示全部楼层
尽管一个服务器中会存在成百上千的人物,但是每个人物必然对应的是一个Client,每个Client在网络必然拥有一个唯一的IP地址,这样的话,难道你还不知道这个数据包是发给谁的吗?
回复

使用道具 举报

发表于 2003-11-5 21:31:35 | 显示全部楼层
你有没有去www.gameres.com看看,有不少资料

另外,我看了你的网站

很不错,虽然现在考研没有时间,但是挺感兴趣的
回复

使用道具 举报

 楼主| 发表于 2003-11-5 22:32:48 | 显示全部楼层
我而网站?不会是那个my3Dgui的项目页吧?那个其实做得也不好的,汗~~
虽然IP和客户端是一一对应的,但是仅仅根据数据包里的数据,服务器端还不能直接得到那个客户端所对应的(服务器内存中的)对象的地址,那么就没法执行数据包里的操作请求,所以我才要在网络连接和对象地址间建立一个联系的~~
回复

使用道具 举报

发表于 2003-11-6 02:08:35 | 显示全部楼层
你能不能把你设计的数据包的结构写出来看看
回复

使用道具 举报

 楼主| 发表于 2003-11-6 13:01:59 | 显示全部楼层
比如:
数据包结构(不包含数据包本身需要的一些信息):
[code:1]
int  |  int
id   |  Message
[/code:1]
服务器收到后,要根据id找到一个目标对象并处理操作请求,具体过程:
线程A:
根据收到数据包的连接来确定数据包发送者控制的人物对象,得到一个人物对象的地址P1;
根据这个人物对象的地址P1,找到它所在的八叉树节点,以此节点为起点,根据id搜索目标对象,得到一个地址P2;
把Message和发送者对象的地址P1一起发送到目标对象的一个队列中;
线程B:
读取目标对象的队列,得到一个Message和一个人物对象地址P1,然后调用Rule对象的一个成员函数,以这两个数据及目标对象自身的地址P2为参数,然后可以得到:一个函数地址,这个函数使用的一些参数;
使用这个函数地址和参数执行函数;
继续处理队列中的其他Message;
Rule对象:
上文的那个“成员函数”:
根据Message,通过一个hash表找到一个函数地址,调用这个函数,使用那个发送者人物对象地址P1和目标对象地址P2作为参数,这个函数会检测那个人物对象能否执行Message所对应的操作,并且计算操作中的具体参数,然后根据Message,再通过另一个hash表找出这个Message所对应的操作,得到另一个函数地址,然后把这个函数地址和计算得到的操作参数作为返回值交给Rule对象,然后Rule对象再把这些交给线程B进行其他操作。
当然,这两个hash表可以合并为一个表;
另外,计算操作参数的过程和查找操作函数地址的过程可以分到两个函数内执行;
还有,Rule对象可以从程序外部获取用hash表管理的那些函数,比如从动态连接库。
回复

使用道具 举报

发表于 2003-11-6 15:12:55 | 显示全部楼层
我想我明白了你所说的根据数据包没有办法确定存储人物对象的地址是什么意思了。

数据库中记录人物的各种信息,包括ID, PASSWD, 人物的最后状态等等;

用户通过Client登录服务器进入游戏,于是Client向Server发送数据包,建立连接;
Server返回用户在该服务器中的人物状态,这个时候~~单击“确定”按钮~~

服务器端的程序将会调用人物的构造函数,生成一个实例,我们可以把实例存储的
地址作为返回值,发送给Client,一旦确定,可以把这个地址也作为数据包的一部分
由Client发给Server作为以后的操作使用


不知道这样是不是行得通呢?
回复

使用道具 举报

 楼主| 发表于 2003-11-6 17:37:45 | 显示全部楼层
[quote:cad1109ef5="fishcrazy"]
服务器端的程序将会调用人物的构造函数,生成一个实例,我们可以把实例存储的
地址作为返回值,发送给Client,一旦确定,可以把这个地址也作为数据包的一部分
由Client发给Server作为以后的操作使用
[/quote]
呵呵,英雄所见略同!不过只和我以前所见相同~
我们假设一下:
客户端告诉服务器:我叫某某某,我从我的背包里拿出10000000000个金币送给某某某……
如果把人物地址发给客户端,那么其实就意味着,客户端的身份是客户端自己告诉服务器的,但是我们不能保证客户端不说谎,因为程序是开源的~
如果客户端没有使用服务器发回的地址,而是自己给出另一个地址,要么就是碰巧是另一个人物的地址,然后就可以作弊了,而大多数情况下,这个地址会引起内存访问的问题,比如访问了不属于服务器端程序的内存空间,或者这个地址并不是某个人物对象的起始地址,那么客户端一个随便写的数据包就可以让服务器端程序崩溃~~
所以,不能让客户端直接或间接地操作服务器端的内存,客户端对服务器端的一切行为都要受到监控~~
回复

使用道具 举报

发表于 2003-11-6 19:17:03 | 显示全部楼层
被你这么一说,倒真的要好好想想了,暂时还没有新的想法

这个表情是无奈吧

真希望自己有10000000000个金币,先去买台笔记本,然后就买PS2
回复

使用道具 举报

 楼主| 发表于 2003-11-6 20:24:34 | 显示全部楼层
所以,我想因为收到数据时应该可以找到相应的连接,所以把连接和人物对象联系在一起就好了~
不过,deaboway,如果用select()之类的能实现这个设计吗?
回复

使用道具 举报

发表于 2003-11-6 20:50:20 | 显示全部楼层
你说的这个select不是SQL里面的吧
回复

使用道具 举报

 楼主| 发表于 2003-11-6 23:01:38 | 显示全部楼层
不,是个函数,好像是什么I/O多路复用什么的,我搞不清楚,得问问deaboway他们搞网络的~
回复

使用道具 举报

发表于 2003-11-7 23:43:43 | 显示全部楼层
你不觉得如果总是保持连接或者每次都寻找对象是相当耗费资源的吗?

这样不合算
回复

使用道具 举报

 楼主| 发表于 2003-11-10 22:45:55 | 显示全部楼层
保持连接的资源耗费??我不知道~~
寻找对象?你指寻找目标对象?最关键的是,不能让客户端指明目标对象在服务器端的地址,那样是不安全的,那么只能用和内存地址无关的信息了,那么其本质也就是能唯一标识对象的ID了~要根据ID寻找到一个对象,那么怎么办呢?难道做一个巨大的hash表?成百上千的玩家,N多的NPC、怪物和物品,那么那个hash表也太占空间了吧?
还有什么办法或想法吗? :neutral:
回复

使用道具 举报

发表于 2003-11-10 22:49:43 | 显示全部楼层
个人认为用C语言直接操作数据库是一种可行的方法 不知道你是不是接触过这方面的知识,这样对数据库的访问速度会大大地提高
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

GMT+8, 2025-2-9 06:00 , Processed in 0.031471 second(s), 12 queries .

© 2001-2025 Discuz! Team. Powered by Discuz! X3.5.

快速回复 返回顶部 返回列表