Node.js / Server.js 套接字实现问题

Posted

技术标签:

【中文标题】Node.js / Server.js 套接字实现问题【英文标题】:Node.js / Server.js socket implementation problems 【发布时间】:2015-01-07 16:24:18 【问题描述】:

很难实现 node.js/server.js 设置

我现在有点卡住了,希望有人能解释一下。一般来说,我对套接字相对较新,但多年来一直在使用 javascript 进行编程,尽管只有完成手头任务所需的深度。因此,我对围绕 javascript 堆栈堆和一般套接字的一些概念的理解有些有限。 好的,情况如下:

我创建了一个应用程序,用于在多台机器上简单地增加一个计数器。几个用户可以单击“下一步”按钮,它会立即在所有机器上更新。 当您第一次连接时,它会检索当前号码,并在本地将其吐出。

我在这里创建了服务器:

var io = require("socket.io");
var sockets = io.listen(8000);
var currentlyServing=0;
sockets.on("connection", function (socket)
 
    console.log("client connected");
    socket.emit("receive", currentlyServing);
    socket.on("update", function(serving)
    
        currentlyServing=serving;
        if(currentlyServing>100)
            currentlyServing=0;
        if(currentlyServing<0)
            currentlyServing=99;
        socket.broadcast.emit("receive", currentlyServing);
        console.log("update received: "+currentlyServing);
    );
);
console.log("Server Started");

这是来自客户端的相关(我希望)摘录:

var socket = io.connect("http://www.sampledomain.com:8000");

//function to update the page when a new update is received
socket.on("receive", function(receivedServing)

    document.getElementById('msgs').value=""+String("00" + receivedServing).slice(-2);
    document.getElementById('nowServing').value=receivedServing;
);

//this is called in an onClick event in the html source
//sends the new number to all other stations except this one (handled by server side)
function nextServing() 

    var sendServing = parseInt(document.getElementById('nowServing').value)+1;
    socket.emit("update", sendServing);
    document.getElementById('nowServing').value=sendServing;
    document.getElementById('msgs').value=""+String("00" + sendServing).slice(-2);

好的,这是我的问题。这在我放入的每个系统中都运行得非常好,流畅而精美 - 除了 IE8。如果单独放置超过 2-3 分钟(根本没有活动),我最终会收到“堆栈溢出”错误。它出现的行号会波动(尚未确定所涉及的因素),但它总是在那个间隔发生。在某些工作站上,它需要更长的时间,我开始认为这与机器拥有的物理 RAM 的数量直接相关,或者至少与分配给 Web 浏览器的数量有关。

我找到了一个在线函数来确定“最大堆栈大小”,我意识到这不是一门精确的科学,但是我确实得到了一个 3000 范围内的数字。在我的 IE11 机器上,我找到了更多资源在20,000的范围内。这可能不相关,但我认为信息越多越好:)

为了暂时避免这个问题,以便最终用户看不到这个错误消息,我已经将整个客户端脚本放入一个 iFrame 中,它每 60 秒重新加载一次,基本上是重置堆栈,这坐在离网络插座很近的地方感觉很脏,但让我有时间在这里发帖。我已经用谷歌搜索了,直到我不能再用谷歌搜索了,但是当你在谷歌上搜索“node.js”或“socket.io”以及“堆栈溢出”时,你只会得到很多关于这两个主题的帖子托管在 *** dot com 网站上。 ARG 哈哈

有人吗?

根据以下评论于 2014 年 11 月 18 日编辑:

错误消息通常在第 1056 行声称堆栈溢出。IE 开发工具指向文件 socket.io.js。第 1056 行是:

return fn.apply(obj, args.concat(slice.call(arguments)));

这是文件的这一部分:

var slice = [].slice;

/**
 * Bind `obj` to `fn`.
 *
 * @param Object obj
 * @param Function|String fn or string
 * @return Function
 * @api public
 */


module.exports = function(obj, fn)
  if ('string' == typeof fn) fn = obj[fn];
  if ('function' != typeof fn) throw new Error('bind() requires a function');
  var args = slice.call(arguments, 2);
  return function()
    return fn.apply(obj, args.concat(slice.call(arguments)));
  
;

【问题讨论】:

