Socket.io在IE11中以突发方式传输数据

时间:2015-11-28 15:15:56

标签: c++ node.js socket.io internet-explorer-11 node-modules

编辑:我将源代码简化为最小的测试用例以重现行为。要重现行为,需要" index.html"," server.js"文件并编译" mycppmodule.cpp"文件。它们都在下面全部发布。

  • IE 11版本:11.0.9600.18097
  • 节点版本:v4.1.2

对我来说,这是一个有点神秘的问题,并且描述它有点困难所以请耐心等待。

所以,我有一个node.js服务器是一个非常简单的客户端网站和我用C ++编写的本机node.js模块。服务器和网站之间存在socket.io通信。

这是完整的网站客户端代码,它从服务器获取一个整数值并更新网站上的数字:

// index.html
<!doctype html>
<html>
    <head>
    <title>Test</title>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
    <script src="/socket.io/socket.io.js"></script>
    <script>
        $(document).ready(function () {
            var socket = io();
            var counter = 0;
            socket.on('data', function (data) {
                console.log("received" + data.counter);
                $("#id_counter").text(data.counter);
            });
        });
    </script>
    </head>
    <body>
    Counter: <span id="id_counter"></span>
    </body>
</html>

在服务器上驻留以下代码(完整代码):

// server.js
var http = require("http");
var url = require('url');
var fs = require('fs');

var mycppmodule = require('./build/Debug/mycppmodule');

var server = http.createServer(function(request, response){
    console.log('Connection');
    var path = url.parse(request.url).pathname;
    switch(path){
        case '/index.html':
            fs.readFile(__dirname + path, function(error, data){
            console.log('open ' + __dirname +  path);
                response.writeHead(200, {"Content-Type": "text/html"});
                response.write(data, "utf8");
                response.end();
            });
            break;
        default:
            response.writeHead(404);
            response.write("opps this doesn't exist - 404");
            response.end();
            break;
    }
});

var io = require('socket.io').listen(server);
mycppmodule.testAsync(function (counter) {
        console.log(counter);
        io.emit('data', { 'counter': counter });
});

io.on('connection', function (socket) {
    console.log("client connected");
});

server.listen(8001);
console.log("server running");

我的模块与javascript setInterval的行为有些相似。它大约每秒调用一次。这是一个简化的C ++模块,它显示了相同的行为:

// mycppmodule.cpp
#include <node.h>
#include <v8.h>
#include <nan.h>

using namespace v8;

static Persistent<Function, CopyablePersistentTraits<Function>> _cb; // saving the callback function
static uv_async_t async;    //asyncronous messaging

// Some short function that will message the callback every second
void asyncWork(void *arg) {
    static int i;
    for (;;) {
        i++;
        async.data = (void*)&i;
        uv_async_send(&async);
        Sleep(1000);
    }
}

// the callback that gets called by asyncWork will then call the javascript callback
void testCallback(uv_async_t *handle) {
    Isolate* isolate = Isolate::GetCurrent();
    HandleScope scope(isolate);
    int counter = *((int*)handle->data);
    auto context = isolate->GetCurrentContext(); 
    auto global = context->Global(); 
    auto fn = Local<Function>::New(isolate, _cb);
    const int argc = 1;
    Handle<Value> argv[argc];
    argv[0] = Number::New(isolate, counter);
    fn->Call(global, argc, argv);   // this is where the javascript callback gets invoked
}

void testAsync(const FunctionCallbackInfo<Value>& args) {
    Isolate* isolate = args.GetIsolate();
    Handle<Function> arg0 = Handle<Function>::Cast(args[0]);
    Persistent<Function> cb(isolate, arg0);
    _cb = cb;       // saving the javascript callback as persisitent
    uv_async_init(uv_default_loop(), &async, testCallback);
    uv_thread_t thread_id;
    uv_thread_create(&thread_id, asyncWork, Null);
}

void init(Handle<Object> target) {
  NODE_SET_METHOD(target, "testAsync", testAsync);
}

NODE_MODULE(MyCppModule, init);

以下是令人费解的一点:

  • 整个事情就像镀铬中的魅力一样
  • 在IE11上传输以突发方式发生。大约30秒没有任何事情发生,然后所有数据都在一个短脉冲串中传输。
  • 神秘:当我打开Chrome实例并在那里打开网站时,它可以按预期在IE11中工作,即IE11和Chrome中的数字会按预期更新。只要我关闭Chrome,问题就会重新出现。
  • 神秘:当我使用setInterval代替testAsync函数时,它在IE11中有效。 IE11如何知道谁在服务器上调用io.emit

1 个答案:

答案 0 :(得分:0)

似乎可以通过向socket.io通信添加确认来解决此问题。

index.html我添加了:

// ....
socket.on('data', function (data) {
    console.log("received" + data.counter);
    $("#id_counter").text(data.counter);
    socket.emit('ack'); // ADDED THIS LINE 
});
// ...

并在server.js中添加了:

//...
io.on('connection', function (socket) {
    console.log("client connected");
    // ADDED THE FOLLOWING THREE LINES
    socket.on('ack', function () { 
        console.log('received');
    })
});
//...

整件事对我来说仍然有点神秘,但它现在有效:)