在线游戏,或者比Ajax更快的数据发送/接收方式

11

我会尽可能简短地叙述。

到目前为止,我已经做了什么:
我制作的游戏将使用JavaScript使用setTimeoutsetInterval运行。它不是Flash或任何特殊的东西。到目前为止我所做的就像是一个测试(以便您更好地理解),它几乎循环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上(附有示例),而我只是错过了。


13
好的,以下是对http://w3fools.com的翻译:W3Schools是一个在线学习编程技术的网站。然而,一些开发者认为该网站提供的信息不够准确和完整,尤其是在HTML、CSS和JavaScript方面。W3Fools网站旨在揭示这些问题,并提供更好的替代学习资源。 - 11684
6个回答

16

你可以使用 websocket

与 AJAX 相比,WebSockets 的优点在于 HTTP 开销较小。一旦建立连接,所有后续的消息传递都是通过套接字而非新的 HTTP 请求/响应调用进行的。因此,你会认为 WebSockets 可以每单位时间发送和接收更多的消息。结果证明这是正确的。但是一旦增加延迟,就会出现非常严峻的现实。

WebSockets 大约比 AJAX 快 10-20%。

来源

当我们将 AJAX 与 PHP 一起使用时会发生什么

  1. 它会打开一个到 Apache 服务器的新连接
  2. 然后 Apache 查找 PHP 脚本并启动它
  3. 现在 PHP 脚本将连接到服务器进行查询,并返回结果。

但是 WebSocket 所做的是消除两个连接过程,并只向服务器发送一条消息。服务器已经连接到 SQL 服务器了。

另一个好处是客户端和服务器之间的连接保持打开状态,服务器可以向客户端发送消息。而在 AJAX 中,需要每次都进行调用。


2
更好的是,Websockets允许推送数据,而不需要定期轮询(请参见其他答案)。 - Izkata
其实这完全取决于你如何使用它们 :P - ShrekOverflow

15
答案很简单:使用Websockets。它们可以在两个方向上立即推送数据,实现几乎瞬间的交互。它们消除了从客户端拉取数据的必要性,这很慢、很重(包括对服务器)。请注意,这是我最喜爱的游戏中用于通知推送的解决方案。
你可能会对这篇关于PHP Websockets的介绍感兴趣。但是请注意,PHP并不是处理长连接和实时游戏最高效的解决方案(你可能更喜欢Go、Node.js、Java等)。

9
我同意其他帖子中的观点:Websockets是您应该使用的技术。唯一的缺点是,在Internet Explorer 10之前,Websockets不支持早于Windows 8的任何Windows版本(如Vista和XP)。当您想要支持Vista和XP上的IE用户时,需要使用AJAX或Flash备用方案。
但你可能会遇到另一个问题:
当您需要每秒发送50次从A点到B点的数据时,您的协议似乎出了问题。您是否计划定期以20毫秒的时间更新播放器位置,即使它们没有改变(播放器站立)或者以恒定速率改变(播放器向一个方向行进)?我建议您仅传输运动方向的变化(开始向左移动,在X:Y处停止向左移动等),这样可以节省大量带宽。

微软官方表示IE不安全,建议不要使用。 - NullPoiиteя
你是否计划以20毫秒的固定间隔更新玩家位置,即使它们没有改变?鉴于当前的设计(轮询而非推送),数据需要传输,即使是为了表明“没有发生任何事情”,否则B点将永远不知道A点是否有更新。 - Izkata
通过一种称为“AJAX长轮询”的技术,可以使用AJAX进行推送。它的工作原理是延迟AJAX响应,直到有东西要发送。https://dev59.com/W3RC5IYBdhLWcg3wVvYt - Philipp
仅仅是移动方向的变化。我刚刚意识到这就是为什么当你从许多流行游戏中断开连接时,你的玩家角色会继续朝着某些看似随机的方向奔跑的原因。停止奔跑的事件从未被接收到。 - Isaac Fife
这也是为什么许多流行的游戏允许速度作弊的原因:由于网络抖动(不可靠的延迟),发送精确的停止位置非常重要,否则客户端和服务器很快就会变得异步。但是当服务器盲目信任停止位置时,客户端可以发送比游戏机制允许的距离更远的停止位置。在服务器端防止这种情况并不像看起来那么简单,因为在线环境中客户端和服务器之间的微小时间差异是自然而然的。要检测速度作弊,需要采用一种启发式方法。 - Philipp

6
当架构正确时,长轮询 ajax 请求对于非实时通信工作得很好。也就是说,长轮询更像是一种“hack”;如果你正在寻找一些具有所需连接性的东西,你的选择应该是WebSockets

WebSockets 是一种先进的技术,可以在用户的浏览器和服务器之间打开一个交互式通信会话。使用此 API,您可以向服务器发送消息并接收事件驱动的响应,而无需轮询服务器以获取回复。

请查看browserquest以获得灵感 - Mozilla 的优秀人员将其整个源代码 放在了 github 上

2

尝试这个:http://socket.io/

它可以使用WebSocket、长轮询、Flash套接字等多种技术! 而且他们声称支持IE 5.5。


0

Websockets非常好用,经常被提到,但是Android设备和16%的浏览器不支持websockets(CanIUse.com)。许多服务器安装也不支持websockets,包括共享LAMP设置。如果您有一个共享主机或者想要广泛支持,websockets可能不是一个有效的选择。

长轮询是websockets的唯一有效替代方案。它具有更广泛的支持(它应该可以与几乎所有服务器和客户端一起使用),但是在不能很好地处理许多同时连接的服务器上(如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);
}

短轮询通过重复轮询(请求)来减少并发连接的数量。与往常一样,短轮询的缺点是获取新消息的延迟。然而,这类似于现实生活,所以不应该成为大问题。(如果有人在过去一周没有给你打电话,他们不太可能在接下来的五分钟内给你打电话,所以每五分钟检查手机是愚蠢的。)


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