Socket.io:如何限制从客户端到websocket服务器的发出数据的大小

时间:2014-02-11 15:35:49

标签: javascript node.js socket.io

我有一个带socket.io的node.js服务器。我的客户端使用socket.io连接到node.js服务器。

数据以下列方式从客户端传输到服务器:

在客户端

var Data = {'data1':'somedata1', 'data2':'somedata2'};
socket.emit('SendToServer', Data);

在服务器上

socket.on('SendToServer', function(Data) {
    for (var key in Data) {
           // Do some work with Data[key]
    }
});

假设某人修改了他的客户端并向服务器发送了大量数据。例如:

var Data = {'data1':'somedata1', 'data2':'somedata2', ...and so on until he reach for example 'data100000':'data100000'};
socket.emit('SendToServer', Data);

由于服务器上的这个循环......

for (var key in Data) {
       // Do some work with Data[key]
}

......服务器需要很长时间来遍历所有这些数据。

那么,防止此类情况的最佳解决方案是什么?

由于

修改

我使用此函数来验证对象:

function ValidateObject(obj) {
    var i = 0;
    for(var key in obj) {
        i++;
        if (i > 10) { // object is too big
            return false;
        }
    }
    return false;
}

5 个答案:

答案 0 :(得分:4)

所以最简单的方法就是在做任何事情之前检查一下数据的大小。

socket.on('someevent', function (data) {
    if (JSON.stringify(data).length > 10000) //roughly 10 bytes
        return;

    console.log('valid data: ' + data);
});

说实话,这有点低效。您的客户端发送消息,socket.io将消息解析为一个对象,然后您获取该事件并将其转换回String。

如果你想要更高效,那么在客户端你应该强制执行最大长度的消息。

为了提高效率(并防止恶意用户),当数据包进入Socket.io时,如果长度太长,那么你应该丢弃它们。你需要想办法扩展原型以做你想做的事情,或者你需要拉动源并自己修改它。此外,我还没有研究过socket.io协议,但我确信你不仅要做“丢弃”数据包。此外,一些数据包是ack-backs和nack-backs,所以你也不想搞砸那些。

附注:如果您只关心密钥的数量,那么您可以使用Object.keys(obj)返回一组密钥:

if (Object.keys(obj).length > 10)
    return;

答案 1 :(得分:3)

您可能会考虑切换到socket.io-stream并直接处理输入流。

这种方式你应该加入块并最终手动解析json输入,但是当输入数据长度超过你决定的阈值时,你有机会关闭连接。

否则(继续使用socket.io方法)在收到整个数据流之前,不会调用您的回调。这并不会阻止你的js主线程执行,但会浪费内存,cpu和带宽。

另一方面,如果您的唯一目标是避免处理算法过载,您可以通过计算接收对象中的元素来继续限制它。例如:

if (Object.keys(data).length > n) return; // Where n is your maximum acceptable number of elements.
// But, anyway, this doesn't control the actual size of each element.

答案 2 :(得分:2)

好吧,我将使用Javascript方面的东西......假设您不希望允许用户超过某个数据限制,您可以这样做:

var allowedSize = 10;

Object.keys(Data).map(function( key, idx ) {
    if( idx > allowedSize ) return;
    // Do some work with Data[key]
});

这不仅可以让您正确地循环浏览对象的元素,还可以轻松限制。 (显然这也会破坏你自己的预设请求)

答案 3 :(得分:2)

编辑:因为问题是"如何处理服务器过载"您应该使用gninx http://nginx.com/blog/nginx-nodejs-websockets-socketio/检查负载平衡 - 如果一个客户端正在创建瓶颈,您可以拥有其他服务器。其他服务器将可用。即使您解决了这个问题,仍然存在其他问题,例如客户端发送几个小数据包等等。

Socket.io -library似乎有点问题,在websockets层没有管理太大的消息,三年前有一个pull -request,它给出了一个如何解决它的想法:

https://github.com/Automattic/socket.io/issues/886

但是,由于WebSockets -protocol确实具有有限的数据包大小,因此如果已达到某个大小,它将允许您停止处理数据包。执行此操作的最有效方法是在数据包转换为JavaScript堆之前。这意味着您应该手动处理WebSocket转换 - 这是socket.io正在为您做的事情,但它没有考虑数据包的大小。

如果要实现自己的websocket层,使用此WebSocket -node实现可能很有用:

https://github.com/theturtle32/WebSocket-Node

如果您不需要支持旧版浏览器,那么使用此纯网页框 - 方法可能是合适的解决方案。

答案 4 :(得分:1)

也许destroy buffer size就是您所需要的。

来自wiki

  
      
  • 销毁缓冲区大小默认为10E7
  •   
     

由HTTP传输使用。 Socket.IO服务器将HTTP请求主体缓冲到此限制。此限制不适用于websocket或flashsockets。