首页 技术 正文
技术 2022年11月14日
0 收藏 310 点赞 5,055 浏览 7714 个字

WEB与游戏开发的一些区别

前言

​最近由于在准备期末考,以及准备实习。其实都没好好写过博客,但今天由于个人身边的一些事,所以对做web和做游戏开发的区别做个记录,以下都是从网上搜索到的资料文章,感觉可以解决一些疑惑,有的文章无法贴原作者的链接,因为实在找不到原作者,如有侵权,联系删!!!


  • 需要事先了解的点(复习点)

    • HTTP协议的特点

      简单快速

      ​客户向服务器请求服务时,只需传送请求方法和路径请求方法常用的有GET,HEAD,POST每种方法规定了客户与服务器联系的类型不同由于HTTP协议简单,使得HTTP服务器的程序规模小,因而通信速度很快。

      灵活

      ​HTTP允许传输任意类型的数据对象正在传输的类型由内容类型加以标记。

      无连接

      ​无连接的含义是限制每次连接只处理一个请求服务器处理完客户的请求,并收到客户的应答后,即断开连接采用这种方式可以节省传输时间。

      无状态

      ​HTTP协议是无状态协议无状态是指协议对于事务处理没有记忆能力缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大。另一方面,在服务器不需要先前信息时它的应答就较快支持B / S及C / S模式

      以下是 HTTP 请求/响应的步骤

      1、客户端连接到Web服务器

      一个HTTP客户端,通常是浏览器,与Web服务器的HTTP端口(默认为80)建立一个TCP套接字连接。例如,http://www.oakcms.cn。

      2、发送HTTP请求

      通过TCP套接字,客户端向Web服务器发送一个文本的请求报文,一个请求报文由请求行、请求头部、空行和请求数据4部分组成。

      3、服务器接受请求并返回HTTP响应

      Web服务器解析请求,定位请求资源。服务器将资源复本写到TCP套接字,由客户端读取。一个响应由状态行、响应头部、空行和响应数据4部分组成。

      **4、释放连接TCP连接**

      若connection 模式为close,则服务器主动关闭TCP连接,客户端被动关闭连接,释放TCP连接;若connection 模式为keepalive,则该连接会保持一段时间,在该时间内可以继续接收请求;

      5、客户端浏览器解析HTML内容

      客户端浏览器首先解析状态行,查看表明请求是否成功的状态代码。然后解析每一个响应头,响应头告知以下为若干字节的HTML文档和文档的字符集。客户端浏览器读取响应数据HTML,根据HTML的语法对其进行格式化,并在浏览器窗口中显示。

      原文:https://www.cnblogs.com/ranyonsue/p/5984001.html

    • Socket通信服务器

      ​Socket服务器主要用于提供高效、稳定的数据处理、消息转发等服务,它直接决定了前台应用程序的性能。

      ​我们先从整体上认识一下Socket服务器,Socket服务器从架构上一般分为:网络层、业务逻辑层、会话层、数据访问层

      (一) 网络层

      网络层主要用于侦听socket连接、创建socket、接受消息、发送消息、关闭连接。作为socket通信服务器,网络层的性能相当重要,所以我们在设计网络层时,要着重在以下几方面获得突破:最大连接数、最大并发数、秒处理消息数。如何突破呢?下面我为大家介绍几种网络层常用到的一些技术和技巧(具体实现,我将在博文中逐一具体阐述):

      1)Buffer管理

      ​ 每一个SocketAsyncEventArgs对象(以下简称SAEA)在内存中都有其对应的缓存空间,如果不对这些缓存空间进行同一管理,当SAEA对象逐渐增多时,这些SAEA对象的缓存空间会越来越大,它们在系统内存中不是连续的,造成很多内存碎片,而且这些缓存不能重复利用,当创建、销毁SAEA对象时,造成CPU很多额外消耗,影响服务器性能。面对这问题如何解决呢?用Buffer池管理!

      2)双工通信

      ​ Socket服务器提高通信效率是一个永恒的话题,提高通信效率有很多种方法,双工通信就是其中之一。一个SAEA对象在同一时刻只能用来接收数据或发送数据,有人想,如果一个SAEA对象在同一时刻既能发送数据又能接受数据,那肯定会提高socket通信效率。恩,很有想法!可是你能让你的头在同一时刻既往左转又往右转吗?答案是不行的,那如何实现双工通信呢?既然一个SAEA对象在同一时刻只能做一件事,那我自定义DuplexSAEA对象,在该对象中封装两个SAEA,一个用于接受,一个用于发送,问题不就解决了吗。

      3)poolOfAcceptEventArgs

      ​ poolOfAcceptEventArgs是个什么东西?它不是个东西,是一个容器,一个容纳AcceptSAEA对象的容器。给你两个socket服务器,你能很快判别两个服务器性能的优异吗?很简单,你瞬间向一台服务器打入5、6万的连接,看看会不会都连上,如果都连上,说明这台socket服务器的并发处理连接的能力还是不错的。那如何提高socket服务器的并发连接能力呢?答案:poolOfAcceptEventArgs!

      4)消息队列调度器

      ​ 消息队列调度器主要分为两种:接受消息队列、发送消息队列。为什么要用消息队列呢?主要是提高socket服务器的吞吐量。首先我们定义一个队列Queue,然后编写N个调度器,不断从队列中调度消息,接受队列调度器用于将消息抛至业务逻辑层处理,发送队列调度器用于调用网络层发送消息接口,向指定端口发送数据。

      5)心跳扫描

      ​ 有一个困惑:客户端连接socket服务器,连接没有断开,但客户端挂了,这样这条连接在socket服务器中就成了钉子户,落地生根不走了!一个钉子户还可以忍受,千千万万个呢?那就崩溃了!怎样解决这个问题呢?定时扫描每条连接,如果该条连接在超时时间内没有IO响应,则关闭它。

      6)粘包

      ​ 服务器在接受消息包时,如果两个数据包同时被你服务器收了怎么办?你会把他当成一个数据包吗?如果一个数据包断了,分成两次被你服务器收了,你会把他们拼接起来吗?这些就是粘包了,怎么解决?正则表达式扫描!

      7)多线程编程

      ​ Socket服务器的编程就是多线程编程,面对多线程,线程间怎样同步、怎样避免死锁?多线程访问公共资源如何处理,在下面的博文中,我将会为大家具体阐述。

      (二) 业务逻辑层

        网络层将解包后的消息包抛至业务逻辑层,业务逻辑层收到消息包后,解析消息类型,然后转入相应的处理流程处理。

        网络层应提供发送消息的接口供业务逻辑层调用,因为网络层不会主动发送消息,发送消息的操作是由业务逻辑层来控制的,所以业务逻辑层应根据具体的业务应用,封装不同功能的发送消息的方法。

      (三) 会话层

        会话层主要用于记录在线用户信息,该层隶属于业务逻辑层。既然隶属于业务逻辑层,那为什么还要独立出来呢?这主要为以后分布式开发拓展用,试想,一台服务器最大能支持多少人同时在线?中国有多少人?如果1亿人同时在线,你一台服务器能支持得了吗?答案肯定是否定的,所以要分布式开发。分布式开发涉及到用户信息同步的问题,所以会话层就要独立出来了。

      (四) 数据访问层

        数据库执行效率是整个socket服务器的瓶颈?为什么呢?举个例子:假设我们的socket服务器的秒处理消息的条数为3000,每处理一条消息都会保存历史记录,那么,如果数据访问层不想拖网络层的后腿,那么他的执行sql语句的效率也必须达到每秒3000!如果socket服务器和数据库服务器部署在同一网段上,这个速度是没有问题的,但如果数据库服务器部署在外网呢?你的sql语句的执行效率能达到那么高吗?很困难!

        再思考一个问题:如果网络层执行线程和数据库执行线程是同一个线程,那么网络层的处理必须等待数据库执行完毕后,才能进行!如果数据库执行效率比较慢,那对整个socket服务器将是一个毁灭性的打击。

        那么怎样将数据访问层与网络层分离,让他们互不影响?如何提高数据库执行效率,让网络层的处理速度和数据访问层的处理速度达到一个平衡?答案:连接池+sql调度器+主从数据库

      原文:https://www.cnblogs.com/tianzhiliang/archive/2010/10/28/1863684.html


