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

我有一个node.js服务器与socket.io。 我的客户使用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] } 

…服务器将花费很长时间来循环所有这些数据。

那么,防止这种情况的最佳解决scheme是什么?

谢谢

编辑:

我用这个函数来validation对象:

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

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

 socket.on('someevent', function (data) { if (JSON.stringify(data).length > 10000) //roughly 10 bytes return; console.log('valid data: ' + data); }); 

说实话,这有点低效。 你是客户端发送的消息,socket.ioparsing消息到一个对象,然后你得到的事件,并把它变成一个string。

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

为了提高效率(并防止恶意用户),当数据包进入Socket.io时,如果长度太长,则应丢弃它们。 你需要想办法扩展原型来做你想做的事情,或者你需要拉动源代码并自己修改。 另外,我还没有查看socket.io协议,但是我相信你不仅仅需要“丢弃”这个数据包。 另外,有些数据包是反面的,反面的,所以你也不想惹他们。


注意:如果你只关心键的数量,那么你可以使用Object.keys(obj)来返回键的数组:

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

可能你可能会考虑切换到socket.io-stream并直接处理inputstream。

这样你应该join块,并最终手动parsingjsoninput,但是当input数据长度超过你决定的阈值时,你有机会closures连接。

否则(使用socket.io方法)只有在收到整个数据stream之后才会调用callback函数。 这不会停止你的js主线程的执行,但是会浪费内存,cpu和带宽。

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

 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. 

那么,我会用这个东西的Javascript侧面来说吧…比方说,你不想让用户超过一定的数据限制,你可以:

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

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

也许destroy buffer size是你需要的。

来自wiki :

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

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

编辑 :因为问题是关于“如何处理服务器过载”你应该检查与gninx的负载平衡http://nginx.com/blog/nginx-nodejs-websockets-socketio/ – 你可以有额外的服务器,以防一个客户端造成瓶颈。 其他服务器将可用。 即使你解决了这个问题,还有其他的问题,比如客户端发送几个小包等等。

Socket.io-library似乎有点问题,pipe理太大的消息在websockets层是不可用的,三年前有一个pull-request,这让人想到如何解决这个问题:

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

但是,由于WebSockets-协议确实具有有限的数据包大小,因此如果达到一定的大小,它将允许您停止处理数据包。 这样做的最有效的方法是在数据包变成JavaScript堆之前。 这意味着你应该手动处理WebSocket转换 – 这是socket.io为你做的,但是它没有考虑到数据包的大小。

如果你想实现你自己的websocket层,使用这个WebSocket的节点实现可能是有用的:

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

如果你不需要支持旧的浏览器,使用这个纯粹的websocket -approach可能是合适的解决scheme。