QQ登录

只需一步,快速开始

 找回密码
 注册

QQ登录

只需一步,快速开始

楼主: sjinny

关于网络游戏的初步设想

[复制链接]
发表于 2003-9-20 10:55:45 | 显示全部楼层
我在想端口的三要素:网域,类型和规程—我们如何选择?
我倾向于使用AP_INET因特网端口,采用无连接(connedtionless)即数据报(datagram)模式,这样,规程也只有使用UDP了。
回复

使用道具 举报

发表于 2003-9-20 11:16:28 | 显示全部楼层
rocklgk, 我看了http://www.fanqiang.com/a4/b7/20010810/1200001101.html
我想还是要使用C++——用类封装,这样便于开发和维护,如果你不方便,我可以搞定类的定义,你只要写一些成员函数就可以了,和C没有什么区别的   
回复

使用道具 举报

 楼主| 发表于 2003-9-20 12:42:39 | 显示全部楼层
上传图片好麻烦啊,我要先把他传到校友录,然后才能连接过来,不爽啊!

上传文件不需要再链接了,上传后会自动显示的。
我在想端口的三要素:网域,类型和规程—我们如何选择?
我倾向于使用AP_INET因特网端口,采用无连接(connedtionless)即数据报(datagram)模式,这样,规程也只有使用UDP了。

我对这个不懂,不过我觉得需要有这样的特性:各个客户端与服务器之间的通信不能互相影响,尽量少占用端口,能够在一定程度上保证与客户端之间的连接是稳定的、可信任的。具体的你们懂行的人选择吧~   另外,最好能保证网络模块内部能够方便地调整所使用的你说的那三个东东,这样就算设计有误,也可以调整,至少不会影响到其他模块。

deaboway的意思好像是为每一个客户端创建一个线程和一个连接,那样会不会太占资源呢?是否可以这样:只用一个线程来读取网络流,只用一个线程来写入网络流;每个客户端与服务器的通信都不需要建立TCP连接,服务器端根据客户端发来的数据包来判断这是谁的操作请求并判断该怎么处理。所以我觉得没必要使用多个端口和进程啊~~

消息队列,我的设想是专门写成一个类,只提供这两个public接口:
取出一个消息
增加一个消息
而且这些操作里是有互斥的,就是在这个类里面使用一个protected的互斥变量,使用这个来保证多个线程同时操作同一个对象的队列时不会出错。编好后,从这个类public继承就行了。
其实所谓的“消息”就相当于函数调用。但是不同的是,调用一个函数得等待这个函数返回,如果这个函数有很多事做,调用它的模块就得等很长时间,这样可能会出现工作停滞甚至死锁。而消息,只是“告诉”另一个线程,要求调用哪个函数,但是却并不等待它返回。这样可以有很多好处,比如当网络模块收到一个消息时,不需要等待仿真模块处理它就可以去检测下一个网络数据是否到达了。

然后还有一个问题:线程怎么管理?
我曾经尝试过,想让一个对象在初始化时自动创建一个线程,然后用这个线程来调用自己的一个成员函数,但是最终失败了。发现只能写一个单独的函数,在这个函数里可以调用对象的成员函数,然后让线程调用这个单独的函数。这样“曲线救国”虽然也能奏效,但是却破坏了模块化的特性。但是我们这个游戏里,各大模块都各有至少一个线程。所以,我觉得可能应该专门写一个模块,由这个模块来创建并管理所有的线程,其实也就是同一管理所有的功能模块。这个线程模块有这些任务:创建线程并把这个线程资源分配给相应的模块;如果某个线程挂了,得重新创建一个来代替它;程序退出时它要回收所有线程资源。(暂时只想到这些)

大家继续讨论~~
回复

使用道具 举报

发表于 2003-9-21 10:45:39 | 显示全部楼层
deaboway的意思好像是为每一个客户端创建一个线程和一个连接,那样会不会太占资源呢?是否可以这样:只用一个线程来读取网络流,只用一个线程来写入网络流;每个客户端与服务器的通信都不需要建立TCP连接,服务器端根据客户端发来的数据包来判断这是谁的操作请求并判断该怎么处理。所以我觉得没必要使用多个端口和进程啊~~