解释一:

​原文未找到!!!

在一间游戏公司的两个部门待过, 前一个部门以做web开发为主,后一个部门做游戏开发,我在两边都是做后端的。在游戏部门待的时间不长, 不敢说已经深入了解游戏开发技术细节,我仅把我已经接触到的内容与之前擅长的web技术做对比,一来作为工作日志记录, 二来希望能给想从web转游戏的同学提供一个预先学习的方向,少走一些弯路。

​这一系列内容我会连载发布,而不是一次性讲清楚所有内容, 毕竟当前还不敢狂妄的表示已经了解游戏开发的种种细节。

通用性

​即使不同类型的软件开发也是具有一定相似性的,这种相似性随软件类型的不同而不同。 如web前端开发与web后端开发差异就挺大, 前端程序运行在浏览器中,后端程序运行在服务器上;前端程序操纵的目标是网页元素,后端程序操纵的目标是存储在服务器上的数据。前端和后端相似的地方估计也就编程语言使用的一些基础概念了,所以前后端程序员岗位转变存在一定难度,比如让一个没有任何后端经验的前端程序员立马上手写后端程序,几乎不可能。

​然而web服务器和游戏服务器的差异就没这么大了,它们用的是相同的编程语言, 比如说java;它们用的是相同的数据库软件,比如mysql和redis;它们都运行在服务器端,比如linux server和windows server,且对稳定性要求及其严格。拥有这几处相同点两种程序在宏观上是完全相似的,对应程序员工作的转换也不存在硬性的技术障碍, 如果程序员技术基础扎实,完全可以平滑过渡。

