多客户端同步

时间:2012-01-31 22:48:14

标签: php javascript synchronization latency

我面临的问题是:我有N个可以触发事件的IPads。如何在服务器端知道谁先触发了事件。用于服务器端的语言是PHP和客户端JavaScript(JQuery)。最大的问题是延迟,所以简单地发送AJAX轮询是行不通的,因为我可以在j之前按下按钮,但是由于延迟,服务器可以在我之前得到j请求。由于IPad未同步到毫秒或更小的单位,因此节省按下时间也不是最佳选择。也许有某种协议可以解决这个问题,我可以从中获得一些想法吗?

1 个答案:

答案 0 :(得分:1)

这里有两种方法可用于检查延迟。

然后您可以计算用户的请求到达时间

请求的实际时间=请求到达时间 - 延迟

请求到达时间必须是服务器时间(当请求到达服务器时),因此我们不需要同步单元。但延迟数据必须来自客户端以及请求数据。您必须创建一个客户端脚本来轮询和计算平均延迟时间。


第一种方法是taken from a question here in stackoverflow。这个使用ajax。这是我搜索过的最精确的,与实际偏差不到10毫秒。它的作用是调用(通过ajax)服务器的一个页面(示例中的“/”url是你的web根目录)

  • 优点:我们使用jQuery ajax .success()在收到回复后但在加载回复数据之前触发事件(因此请求大小无关紧要)

  • 缺点:ajax不跨域(没有帮助)。但是如果你有自己的服务器,没问题。


第二个是taken from here,我修改了一下。这最初是作为服务器测试程序创建的,用于测试服务器是否仍在那里。

  • 优点:跨域(我们使用img = new Image()“图像预加载器”方法)

  • 缺点:互联网速度快。有效负载大小(在这种情况下,图像)和互联网速度将很重要,因为我们只使用在内容加载后触发的.onLoad()

根据图像尺寸的不同,这个偏差约为200-400ms。

//this is a static class. values are preserved. do resets before and after use.
var ping = {

    //the sample image. make it as small as possible like 1 x 1 px black and white. 
    //we are only testing ping, not download times
    //replace with your own image on your server since this link will die soon
    picture: "http://205.196.122.17/vh8cvmdtgfsg/8nsd22kphe1fz5w/spacer.bmp",

    //placeholder for test subject
    pictureFrame: null,

    //timer
    timer: null,

    reset: function(){
        //clear timeouts and timer
        clearTimeout(ping.timer);
        ping.timer = null;

        //clear the picture frame
        ping.pictureFrame = null;
    },

    //start ping function
    init: function() {

        //reset
        ping.reset();

        //get time before request
        var preSess = new Date();
        var preTime = preSess.getTime();

        //append current timestamp so request won't be from cache
        var pictureUri = ping.picture + "?time=" + preTime; 

        //create placeholder    
        ping.pictureFrame = new Image();
        ping.pictureFrame.onload = function() {

            //get time after load
            var postSess = new Date();
        var postTime = postSess.getTime();
            var requestTime = postTime - preTime;

            alert("Ping took "+requestTime+"ms");

            //reset
        ping.reset();
        };

        //triggers loading
        ping.pictureFrame.src = pictureUri;

        //set maximum timeout (in ms) before we declare domain not there
        ping.timer = setTimeout("ping.failed()", 60000);
    },

    //time-out reached
    failed: function() {
        //reset
        ping.reset();

        //alert what happened
        alert("Ping took too long");
    }
};

ping.init();