关于端游游戏服务器后端语言的语言选择什么比较合适

中国领先的IT技术网站
51CTO旗下网站
游戏服务器:到底使用UDP还是TCP
一般来说你会听到人们这样说:“除非你正在写一个动作类游戏,否则你就用TCP吧” 或者是 “你能够在MMO游戏中用TCP,因为魔兽世界就用的TCP!”
作者:菜鸟浮出水 编译来源:伯乐在线| 09:51
在编写网络游戏的时候,到底使用UDP还是TCP的问题迟早都要面对。
一般来说你会听到人们这样说:&除非你正在写一个动作类游戏,否则你就用TCP吧& 或者是 &你能够在MMO游戏中用TCP,因为魔兽世界就用的TCP!&
遗憾的是,这些观点都没有反映这个问题的复杂性。
首先,说明一下,我之前主要是用TCP进行网络编程。我曾为一个流行的在线纸牌游戏编写服务器了好几年,在高峰期我们的每台服务器能够承受个连接(同一台物理机器上有多个服务器进程在跑)都没有问题。在我来看,TCP是一种安全而且常见的选择。
尽管如此,我们最新的项目却是使用UDP协议,而且我们的项目无法通过任何方式在TCP下工作。事实上,项目一开始使用的TCP,但是后来发现我们使用TCP无法达到我们需求的连接数量时,我们只能换成UDP了。
在使用中TCP表现怎么样呢
从原理上,TCP的优势有:
简单直接的长连接
可靠的信息传输
数据包的大小没有限制
任何一个和TCP打过交道的人都知道,要实现一个稳定的TCP网络连接,需要处理各种隐藏的坑,比如断线检测、慢速客户端响应阻塞数据包,对开放连接的各种dos攻击,阻塞和非阻塞IO模型等等。
除了上面列出的这些问题外,一个好的TCP模块确实不好编码实现。
但是,TCP最糟糕的特性是它对阻塞的控制。一般来说,TCP假定丢包是由于网络带宽不够造成的,所以发生这种情况的时候,TCP就会减少发包速度。
在3G或WiFi下,一个数据包丢失了,你希望的是立马重发这个数据包,然而TCP的阻塞机制却完全是采用相反的方式来处理!
而且没有任何办法能够绕过这个机制,因为这是TCP协议构建的基础。这就是为什么在3G或者WiFi环境下,ping值能够上升到1000多毫秒的原因。
为什么不用UDP
UDP相对TCP来说既简单又困难。
举个例子来说,UDP是基于数据包构建,这意味着在某些方面需要你完全颠覆在TCP下的观念。UDP只使用一个socket进行通信,不像TCP需要为每一个客户端建立一个socket连接。这些都是UDP非常不错的地方。
但是,大多数情况下你需要的仅仅是一些连接的概念罢了,一些基本的包序功能,以及所谓的连接可靠性。可惜的是,这些功能UDP都没有办法简单的提供给你,而你使用TCP却都可以免费得到。
这也是人们为什么经常推荐TCP的原因。在用TCP的时候你可以不考虑这些问题,直到你需要同步连接的数量级达到500以上的时候。
所以,是的,UDP没有提供所有的解决方法,但是就像你看到的那样,这也正是UDP好用的地方。在某种意义上来说,TCP对UDP就好比是Hibernate和手写SQL的区别。
使用TCP失败的地方
人们经常给你建议,让你去使用TCP,比如&TCP跟UDP一样快&或者&游戏X用TCP如此成功,所以TCP当然是首选&,然而,他们完全没有理解为什么在那个特定的游戏中TCP是有效的,为什么UDP不按照顺序发送数据包呢?
那么为什么魔兽世界采用TCP呢?首先我们需要解释这个问题。这个问题其实是&为什么魔兽世界有的时候1000毫秒以上的延迟还能够运行?&这是TCP的性质决定的,在发生丢包的时候,会产生巨大的延迟,因为TCP首先会去检测哪些包发生了丢失,然后重发所有丢失的包,直到他们都被接收到。
可靠的UDP也是有延迟的,但是由于它是在UDP的基础之上建立的通信协议,所以可以通过多种方式来减少延迟,不像TCP,所有的东西都要依赖于TCP协议本身而无法被更改。
就这一点来讲,一些人要开始提到Nagle算法了,实际上它是你在实现任意一个对延迟敏感的TCP模型时首先需要禁止使用的。
那么魔兽世界以及其他的一些游戏是怎么处理延迟问题的呢?
方法也很简单,他们能够隐藏掉延迟带来的影响。
在魔兽世界中,玩家和玩家是无法碰撞的:因为这类碰撞是无法通过一些预测来处理的,但是玩家和环境之间的碰撞却是可以通过预测来处理的,所以这里使用TCP是没有问题的。
我们来看一下魔兽世界的战斗就会发现,玩家的攻击指令发送给服务器的操作是放在比如&attack_entity(entity_id)&或者&cast_spell(entity_id, spell_id)&的接口中来做的,换句话说,瞄准操作是独立于进行的。如此一来,一些类似发起攻击动作和释放技能特效就能够在没有收到服务器确认的情况下就直接执行,比如展现冰冻技能的效果就可以在服务器没有返回数据前在客户端就做出来。
客户端直接开始进行计算而不等待服务端确认是一种典型的隐藏延迟的技术。
几年前,我为一个叫&Five Card Jazz&的纸牌游戏编写过客户端。它使用的是http协议,它比直接的TCP协议连接的延迟更加严重。
我们用简单的纸牌绘制和抽牌的动画来掩盖延迟的问题,所以延迟的问题只在非常糟糕的连接下才会被看出来。这种方法也非常的典型:发送请求的同时开始播放牌桌的动画,一直播放翻动最后一张牌直到接收到了服务端传回来的数据为止。魔兽世界的战斗特效就是使用类似的原理。
这也意味着,我们到底是使用TCP还是UDP取决于我们能否隐藏延迟。
TCP在什么时候失效
一个采用TCP的游戏必须能够处理好突发的延迟问题(纸牌客户端就很典型,对突发性的一秒的延迟,玩家也不会产生什么抱怨)或者是拥有缓解延迟问题的好方法。
但是如果你运行的是一个无法使用任何减缓延迟措施的游戏呢?玩家对玩家的动作类游戏通常就属于这个范畴,但是这也不仅仅限于动作类游戏。
举个例子:
我目前正在写一个多人游戏(War Arcana)。
一种常见的操作是,你快速的移动你的角色通过一张充满战争迷雾的世界地图,但是一旦你探索过,迷雾就会被打开。
为了确保游戏的规则,防止玩家作弊,服务器只能显示玩家当前位置附近的信息。这意味着不像魔兽世界,玩家无法在没有得到服务器响应的情况下,做出完整的动作。和Five Card Jazz相比,我们即使允许500毫秒的延迟,也已经非常困难了。
在实现了游戏的原型后,在局域网内一切都进行的非常顺利,但当我们在WiFi环境下测试时,操作会间歇性的卡起来或者延迟高起来。写了一些测试程序之后发现,WiFi环境下偶尔会发生丢包行为,每当发生丢包的时候,服务器的响应速度就从100-150毫秒上升到毫秒。
没有任何办法可以绕过TCP的这个设置来避开这个问题。
我们替换了TCP的代码,用了自定义的可靠的UDP来实现,把大量的丢包产生的延迟降到了仅仅只有50毫秒,甚至比以前TCP不丢包的情况一个来回的延迟还要小。当然,这只可能建立在UDP之上,这样我们才对可靠性拥有完全的掌控力。
困惑:可靠的UDP只是TCP的一种简单的实现?
你有没有听过这种说法:&可靠的UDP就像TCP一样,所以还是用TCP吧&。
问题是这种说法是错误的。可靠的UDP一点也不像TCP,要去实现一个特殊的阻塞控制。事实上,这也是你使用可靠UDP代替TCP的最大的原因,避免TCP的阻塞控制。
另一个重点是可靠的UDP的可靠性是如何保证的。这里有很多种方法去实现。我非常喜欢Quake3网络库代码里的一些想法,它们也激发了我在War Arcana中使用UDP协议。
你也可以使用许多支持可靠通信的UDP库,当然,这样在可靠性方面,相比自己手动实现全部的代码而言,可能会更加通用而失去了一些性能优势。
那么到底是用UDP还是TCP呢?
如果是由客户端间歇性的发起无状态的查询,并且偶尔发生延迟是可以容忍,那么使用HTTP/HTTPS吧。
如果客户端和服务器都可以独立发包,但是偶尔发生延迟可以容忍(比如:在线的纸牌游戏,许多MMO类的游戏),那么使用TCP长连接吧。
如果客户端和服务器都可以独立发包,而且无法忍受延迟(比如:大多数的多人动作类游戏,一些MMO类游戏),那么使用UDP吧。
这些也应该考虑在内:你的MMO客户端也许首先使用HTTP去获取上一次的更新内容,然后使用UDP跟游戏服务器进行连接。
永远不要害怕去使用最佳的工具来解决问题。
原文链接:&&&&翻译:&-&
译文链接:&
【编辑推荐】
【责任编辑: TEL:(010)】
大家都在看猜你喜欢
外电热点热点热点外电
24H热文一周话题本月最赞
讲师:1人学习过
讲师:33人学习过
讲师:0人学习过
精选博文论坛热帖下载排行
主要内容:
● 如何设计像自动售货机那样有效的用户界面。
● 深入理解窗口和对话框的管理机制。
● 为什么性能优化与我们在直觉上的理...
订阅51CTO邮刊使用 Go 语言开发大型 MMORPG 游戏服务器怎么样?
【达达的回答(53票)】:
我们公司正在用Go开发页游。上线运行有一段时间了,效果还算满意。
用Go开发大型mmorpg服务端不会有问题的,如果掉坑里肯定不会是语言的问题。
唯一比较可能掉进去的坑就只有GC,其实很容易预防和调整的,具体细节可以看我博客分享的文章。
但是技术选型不只是选语言,如果当时我手头有一套性能满意,开发效率OK,人员补给不会有问题的技术方案,不管是什么语言的,我肯定不会放弃它而选择冒险的。
我去年项目立项时选择Go是有以下一些考虑的:
1. 前一个项目用Erlang开发的,活动时间一到,密集运算CPU就受不了,这点很不满意
2. 项目过程中出现过补人难的情况,听过Erlang并愿意转Erlang的人少,招来了培训到加入开发又要一段时间
3. 因为前两点,所以新项目想找一个解决性能问题又解决人员问题的技术方案
4. 我自身没有C/C++项目经验,只会点皮毛语法,短时间要上手并拿出可用的框架不现实
5. C/C++开发人员我们这也不好招
6. 那会正好Go 1.0即将发布,我估摸着项目上线后Go还会更完善,有点赌一把的意思
7. 我给自己设想的最坏情况是Go不行的时候可以用CGO补救,当时考虑比较多的是性能,但实际上性能没问题,倒是用CGO做了GC优化,补救了自己最初设计上的不合理。
8. Go的语法元素非常之少,并且是类C的命令式语音,又有Google这个开发人员心中形象完美的亲爹,人员补充上应该比Erlang容易
对了,我最近做了个Go语言的V8引擎绑定,可以用来做游戏逻辑脚步啥的。欢迎各路勇士踊跃跳坑:
【许式伟的回答(13票)】:
我的看法是:
未来肯定会成为标配,也就是 mmorpg 最为广泛接受的方案。
1. 你信不信
2. 你应该什么时候介入
这个别人帮不了你。
【kubisoft的回答(3票)】:
如果跟C语言比,大部分脚本都胜出啊。Go, Node.js, Python ......
网易弄过一个Node.js的开源服务器框架。
至于IDE, 不重要,做服务器开发很少会要开着IDE调试的。最常用的手段就是打Log. 设置了断点也很难调,多个客户端并发。
那种单客户端连接进来就可以重现的bug倒是可以用IDE调,但是这种bug本来就容易解决。
用脚本语言,有一个很大的好处是容易做自动测试,可以更好地保证代码质量。
--------------------------
开发效率当然是脚本高。运行效率,其实更重要的是并发,框架合理的话增加机器就可以直接提高效率增加人数。
【asta谢的回答(15票)】:
因为我自己本身不是做mmorpg的,这里只是给出我认识的一些人给我的反馈信息。
1. 我认识的几个人都有用在游戏开发中,手游、页游都有,所以不能说没有成功案例
2. golang主要存在的问题是GC问题,但是如果你的应用访问量没有上千万的话,达达分享的如何有效的控制GC非常宝贵的经验,而且下一版本Go1.3基本上能够解决Go的GC问题。
3. golang的并发控制是最大的特点,能够很容易就实现高并发
4. 目前golang发布的节奏是每半年一个版本,而且基本都是性能的提升,就目前的性能而言,你的应用已经足够用了。
5. 开发工具LiteIDE写代码就非常棒,写Go代码足够足够了
6. Go方面的资料现在还是挺多的吧,而且你遇到问题去golang-nuts去问,都会很快得到答复
7. 而且对于Go在Google内部使用的情况来看,网络这一块的包是非常稳定和可靠的,用来开发游戏很合适啊
【阿猫的回答(13票)】:
看完答案后,纠正一些常见错误,曲线救国回答一下题主;
1.为什么golang的开发效率高?
golang是一编译型的强类型语言,它在开发上的高效率主要来自于后发优势,不用考虑旧有恶心的历史,又有一个较高的工程视角。良好的避免了程序员因为“ { 需不需要独占一行 ”这种革命问题打架,也解决了一部分趁编译时间找产品妹妹搭讪的阶级敌人。
它有自己的包管理机制,工具链成熟,从开发、调试到发布都很简单方便;
有反向接口、defer、coroutine等大量的syntactic sugar;
编译速度快,因为是强类型语言又有gc,只要通过编译,非业务毛病就很少了;它在语法级别上支持了goroutine,这是大家说到最多的内容,这里重点提一下。首先,coroutine并不稀罕,语言并不能超越硬件、操作系统实现神乎其神的功能。golang可以做到事情,其他语言也可以做到,譬如c++,在boost库里面自己就有的coroutine实现(当然用起来跟其他boost库一样恶心)。golang做的事情,是把这一套东西的使用过程简化了,并且提供了一套channel的通信模式,使得程序员可以忽略诸如死锁等问题。
goroutine的目的是描述并发编程模型。并发与并行不同,它并不需要多核的硬件支持,它不是一种物理运行状态,而是一种程序逻辑流程。它的主要目的不是利用多核提高运行效率,而是提供一种更容易理解、不容易出错的语言来描述问题。
实际上golang默认就是运行在单OS进程上面的,通过指定环境变量GOMAXPROCS才能转身跑在多OS进程上面。有人提到了网易的pomelo,开源本来是一件很不错的事情,但是基于自己对callback hell的偏见,我一直持有这种态度:敢用nodejs写大规模游戏服务器的人,都是真正的勇士 : ) 。
2、Erlang与Golang的coroutine有啥区别,coroutine是啥?
coroutine本质上是语言开发者自己实现的、处于user space内的线程,无论是erlang、还是golang都是这样。需要解决没有时钟中断;碰着阻塞式io,整个进程都会被操作系统主动挂起;需要自己拥有调度控制能力(放在并行环境下面还是挺麻烦的一件事)等等问题。那为啥要废老大的劲自己做一套线程放user space里面呢?
并发是服务器语言必须要解决的问题;
system space的进程还有线程调度都太慢了、占用的空间也太大了。把线程放到user space的可以避免了陷入system call进行上下文切换以及高速缓冲更新,线程本身以及切换等操作可以做得非常的轻量。这也就是golang这类语言反复提及的超高并发能力,分分钟给你开上几千个线程不费力。
不同的是,golang的并发调度在i/o等易发阻塞的时候才会发生,一般是内封在库函数内;erlang则更夸张,对每个coroutine维持一个计数器,常用语句都会导致这个计数器进行reduction,一旦到点,立即切换调度函数。
中断介入程度的不同,导致erlang看上去拥有了preemptive scheduling的能力,而golang则是cooperative shceduling的。golang一旦写出纯计算死循环,进程内所有会话必死无疑;要有大计算量少io的函数还得自己主动叫runtime.Sched()来进行调度切换。
3、golang的运行效率怎么样?
我是相当反感所谓的pingpong式benchmark,运行效率需要放到具体的工作环境下面考虑。
首先,它再快也是快不过c的,毕竟底下做了那么多工作,又有调度,又有gc什么的。那为什么在那些benchmark里面,golang、nodejs、erlang的响应效率看上去那么优秀呢,响应快,并发强?并发能力强的原因上面已经提到了,响应快是因为大量非阻塞式io操作出现的原因。这一点c也可以做到,并且能力更强,但是得多写不少优质代码。
然后,针对游戏服务器这种高实时性的运行环境,GC所造成的跳帧问题确实比较麻烦,前面的大神
有比较详细的论述和缓解方案,就不累述了 。随着golang的持续开发,相信应该会有非常大的改进。一是屏蔽内存操作是现代语言的大势所趋,它肯定是需要被实现的;二是GC算法已经相当的成熟,效率勉勉强强过得去;三是可以通过incremental的操作来均摊cpu消耗。
用这一点点效率损失换取一个更高的生产能力是不是值得呢?我觉得是值得的,硬件已经很便宜了,人生苦短,让自己的生活更轻松一点吧: )。
4、基于以上的论述,我认为采用go进行小范围的MMORPG开发是可行的。
【知乎用户的回答(2票)】:
可以,但我现在了解到的大部分webgame大多采用c c++ c# 做底层 erlang python lua js做脚本,直接用c c++ c#(scut开源) python(firefly开源) js(node)(网易开源) go(达达,仙侠道,貌似有用js做脚本)的也有,但技术选型其实是考虑人员配置和团队成长,不必纠结,而且大部分情况是没得选。
刚刚又看到 云风的c+lua框架 大家可以入门也可以直接用。
【李智勇的回答(2票)】:
很多时候回答这类问题大家喜欢用一种特征列举的方式,比如:C有什么什么特征,所以适合,Go有什么什么特征所以不适合。但其实对于实际想获得答案的人这种特征列举并没有想的那么有用,因为你没法判定那个片面那个不片面,那些是偏见,那些是纯主观。所以最简单实用的方法是去确认什么是被证明过的成熟的技术,比如有多少成功的mmorpg用的是这门语言或框架,另一个是看那个社区成熟。毕竟大多时候事业本身并不适合为新技术背书。
【高宏达的回答(2票)】:
下面是我在准备写一个新的游服时技术选型的比较,最后我选了C#;
C#的优点:
1.有强大IDE,无论编写还是调试都非常容易,可以节省大量时间。
2.有大量资料可查
3.不会有Runtime层的内存泄漏。
4.有成功先例,说明用起来没问题。
5.运行速度快。
6.我非常熟悉。
7.代码框架可以参考传统游戏服务器的实现方式。
1. 相对go,布署比较麻烦。
2. linux上得用mono,性能有下降。
3. 非开源(相对GO,其实从实用角度来说,不是什么问题)。
golang的优点:
1.原生高并发
2.布署方便
golang的缺点
1.没有强大的IDE,开发和调试都不方便(至少是没有用VS那么方便)
2.没有大量资料。
3.有runtime内存泄漏问题。
4.市面上没听说过有golang开发的游戏服务器,没先例,无人研证过可不可用,有风险。
5.运行速度并不比c#有优势。
6.我没c#那么熟悉
7.代码框架虽然也可以参考传统游戏服务器的实现方式,但这样就失去了高并发和go程的优势,所以这块势必要重新思考,增加了风险。
【DamonChen的回答(0票)】:
从趋势上看,go以后发展最多的肯定是后端的应用,gc的问题只是暂时的,c++被取代是毫无疑问的。
【蒋惟堃的回答(0票)】:
优势。开发效率高。
劣势 速度相对慢。但对于一般网游来说,应该可以忽略。
个人感觉开发效率对大部分团队来说是首要的,因为你能快速出产品比什么都强。
服务器效率go比不上c++,但是对大部分人来说肯定也够了。
go另外一个劣势就是对大多数程序员来说是一门新语言,需要学习。不像c,java拿来就写。
不过这一点可以被开发效率高弥补。
【应跨江的回答(2票)】:
大型 MMORPG 游戏服务端,估计以后都很难看到golang的“成功案例”。障碍不在于GC这些,而在于现在大型 MMORPG 只有大公司能搞得动。而大公司一般都已经有大牛,已经有积累了n年的服务端c/c++框架。
如过真的有新进入者,需要从头开发服务端框架,那用go几乎是最佳选择。
对页游/手游来说,go可以说是天地广阔,大有可为。一个用C++半年抄出一个游戏且时不时会宕机再加3个月才能搞稳定的团队 VS 一个用go三个月抄出一个游戏且从不宕机的团队,嘿嘿......
&&&&&本文固定链接:
【上一篇】
【下一篇】
您可能还会对这些文章感兴趣!
最新日志热评日志随机日志游戏服务器端_百度文库
两大类热门资源免费畅读
续费一年阅读会员,立省24元!匿名用户不能发表回复!|
每天回帖即可获得10分可用分!小技巧:
你还可以输入10000个字符
(Ctrl+Enter)
请遵守CSDN,不得违反国家法律法规。
转载文章请注明出自“CSDN(www.csdn.net)”。如是商业用途请联系原作者。匿名用户不能发表回复!|
每天回帖即可获得10分可用分!小技巧:
你还可以输入10000个字符
(Ctrl+Enter)
请遵守CSDN,不得违反国家法律法规。
转载文章请注明出自“CSDN(www.csdn.net)”。如是商业用途请联系原作者。}

我要回帖

更多关于 易语言服务器与客户端 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信