Socket.io在IE11中以突发方式传输数据
Socket.io transmits data in bursts in IE11
编辑:我将源代码简化为最小测试用例以重现该行为。要重现该行为,需要 "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);
这里是令人费解的部分:
- 整件事在 chrome
中很有魅力
- 在 IE11 上,传输是突发的。大约 30 秒没有任何反应,然后所有数据都在一个短脉冲中传输。
- Mysterious:当我打开一个 Chrome 实例并在那里打开网站时,它在 IE11 中按预期工作,即数字在 IE11 和 Chrome 正如预期的那样。我一关闭Chrome,问题又出现了。
- Mysterious:当我使用
setInterval
而不是我的 testAsync
函数时,它在 IE11 中有效。 IE11怎么知道服务器上谁调用了io.emit
?
似乎可以通过向 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');
})
});
//...
整个过程对我来说还是有点神秘,但现在可以用了:)
编辑:我将源代码简化为最小测试用例以重现该行为。要重现该行为,需要 "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);
这里是令人费解的部分:
- 整件事在 chrome 中很有魅力
- 在 IE11 上,传输是突发的。大约 30 秒没有任何反应,然后所有数据都在一个短脉冲中传输。
- Mysterious:当我打开一个 Chrome 实例并在那里打开网站时,它在 IE11 中按预期工作,即数字在 IE11 和 Chrome 正如预期的那样。我一关闭Chrome,问题又出现了。
- Mysterious:当我使用
setInterval
而不是我的testAsync
函数时,它在 IE11 中有效。 IE11怎么知道服务器上谁调用了io.emit
?
似乎可以通过向 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');
})
});
//...
整个过程对我来说还是有点神秘,但现在可以用了:)