在线游戏,或者比 ajax 更快的东西来发送/接收数据
Posted
技术标签:
【中文标题】在线游戏,或者比 ajax 更快的东西来发送/接收数据【英文标题】:Online gaming, or something faster then ajax for sending/receiving data 【发布时间】:2012-09-30 15:29:50 【问题描述】:我会尽量简短。
到目前为止我做了什么:
我的游戏将使用 setTimeout
或 setInterval
使用 javascript 运行。这不是闪光或任何特别的东西。到目前为止,我所做的就像一个测试运行(这样你可以更好地理解),几乎是循环 Ajax 以尽可能快地向 php 页面发送请求,然后 PHP 从 url 中读取 $_GET
请求,然后 PHP 使用$_GET
编辑一个名为 p1.html 的文件,这只是玩家 1 的 x 和 y 轴坐标。所以在玩家 2 的浏览器中,它和我上面说的差不多,现在当它收到 Ajax 请求时,它会收到玩家 1 的坐标。所以 JavaScript 做它所做的,并在玩家 2 的浏览器上移动玩家 1。那是我自己制作的,我对其进行了测试,是的,它可以工作,是的,当我修复所有错误和东西时,它会永远持续下去。
这么说,这就是我目前所做的,但如果我想要一款在线格斗游戏或实时横向卷轴游戏,这还不够快。所以这就是我需要帮助的地方。我知道 w3schools.com 上的很多东西,但我就是不知道如何完成这项工作。大概就是这样。我只需要浏览器 1,将数据发送到浏览器 2,类似于“1,100,200”或实际上更长一点,并让浏览器 2 将该数据作为 JavaScript 中的变量读取(任何类似于 x="received data";
的东西),仅此而已。 JavaScript 将完成剩下的工作。
我确信我可以自己编程我需要的一切,但是对于从 A 点到 B 点每秒发送 50 次数据,我对此一无所知。连名字都没有。最后,网址和示例会非常好(更清楚)。特别是如果它已经在 w3schools.com 上(带有示例)而我只是错过了它。
【问题讨论】:
w3fools.com 【参考方案1】:您可以使用websocket
WebSockets(优于 AJAX)的优势基本上是 HTTP 开销更少。建立连接后,所有未来的消息传递都通过套接字而不是新的 HTTP 请求/响应调用。因此,您会假设 WebSockets 每单位时间可以发送和接收更多的消息。事实证明这是真的。但是,一旦您将延迟添加到混合中,就会有一个非常痛苦的现实。
WebSockets 比 AJAX 快大约 10-20%
source
当我们在 php 中使用 ajax 时会发生什么
-
它打开一个到 apache 服务器的新连接
比 apache 寻找 php 脚本并启动它
现在 php 脚本将连接到服务器进行查询并返回结果。
但是 websocket 所做的是消除了 2 个连接进程,并且只会向服务器发送一条消息。服务器已经连接到sql server
另一个好处是客户端和服务器之间的连接保持打开状态,服务器可以向客户端发送消息。在ajax中你每次都需要调用
【讨论】:
比这更好的是,websockets 允许推送数据并且不需要定期轮询(请参阅其他答案) 实际上这完全取决于您如何使用它们:P【参考方案2】:答案很简单:使用websockets。它们允许在两个方向上立即推送数据,以实现看似即时的交互。它们消除了从缓慢而繁重的客户端(包括服务器)提取数据的需要。请注意,这是my favorite game 中用于通知推送的解决方案。
您可能对this introduction on websockets on PHP 感兴趣。但请注意,对于长连接处理和实时游戏(您可能更喜欢 Go、node.js、java 等),PHP 确实不是最有效的解决方案。
【讨论】:
【参考方案3】:我同意其他发帖者的观点:websockets 是您应该使用的技术。唯一的缺点是 Internet Explorer 版本 10 之前不支持 Websockets,目前仅适用于 Windows 8,并且不适用于 Windows 7 之前的任何 Windows 版本。当你想在 Vista 和 XP 上支持 IE 用户时,您需要使用 AJAX 或 Flash 进行后备。
但是你可能会遇到另一个问题:
用于从 A 点向 B 点发送数据,例如每秒 50 次
当您需要频繁发送数据时,您的协议似乎有问题。您是否计划以 20 毫秒的固定间隔更新玩家位置,即使他们没有改变(玩家站立)或以恒定速率改变(玩家朝一个方向行走)?我建议你不要转移位置,而只改变移动方向(开始向左移动,在 X:Y 处停止向左移动等),这样可以保证大量带宽。
【讨论】:
微软官方告知 ie 使用不安全Do you plan to update the player positions at regular intervals of 20ms even though they didn't change
- 鉴于当前的设计(轮询,而不是推送)数据需要传输,即使说“什么也没发生”,否则 B 点永远不会知道 A 点何时有更新。跨度>
通过 AJAX 推送可以使用一种称为“AJAX 长轮询”的技术来完成。它的工作原理是延迟 AJAX 响应,直到有东西要发送。 ***.com/questions/333664/…
only changes in movement direction
我刚刚意识到这就是为什么当您与许多流行游戏断开连接时,您的玩家角色会继续向某个看似随机的方向逃跑的原因。说停止运行的事件从未收到。
这也是许多流行游戏允许速度hack的原因:由于网络抖动(不可靠的延迟),发送准确的停止位置很重要,否则客户端和服务器将很快变得异步。但是当服务器盲目地信任停止位置时,客户端可以发送比游戏机制允许的更远的停止位置。防止这种服务器端并不像看起来那么简单,因为客户端和服务器之间的微小时间差异在在线环境中是很自然的。要检测速度黑客,需要采用启发式方法。【参考方案4】:
如果架构正确,long polling ajax 请求可以很好地用于非实时通信。话虽如此,长轮询更像是一种“黑客”;如果您正在寻找具有所需连接性的内置,那么您的选择肯定是websockets:
WebSockets 是一种先进的技术,它可以打开一个 用户浏览器与 服务器。使用此 API,您可以将消息发送到服务器并接收 事件驱动的响应,无需轮询服务器以获取回复。
查看browserquest 以获得灵感 - Mozilla 的优秀人员提供了其完整源代码on github!
【讨论】:
【参考方案5】:试试这个:http://socket.io/
它可以做 websockets、长轮询、flash sockets 等等! 他们声称它支持 IE 5.5。
【讨论】:
【参考方案6】:Websockets 很棒,并且经常被提及,但是 android 设备和 16% 的浏览器不支持 websockets (CanIUse.com)。许多服务器安装也不支持 websocket,包括共享 LAMP 设置。如果您有共享主机或想要获得广泛支持,websockets 可能不是一个有效的选择。
长轮询是 websocket 的唯一有效替代方案。它有更广泛的支持(它应该适用于几乎所有的服务器和客户端),但它在不能很好地处理许多同时连接的服务器上(比如 Apache)有一个明显的缺点。另一个缺点是,无论连接了多少用户,您都必须执行许多常规数据库查询(可能每秒几次)。使用共享内存,如 PHP 中的shm_attach()
,可以减轻这种负担。当服务器脚本监视新消息时,一旦发现它们就会立即通过打开的连接发送。客户端将收到消息,然后通过新请求重新启动长连接。
如果您不能使用 websockets(很可能是这种情况),您可以使用长短轮询混合(见下文)。使用非常长的轮询是不必要的,并且会占用太多资源。在持续连接大约 10 或 15 秒后,您应该将其关闭并切换到老式的短轮询,这只是一个重复的常规 GET 请求。
这个 jQuery 代码未经测试,但你明白了:
function longpoll(lastid)
/* Start recursive long polling. The server script must stay
connected for the 15 seconds that the client waits for a response.
This can be done with a `while()` loop in PHP. */
console.log("Long polling started...");
if (typeof lastid == 'undefined')
lastid = 0;
//long polling...
setTimeout(function ()
$.ajax(
url: "stream.php?long=1&lastid=" + lastid, success: function (payload)
if (payload.status == "result")
//result isn't an error. lastid is used as bookmark.
console.log("Long poll Msg: " + payload.lastid + ": " + payload.msg);
longpoll(lastid); //Call the next poll recursively
else if (payload.status == "error")
console.log("Long poll error.");
else
console.log("Long poll no results.");
/* Now, we haven't had a message in 15 seconds. Rather than
reconnect by calling poll() again, just start short polling
by repeatedly doing an normal AJAX GET request */
shortpoll(lastid); //start short polling after 15 seconds
, dataType: "json"
);
, 15000); //keep connection open for 15 seconds
;
function shortpoll(lastid)
console.log("Short polling started.");
//short polling...
var delay = 500; //start with half-second intervals
setInterval(function ()
console.log("setinterval started.");
$.ajax(
url: "stream.php?long=0&lastid=" + lastid, success: function (payload)
if (payload.status == "result")
console.log(payload.lastid + ": " + payload.msg);
longpoll(lastid); //Call the next poll recursively
else if (payload.status == "error")
console.log("Short poll error.");
else
console.log("Short poll. No result.");
, dataType: "json"
);
delay = Math.min(delay + 10, 20000) //increment but don't go over 20 seconds
, delay);
短轮询减少了并发连接的数量,而是使用重复轮询(请求)。与往常一样,短轮询的缺点是延迟获取新消息。但是,这类似于现实生活,所以应该没什么大不了的。 (如果有人在过去一周内没有给你打电话,他们不太可能在接下来的五分钟内给你打电话,所以每五分钟检查一次你的手机是很愚蠢的。)
【讨论】:
以上是关于在线游戏,或者比 ajax 更快的东西来发送/接收数据的主要内容,如果未能解决你的问题,请参考以下文章