差异性

​因为业务的不同,web服务器和游戏服务器势必存在不同之处,然而这种不同并非技术上的不同,而是套路上的不同。

服务器类型的不同

​web程序使用http服务,浏览器和服务器之间是http协议通信。游戏服务器通常是一个socket服务器,与游戏客户端之间保持长连接,如果是网页H5游戏,那么使用的也是全双工的websocket协议。通常,使用http协议的web服务器不用程序员费事去管理网络连接,程序员只要专注业务逻辑即可。而使用socket或者web socket等协议进行长连接通信却需要程序员手动编程管理,比如说断线重连游戏状态恢复机制,就需要手动处理网络连接。这表示socket编程难度大于http编程,从而导致游戏服务器编程大于web服务器编程。可这并不能表示游戏服务器编程不同于web编程, 如果一个web程序员不了解socket编程原理,那也不能算一个优秀的web程序员,毕竟http是以socket为基础的。

传输数据格式的不同

​在web前后端传输数据除了使用http标准的键值对格式以外使用最多的是json,json被使用的一个最重要的原因是与JS无缝兼容,高效方便。然而,这种优势在游戏客户端中不存在,人家游戏客户端又不使用JavaScript编程,所以游戏客户端和服务器之间有更合适的数据传输时格式存在。我接触到的是谷人希家的protocol buffer协议, 它相对于json的优点是体积小。经我测试,同样的数据内容,使用protocol buffer格式存储大小只有使用json存储的三分之一甚至更低,即使在某些特殊情况下也不会超过json的一半。

严格验证数据格式,有xml xsd的功效。而json数据格式验证相对宽松,只要符合json语法就行,因此容易出错。反之,protocol buffer则更加稳定。至于缺点最严重的是使用麻烦, 需要借助谷人希的第三方工具才行。protocol buffer的使用细节,这里不作讲解。