大多数的网络游戏的服务器都会选择非阻塞select这种结构,因为网络游戏的服务器需要处理的连接非常之多,并且大部分会选择在Linux/Unix下运行,那么为每个用户开一个线程实际上是很不划算的,一方面因为在Linux/Unix下的线程是用进程这么一个概念模拟出来的,比较消耗系统资源,另外除了I/O之外,每个线程基本上没有什么多余的需要并行的任务,而且网络游戏是互交性非常强的,所以线程间的同步会成为很麻烦的问题。由此一来,对于这种含有大量网络连接的单线程服务器,用阻塞显然是不现实的。对于网络连接,需要用一个结构来储存,其中需要包含一个向客户端写消息的缓冲,还需要一个从客户端读消息的缓冲,具体的大小根据具体的消息结构来定了。另外对于同步,需要一些时间校对的值,还需要一些各种不同的值来记录当前状态。
服务器端根据客户端发来的数据包来判断这是谁的操作请求并判断该怎么处理

应该可以实现的,一般来说,一个消息由消息头和消息体两部分组成,其中消息头的长度是不变的,而消息体的长度是可变的,在消息体中需要保存消息体的长度。由于要给每条消息一个很明显的区分,所以需要定义一个消息头特有的标志,然后需要消息的类型以及消息ID。
回复

使用道具 举报

发表于 2003-9-21 10:51:17 | 显示全部楼层
还有广播的问题:
考虑使用super的方法——就是把地图分块,分成大小合适的小块,然后每次只象周围几个小块的玩家进行广播。
回复

使用道具 举报

发表于 2003-9-21 10:54:26 | 显示全部楼层
我觉得可能应该专门写一个模块,由这个模块来创建并管理所有的线程,其实也就是同一管理所有的功能模块。这个线程模块有这些任务:创建线程并把这个线程资源分配给相应的模块;如果某个线程挂了,得重新创建一个来代替它;程序退出时它要回收所有线程资源。

sjinny, 有关线程及线程同步的问题我还没有想过,看看大家还有什么好的建议吧
回复

使用道具 举报

 楼主| 发表于 2003-9-21 12:12:09 | 显示全部楼层
[quote:49bfaf9c43="deaboway"]还有广播的问题:
考虑使用super的方法——就是把地图分块,分成大小合适的小块,然后每次只象周围几个小块的玩家进行广播。[/quote]
所以,在服务器端也要使用八叉树作为仿真模块的数据基础。

又一次发现,我对网络真是知之甚少~
回复

使用道具 举报

发表于 2003-9-21 19:11:39 | 显示全部楼层
[quote:8be301c5a6="sjinny"][quote:8be301c5a6="deaboway"]sjinny,你的my3Dgui_Demos-linux解压缩/config/make后好像有两个错误,我不知道是什么问题,可以给我讲一讲吗? [/quote]

你是指解包后make发生错误吗?那把错误提示帖出来给我看看。
my3Dgui是用Kdevelop开发的,Makefile是Kdevelop自动生成的。
我记得我是先编译后再打包的,你解包后在/my3dgui下找找,应该有个文件叫“my3dgui”的,就是编译后的可执行文件。你用终端切换到这个目录下(要在X里,还要有Mesa或安装了显卡驱动),再运行看看。

Kdevelop并不难用的,至少可以不写Makefile   [/quote]
我又下载了1.7的my3dgui,可惜还是不能用,如果编译安装还是原来的错误,而我已经安装了glut,在my3dgui下找到了可执行文件但是却不能执行,错误如下:
[root@www my3dgui]# ./my3dgui
./my3dgui: relocation error: /usr/lib/libglut.so.3: undefined symbol: XmuLookupStandardColormap
怀疑是显卡驱动没有安装,是不是啊?
回复

使用道具 举报

 楼主| 发表于 2003-9-21 22:50:29 | 显示全部楼层
晕,提示是说在/usr/lib/目录下找不到libglut.so.3这个文件
你用的是什么系统?我是用的RH8完全安装
你试试自己在/usr/lib下做个符号链接试试?
另外,你有没有安装显卡驱动呢?
回复

使用道具 举报