您使用的是哪个版本的 socket.io?最新的?我在 github 问题页面上发现了一些可能与 here 和 here 相关的问题,希望对您有所帮助。 看起来我使用的是 1.1.0 - 我是从 History.md 文件中得到的。认为我无法从我的所有客户端计算机中删除闪存(re:第一个链接),并且第二个链接中提到的代码似乎在后续版本中已更改。让我的希望在那里大声笑 你试过在'nextServing()'中设置断点吗?我会先检查一下以确保没有无限循环。错误总是在您的代码中抛出还是在 socket.io 代码本身中? IE 8 堆栈溢出错误是出了名的难以调试。我在发布的代码中没有看到问题,因此我建议您逐步禁用代码,直到您可以将其缩小到几行。 不知道socket.io有没有使用flash,但是你可以在不支持websockets的浏览器上设置使用长轮询,这样应该避免使用flash。 【参考方案1】:

可以尝试替换

""+String("00" + receivedServing).slice(-2)

('00' + receivedServing).slice(-2)

【讨论】:

不,String() 不应该new 调用! new String("abc") 结果为 "0": "a", "1": " b", "2": "c"【参考方案2】:

查找现有问题Causes a "Stack Overflow" in IE8 when using xhr-polling #385。

已通过禁用 Flash 解决此问题。

也可以找到Safari over windows client use xhr-polling instead of websocket - performance are severely harm #1147。虽然这是 Safari,但它可能适用于 IE8,因为它使用了类似的机制。

我使用你的 socket.io 做了一个小测试,但在 IE 10 中并模拟了 IE8 这样我就可以很好地调试了。开始在选项卡中捕获网络并 注意到每隔几秒就会记录一次请求。只留下几个 分钟,我看到很多请求登录。你不会看到这个 在 Chrome 中,因为它具有真正的 WebSockets。虽然 IE8 不支持 WebSockets socket.io 模拟使用普通 HTTP GET/POST 使用一些 机制。所以我的理论是,即使 socket.io 与 IE8 一起使用它 不能可靠地模拟网络套接字

我的建议是排除 IE 8 用于长时间运行的客户端应用程序。 IE8 is no longer supported by Microsoft.

【讨论】:

我也确实将其作为一个选项阅读 - 但不幸的是,从 IE8 升级不是一个选项,因为我的客户正在使用另一家公司的一些基于 Web 的软件,这些软件需要 IE8 才能运行。不要让我开始谈论那个话题,大声笑。底线是我们必须使我们所做的一切向后兼容,可以追溯到 IE8。也不能禁用闪存,因为这些其他应用程序需要它。今天下午将尝试这些其他解决方案 - 我的赏金时间不多了【参考方案3】:

从我读到的内容看来,IE8 上的问题可能与闪存有关。它 IE8 使用 flashsocket 作为默认配置。我建议在客户端尝试以下操作:

 if(navigator.appName.indexOf("Internet Explorer")!=-1 && navigator.appVersion.indexOf("MSIE 8")==-1 )      
      socket = io.connect("http://www.sampledomain.com:8000", 
           transports: ['xhr-polling']
      );
 
 else
 
       socket = io.connect("http://www.sampledomain.com:8000" );
 

这应该使 IE8 使用长轮询,而所有其他机器都使用它们可以使用的最佳方法。

附带说明:您可能还需要考虑增加服务器上的“服务”变量。

【讨论】:

您是说 !=-1 代表 MSIE 8 吗? 刚刚发现这是一个 IE 8 浏览器,IE8 浏览器模式,但 IE7 标准文档模式,你认为这会改变什么吗? 试过了 ("MSIE 8")==-1, ("MSIE 8")!=-1, and ("MSIE 7")!=-1 不幸的是没有运气仍然让堆栈溢出错误:(

以上是关于Node.js / Server.js 套接字实现问题的主要内容,如果未能解决你的问题,请参考以下文章

Node.js - 在 Server.js 上执行 Node 命令(Express + React + Webpack)

Node.js入门-知识整理

ajax+node.js玩转注册与登录

NODE.JS 如何使用 node.js 显示位于名为 CSS 的文件夹内的我的 css 文件,其中我的 server.js 和 index.html 在文件夹外

Node JS 服务器代码中的 Webpack 别名

在nginx服务器里面搭建好node.js本地服务器后,利用Node.js的FS模块,实现简单数据的写入和读取