Websockets上的数据排序不良

时间:2013-02-07 20:49:59

标签: c# javascript websocket highcharts

我一直在努力学习通过websockets“实时”传递和显示数据。在这种情况下,实时意味着每隔 .03到1秒从传感器(带图像处理的相机)读取数据。每个数据点由一个时间和一个值(t,v)组成,它们被编码为双精度数(尽管在这种情况下时间总是一个整数,我不假设它是。)< / p>

服务器端使用Alchemy Websockets实施( C#),因为我觉得很容易理解/修改我的目的。

我正在利用找到herehere示例以及Alchemy中包含的示例。

我正在使用HighChartsdisplay the data in "real-time",但我也有打印到div 以进行调试(独立示例,因此它们不会相互干扰)。

其中很多功能已经很好用了,但是当我发送数据太快时会发生明显的问题(要清楚,发送关于点的数据每两秒或两次产生一个漂亮的图表似乎没有任何问题 - 问题变得越来越明显,我称之为炼金服务器“发送”功能的速度越快。

数据似乎以错误的顺序进入,导致有趣的“受损”效果。

Mangled Data Points

我将开始深入研究服务器端缓冲区中包含的数据包顺序(当新用户连接时,服务器被指示发送一定数量的“历史”点。已经运行 - 这导致一个明显的问题,如上图所示)以及客户端通过查看时间戳接收订单。

错误不一致每次重新加载页面时都会产生不同的“受损”数据集。这让我怀疑通过websockets的通信是负责任的还是涉及炼金术服务器的事情。

如果有必要,我会附上完整的代码,但是现在它非常混乱,所以我更想找到故障排除的想法。

我已经收集到了这不是Web套接字的预期行为,因为它是基于TCP构建的。

有什么建议/想法可以查看的内容吗?

谢谢!

编辑:我每次刷新页面时都运行了另一个测试来检查有多少数据点乱序。数字如下:

1 2 3 25 6 5 10 11 96 2 8

非常不一致(从不0)。当然很有意思!

此结果是通过排除图表组件并仅使用websockets和数组来存储数据。

更新

我决定开始分析输入的顺序,它似乎是使用相同的数据集随机接收乱序点。我实现了一个“插入”功能,它将考虑乱序包。结果(加上一点主题变化)看起来很不错!

Yes I know it's not "random data".

打开问题仍然存在:是否期望websocket可以无序传递信息?或者我在服务器端(或Alchemy)的实现有问题。我有空的时候会进一步调查。

解<!/强>

我明白了!经过大量的测试,我意识到我的Connection对象(它负责观察新数据的数据集,并根据连接的配置方式发送它)是使用Timer对象实现的。这是我从一个例子中得到的东西(通常我只是使用Thread对象来处理异步的大多数事情)。

当Timer对象加速时,它开始与之前调用它的Tick函数异步执行。这意味着偶尔会有一次调用它的Tick函数比另一个调用快一些(由于Alchemy Send函数的延迟)。这会导致轻微的乱序问题。

我将通信循环的实现从Timer对象切换到Thread对象,从而强制执行同步,并且无序数据包消失了!

3 个答案:

答案 0 :(得分:1)

Websockets使用TCP,TCP保证数据按顺序传递。

我希望浏览器也按顺序触发websocket消息事件。在我的测试中,情况似乎如此。

使用这个简单的Node应用程序进行测试:

var sio = require('socket.io')
    , http = require('http')
    , express = require('express')
    , app = express()
    , srv = http.createServer(app)
    , io = sio.listen(srv)
    , fs = require('fs')
    , idx = fs.readFileSync('index.html').toString()
    ;

app.get('/', function(req, res) {
    res.send(idx);
});

var i = 0;
setInterval(function() {
    io.sockets.emit('count', i++);
}, 1);

srv.listen(888);

这只是尽可能快地发送websocket消息,并且每个消息都会增加一个数字。客户:

<script src="/socket.io/socket.io.js"></script>
<script>
var last = 0;
var socket = io.connect('/');
socket.on('count', function(d) {
    if (d-1 != last) console.warn('out of order!', last, d);
    last = d;
});
</script>

如果收到包含的数字不是上一封邮件的邮件,则会引发控制台警告。

在Chrome和Firefox中,我看到零无序消息。

我还尝试在收到消息的事件(for (var i = 0; i < 1000000; i++) { })中阻塞一段时间来模拟可能导致消息排队的工作。消息事件仍按顺序触发。

换句话说,它是您设置中的其他内容。最有可能的是,Alchemy服务器实际上是以不同的顺序发送消息。

答案 1 :(得分:0)

当任务同步时,不要使用Timer这样具有异步回调的对象。 使用 a Thread并以这种方式运行通信循环。

答案 2 :(得分:0)

我不知道问题何时发布。我也有类似的问题。我用Alchemy Client发送小数据,那就没问题了。聊天服务有很多例子。但是当我发送一些超过4 KB的文件(不精确)时,就会出现问题。我试着找到发生的事情。我编写了一个程序,由Alchemy客户端发送0-7000的数字,并从UserContext.DataFrame(onreceive)收到,DataFrame.ToString将在约508位置上获得额外的"\0\0\0\0"。然后,在此位置之后,数据排序将是错误的。我使用了nuget的2.2.1。我在GiHub上阅读了2.0版本。源代码不可行。所以,旧的,没有参考价值。