发表于 2003-9-22 16:17:42 | 显示全部楼层
[quote:28339d3445="deaboway"]
我倾向于使用AP_INET因特网端口,采用无连接(connedtionless)即数据报(datagram)模式,这样,规程也只有使用UDP了。[/quote]
呵呵,俺来了,最近美国人要来,所以就。。。。。不好意思    大家不要想我啊    deaboway,你的想法是好的,不过我建议用TCP因为这样可以保证数据传输的准确性,而这又是网游的必要性。你考虑阻塞的问题很正确,但这个概念你可能不太清楚,是否是阻塞传输是说在传输过程中是否要等待一个send或recv函数执行完,而并不是说TCP就是阻塞传输,而UDP就是非阻塞传输,TCP也完全可以无阻塞传输,只一个select()就搞定了,它可以用来监听socket描述符以判断读和写哪个可用哪个不可用,也就是说是否有新的连接请求和是否有新的消息发出(相对于connect和accept来说),这样程序就是在有通信的情况下才做出反应,而上层处理机制完全不受影响,可以做自己的工作,也就是象sjinny说的不会产生停滞和死锁的情况,其实TCP和UDP在传输伊始的处理是一样的,只是UDP在传输后并不检查传输的数据是否正确,而网游我认为数据的传输质量一定要有保证,最起码也应该为纠错模块提供一个不太错误的数据吧。而且这是TCP和UDP自身的差异,并不存在于程序设计之中。
为每一个客户端创建一个线程和一个连接,那样会不会太占资源呢?是否可以这样:只用一个线程来读取网络流,只用一个线程来写入网络流;每个客户端与服务器的通信都不需要建立TCP连接,服务器端根据客户端发来的数据包来判断这是谁的操作请求并判断该怎么处理。所以我觉得没必要使用多个端口和进程啊~~

deaboway说的是一种网络编程的处理机制,它就好比是一个人需要在不同的要求下做不同的工作一样,当网络模块(比如说服务器端)接受到一个消息后,它会自动为这个消息分配一个进程,然后它继续监视是否有请求进来和是否有消息送出,而对于刚才的消息就转有后台处理,然后根据需要在传送给仿真模块,而整个过程实际上就是在一个端口或两个端口(一个用于收一个用于发)进行的,并不存在大量占用系统端口的问题。
sjinny说的对,只有设计好了,才会有好的程序,别急哦。
呵呵,先说这些,我一直在构思网络模块,成形之后贴出来大家考虑一下。
回复

使用道具 举报

发表于 2003-9-22 16:19:12 | 显示全部楼层
热烈的讨论我喜欢,让大家的讨论更热烈些吧!!!     
回复

使用道具 举报

发表于 2003-9-22 21:35:33 | 显示全部楼层
呵呵,还是rocklgk兄理解透彻,我自叹不如,发誓要多看书多实践,最重要的多向大家学习和请教,争取快点赶上来。
这几天我在复习C++以及面向对象编程,又重温了以前的书----温故知新----哈哈,感觉很不错,还好大四无聊的课多多,有的是时间   
回复

使用道具 举报

 楼主| 发表于 2003-9-22 22:58:17 | 显示全部楼层
当网络模块(比如说服务器端)接受到一个消息后,它会自动为这个消息分配一个进程,

rocklgk,
这样会不会导致开太多的进程呢??
另外,如果使用TCP,那么还是要为每个客户端分配一个连接,一个服务器一半只要要能支持到600人以上,如果每个人开一个连接,可能太占资源;如果用线程池,可能又会把不少资源浪费在管理和维护连接上了。所以我才想如果用UDP那么就没有一个持续的连接,应该就没有这样的问题了吧?
回复

使用道具 举报

发表于 2003-9-23 09:11:07 | 显示全部楼层
我的理解是当一次通信结束后,TCP就会断开连接的,直到其重新请求连接才再次建立连接的,线程池我现在就去看看,     
呵呵,deaboway兄,大四的时光要好好珍惜啊,过来了才觉得错过了 :-(  :-(
回复

使用道具 举报

发表于 2003-9-23 09:39:16 | 显示全部楼层
当网络模块(比如说服务器端)接受到一个消息后,它会自动为这个消息分配一个进程,

不好意思,不应该是进程,应该是线程      刚看了连接池的技术,个人认为不错,值的借鉴,具体实现我去找些源码来研究一下。
回复

使用道具 举报

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

本版积分规则

GMT+8, 2024-11-9 02:57 , Processed in 0.057157 second(s), 13 queries .

© 2021 Powered by Discuz! X3.5.

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