WebSockets适合实时多人游戏吗?

57

我有兴趣构建一个小型实时多人游戏,使用HTML5/JavaScript作为客户端,可能会使用Java作为服务器软件。

我稍微了解了一下WebSockets,但似乎我对WebSockets的理解存在误区。我最初认为WebSockets只是JavaScript处理TCP sockets的方式,就像Java和其他语言中使用的那样,但事实上必须进行整个握手过程,并且每次传输都包含大量HTTP开销(在这种情况下,与Ajax相比的优势似乎并不像一开始看起来那么令人兴奋)?

在相关主题上,是否有更好的替代方案可用于此目的(JavaScript中的实时多人游戏)?


4
实际上,每个传输只包含两个字节的开销。HTTP握手只在打开新的WebSocket时发生,您可以保持WebSocket打开,只要浏览器停留在该页面上即可。 - David Grayson
1
是的,它们是。HTTP握手只需一次即可打开套接字。因此,如果您在发送一条消息后关闭套接字,则开销很大,如果您永久保持套接字打开,则开销微不足道。 - Raynos
为什么握手过程如此复杂?据我回忆,必须读入一些字符串,其中最后一个是一些[随机的?]字符集,必须以某种方式进行base64编码并发送回客户端。我尝试自己编写服务器端握手代码,但它没有起作用(握手过程从未完成,因此我无法发送和检索自己的数据包)。当我使用别人编写的Java包来完成同样的事情时,我得到了完全相同的结果。 - Josh1billion
1
@Josh1billion 握手过程并不是很复杂,一个 WebSocket 服务器大约只有100行代码,我建议使用 socket.io。至于为什么?可能是出于安全考虑。 - Raynos
@Josh1billion:握手过程并不复杂(http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-17#section-1.2)。响应头相对静态(只有两个值需要填写)。它被设计为与HTTP兼容(允许WebSockets和HTTP/S连接在同一端口上进行)。它还添加了CORS安全性(即使Flash套接字也通过带外安全策略请求来实现这一点)。SHA1接受哈希防止AJAX客户端欺骗WebSocket服务器。请注意,还有一个非常不同的旧版本的WebSockets,可能会导致您看到的问题。 - kanaka
15
多年后的更新:自从发布这个问题以来,我成功地开发了多种使用WebSockets的游戏,包括实时和回合制。我发现最简单(也是许多方面最好的)技术栈是使用Node.js作为服务器,同时在服务器和客户端/浏览器中使用socket.io。建立连接很容易,socket.io处理握手和其他要求,整个开发过程非常愉快。我没有遇到任何延迟问题,但我的实时websockets游戏的流量都很低。 - Josh1billion
5个回答

51

WebSockets是在Web浏览器中运行的实时多人游戏的最佳解决方案。正如评论中指出的那样,有一个初始握手过程,其中HTTP连接被升级,但一旦建立连接,WebSockets提供了用于服务器和客户端之间的双向通信的延迟时间最低的连接机制。

我建议您观看这个视频:https://www.youtube.com/watch?v=_t28OPQlZK4&feature=youtu.be

请参考以下内容:

唯一的原始TCP解决方案将是使用支持某种TCPClient对象的插件。 我建议您尝试使用WebSockets。

您可以在此处找到许多选项。只需在页面中搜索WebSockets即可。

还要查看WebRTC。根据您的游戏目的以及是否需要服务器管理游戏状态,您可以使用此技术进行点对点通信。 在这种情况下,您仍然需要一个解决方案来处理将玩家分组-在这种情况下,WebSockets是最快/最好的解决方案。


https://chrome.com/supersyncsports/不再可用,请查看https://experiments.withgoogle.com/super-sync-sports。 - Blaztix

19

基本上在撰写本文时,您有三个选择:

WebSockets

WebSockets是一种轻型的消息传递协议,使用TCP而不是JavaScript实现TCP sockets,正如您所指出的。然而,除了初始握手之外,在此点之后没有HTTP头传递来回。一旦建立连接,数据可以自由地传递,开销极小。

长轮询

长轮询简而言之,就是客户端通过HTTP请求周期性地向服务器轮询新信息。这在CPU和带宽方面非常昂贵,因为每次都会发送一个庞大的新HTTP头。在旧版浏览器中,这基本上是您唯一的选择,而库(如Socket.io)在这些情况下使用长轮询作为后备。

WebRTC

除上述内容外,WebRTC还允许通过UDP进行通信。UDP长期以来一直在非基于Web的环境中用于多人游戏,因为它的开销低(相对于TCP),延迟低,且无阻塞特性。

TCP“保证”每个数据包都会到达(除了灾难性网络故障),并且它们总是按发送顺序到达。对于诸如注册分数、命中、聊天等关键信息非常有用。

另一方面,UDP没有这样的保证,数据包可能以任何顺序或根本不到达。当涉及到频率较高且需要尽快到达的不太重要的数据(例如玩家位置或输入)时,这实际上是有用的。原因在于,如果单个数据包在传输过程中延迟,TCP流将被阻塞,导致游戏状态更新存在大间隙。通过UDP,您可以简单地忽略到达晚的数据包(或根本不到达),并继续处理接收到的下一个数据包,从而为玩家创造更平滑的体验。

撰写本文时,WebSockets可能是您的最佳选择,但是WebRTC的采用正在迅速扩展,并且在您完成游戏时可能是更好的选择,这是需要考虑的事情。


12

我不确定在现今时代(2017年)WebSockets是否仍然是实现实时多人游戏网络连接的最佳工具。 WebRTC 是一种更新的技术,提供了更高性能的潜力。 而且这些天,由于以下库的存在,WebRTC也更易于使用:

  • node-webrtc 简化了服务器端的网络连接
  • webrtc-native 也提供了一个服务器端库,可能更快,正如它的名称所示
  • electron-webrtc 提供了一个实现,如果您想使用electron打包游戏,则匹配度很高

或者,如果您想省去网络实现的实际细节,并且正在寻找提供更高级别多人游戏接口的库,请查看 Lance.gg。(免责声明:我是其中的贡献者之一)。


2
如果我们需要一个权威服务器以防止玩家作弊,WebRTC适用吗?我们如何使用WebRTC防止作弊? - trusktr
2
而且,似乎发送二进制数据会更快。人们正在使用WebSockets对JSON进行(反)序列化。这不是很慢吗?我们如何在Web中创建一个权威的UDP网络? - trusktr

7

多人游戏需要服务器定期向客户端发送世界状态的快照。在浏览器HTML/js应用程序的上下文中,您有很少的选择:轮询、websocket或编写自己的插件来扩展浏览器功能。

HTTP轮询(例如BOSHBayeux)是复杂的,但会引入网络开销和延迟。Websocket旨在克服它们的限制,并且肯定更具响应性。

库,如cometdsocket io,提供了传输的抽象,并为您解决了浏览器兼容性问题。除此之外,它允许在底层传输之间切换并比较它们的性能而不需要额外努力。

我使用socket.io编码了多人街机游戏,使用websocket通常会有2ms的延迟,在局域网上使用xhr-polling大约为30ms。这已经足够用于多人游戏。

我建议您看一下 nodejs 和 socket.io,以便能够在客户端和服务器之间共享代码,您还可以在 [3] 借鉴一些多人游戏的代码。


1
如果你计划在游戏中使用JavaScript(就像你现在这样),那么WebSocket是最好的选择。如果你想支持旧版本的Internet Explorer,那么可以考虑微软开发的Signal R系统。它们在底层使用WebSocket,但也有一些备选方案...因此协议将使用可用的最佳解决方案。

http://signalr.net/


3
Socket.io也有备用方案。 - JorgeGarza

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接