分布式处理业务

​我接触到的游戏服务器是微服务的一种形态, 整个游戏服务器的逻辑被分割成很多服务模块,分别运行在不同的服务器上。然而,我无法理解的是每个模块之间的通信居然使用socket,而不是更流行的http。游戏客户端与服务器之间使用socket连接可以理解, 然而,服务器各模块之间也使用socket却有些使我莫名其妙,虽然这会使服务器之间通信性能有所提升,却会带来编写代码任务过于复杂,稳定性下降等问题,为了些许性能提升而丧失项目的维护性,有点得不偿失。 不过也有可能我还没有理解其中奥秘,判断过于片面。

极端的性能敏感

​游戏中实时对战模块必须使用c/c++实现,原因是JVM执行垃圾收集时会造成虚拟机停顿,也就是stop the world。在虚拟机技术发展日新月异的今天, gc停顿依旧会对游戏体验造成影响,因而必须使用老掉牙的c++, 这使我感到震惊。另外, 游戏中大多数数据被放在redis中而非mysql也使我意外,数据持久化存储显然不是redis的优势,拿性能换稳定和安全,这种做法略显激进。

以上内容是我当前对于web开发与游戏服务器开发不同之处的见解,如有谬误请指出。 此外,在之后的学习和实践中的心得体会,会在之后的文章中继续发布。


解释二:

游戏服务器和Web服务器的区别

有些对游戏服务器的介绍可能会说,游戏服务器是一个需要长期运行的程序,然后怎么怎么样。我个人认为Web服务器一样的需要长期运行,也需要响应不定点不定时来自用户的请求。两者从宏观上来看其实没有本质的区别。同时Web服务器也会对于稳定性和性能有要求,游戏服一般分为大小服,我们这里都按照小服举例子。

3.1 状态

首先要提到的就是状态。可能你会听说过一个概念,游戏服务器是有状态的,而Web服务器是无状态的。什么意思呢?Web服务器的数据流大多直接会到数据库中。而游戏服务器的数据流首先会到内存中,然后定期的写入数据库(落地)。

换句话说,游戏服务器本身的数据与数据库中的数据在运行期间会存在一个数据不一致的窗口。如果此时游戏服务器宕机了,那么就会造成数据首先到的内存数据与数据库存的数据不一致。

而Web服务器则不会有这样的问题,Web所有的数据状态都会落地,而且可以针对操作加上事务,不用担心因为操作失败而引入脏数据。正因为有了状态的约束,游戏服务器就会很慎重的使用内存、CPU。以求在资源有限的情况下,最大化的提高的承载量,并且降低服务延迟。当然,Web服务器会为了降低某个接口的响应时间而去做对应的优化。

3.2 扩容

在Web服务器中,如果你不能评估一个服务所面临的压力,又不想因为瞬时的热点访问导致服务直接不可用的话,完全可以设置成自动扩容,因为每个服务只是单纯的接收请求,然后处理请求、返回结果,不会将数据保存在服务器的内存中。要有数据存到内存,那也是在Redis中。而Redis数据丢失对数据的一致性基本没有影响。

但是在游戏服务器这边很难做到像Web那样灵活。首先,数据的流向不是数据库,而是内存。

举个很简单的例子,玩家的主城被攻打着火了,如果有了自动扩容,很有可能在落地的窗口内,玩家再请求一次,请求到了另一个实例。主城又没有着火了。因为数据都会先存在内存中。

再举一个例子,玩家氪金买了一个礼包。然后退出游戏,落地窗口内再次上线没了。这就不是单纯的数据问题了,玩家这是花了真金白银买的道具,突然就没了,一两个还好处理,如果多个玩家都出现这样的问题,那这就属于严重的线上事故了。修复数据的工作量十分的大。

所以,对于一个游戏服务器,所能使用的内存和CPU的资源是非常有限的,不像Web服务器可以不用花很大的代价做到横向扩展。这也就是为什么游戏服务器会十分十分的注重代码的性能以及稳定性。

3.3 稳定

就像上面说的例子,如果游戏服务器运行中出了BUG,导致服务直接不可用,或者说通过这个BUG刷到了大量的道具,将是一个非常严重的线上事故。

而对于Web服务器来说,如果是管理系统之类的,有可能会有脏数据值得一提的是,脏数据对于Web来说,排查起来也是一件很头疼的事情。如果没有脏数据,只是服务暂且不可用,而且如果用的是微服务架构,重启服务的代价是相对来说比较小的,只有正在重启的服务的业务是不可用的,其余的部分则可以正常的访问。

而对于游戏服务器来说,服务器重启影响的是全服的玩家。玩家在停服期间,甚至连游戏都进不了,特别的影响玩家体验。而且,如果停服之前服务器的数据落地出现了问题,服务重启之后会将数据从数据库load到内存中,此时同样会造成数据不一致的问题。

3.4 性能

从我的经验来看,在做Web服务器的时候,没有为了减少GC的压力,为了少占用内存去做过多的优化。当然这是因为项目本身的体量不大,如果QPS很高的话,Web服务器同样很需要注重性能,只不过游戏服务器需要一直特别注意这个方面。

不过在Web,如果访问量很大的话导致单个服务不能扛住压力,大部分人首先想到的解决方案应该就是搞多个实例,毕竟可以做到很轻松的横向扩展。

在游戏服务器里,会把服务器的资源看的相当的宝贵。例如,能不落地的字段就绝对不要落地,某个字段的值可以通过已知的条件算出来的,就尽量不要定义在代码里。不过这也要看具体情况权衡运算量和调用的频率。因为上线之后,如果遇到了数据不一致,维护的数据越少,修复数据的难度就越小。

3.5 严谨

这一点上来说,我认为是两者都很关注的一个重点。只不过,在游戏服务器的某些情况中,如果服务器抛出异常或者panic。其造成的后果会被游戏特殊的环境放大。

例如,召回你的在外部队失败了,那么部队就会一直在外面且不可用。这跟在浏览器中点一个按钮没有反应比起来,影响相对较小。而且使用微服务架构,在修复问题之后可以以很低的成本来重启对应的服务,而游戏服务器中还要修复一次数据。

再举一个很极端的例子,点击商店,玩家要准备氪金了。但是却发现进不了商店,也可能不能获取商品列表。这些会直接影响到游戏的体验,甚至收入。

而对于Web来说,服务器的稳定性同样很重要。不然根据业务的不同,造成后果的严重性也有可能不同。影响了用户体验,就会直接影响到产品的口碑。

3.6 数据传输格式

熟悉Web的都知道,数据传输格式是JSON。而在游戏服务器中是Protobuf,是由Google开发的数据传输格式,与JSON类似。Protobuf是二进制的,二进制数据量会比JSON更小一点。而且,如果传输的字段是空值,就不会被传输。而JSON如果是空值,一样的也会被传输。

无论是在什么样的环境中,举个例子,Node.js和Java中,Protobuf的性能表现都比JSON好。在Java中,Protobuf甚至要比JSON快了接近80%。如果Java的服务之间通信有了性能瓶颈, 可以考虑服务之间使用RPC来通信。

但是凡事都具有两面性。Protobuf的缺点仍然存在:

  • 文档较少
  • 社区与JSON的对比起来
  • 可读性没有JSON好

原文:https://zhuanlan.zhihu.com/p/86748689


问题

​对这块仅仅做了个简单的了解,也并不知道大佬们眼中的区别是怎样的,以及那种多人联网棋牌类游戏用Java可以开发吗?如果可以,可以用什么方式呢?个人没有一个准确的认识,希望有大佬可以给我指正以及讲述一下这里面的一些原理。

相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:8,957
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,480
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,327
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,110
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:7,742
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:4,776