Socket.io: RangeError: تم تجاوز الحد الأقصى لحجم مكدس الاستدعاءات

تم إنشاؤها على ٤ يوليو ٢٠١٤  ·  32تعليقات  ·  مصدر: socketio/socket.io

أنا فقط أدعو ìo.sockets.emit ('hey'، data)؛ and it will crash with RangeError: تجاوز الحد الأقصى لحجم مكدس المكالمات . I use it in other places in my app and it works fine. I am not repeating this (checked with console). The logs say the error is in socket.io/node_modules/has-binary-data/index.js: 46 ''.

لا أعلم أين تكمن المشكلة. لقد حاولت تسجيل io.sockets مباشرةً قبل استخدامه وكان الناتج:

{ name: '/',
17:39:37 web.1  |   server:
17:39:37 web.1  |    { nsps: { '/': [Circular] },
17:39:37 web.1  |      _path: '/socket.io',
17:39:37 web.1  |      _serveClient: true,
17:39:37 web.1  |      _adapter: [Function: Adapter],
17:39:37 web.1  |      _origins: '*:*',
17:39:37 web.1  |      sockets: [Circular],
17:39:37 web.1  |      eio:
17:39:37 web.1  |       { clients: [Object],
17:39:37 web.1  |         clientsCount: 2,
17:39:37 web.1  |         pingTimeout: 60000,
17:39:37 web.1  |         pingInterval: 25000,
17:39:37 web.1  |         upgradeTimeout: 10000,
17:39:37 web.1  |         maxHttpBufferSize: 100000000,
17:39:37 web.1  |         transports: [Object],
17:39:37 web.1  |         allowUpgrades: true,
17:39:37 web.1  |         allowRequest: [Function],
17:39:37 web.1  |         cookie: 'io',
17:39:37 web.1  |         ws: [Object],
17:39:37 web.1  |         _events: [Object] },
17:39:37 web.1  |      engine:
17:39:37 web.1  |       { clients: [Object],
17:39:37 web.1  |         clientsCount: 2,
17:39:37 web.1  |         pingTimeout: 60000,
17:39:37 web.1  |         pingInterval: 25000,
17:39:37 web.1  |         upgradeTimeout: 10000,
17:39:37 web.1  |         maxHttpBufferSize: 100000000,
17:39:37 web.1  |         transports: [Object],
17:39:37 web.1  |         allowUpgrades: true,
17:39:37 web.1  |         allowRequest: [Function],
17:39:37 web.1  |         cookie: 'io',
17:39:37 web.1  |         ws: [Object],
17:39:37 web.1  |         _events: [Object] } },
17:39:37 web.1  |   sockets:
17:39:37 web.1  |    [ { nsp: [Circular],
17:39:37 web.1  |        server: [Object],
17:39:37 web.1  |        adapter: [Object],
17:39:37 web.1  |        id: 'RfgXeMgHeP_9SQC5AAAC',
17:39:37 web.1  |        client: [Object],
17:39:37 web.1  |        conn: [Object],
17:39:37 web.1  |        rooms: [Object],
17:39:37 web.1  |        acks: {},
17:39:37 web.1  |        connected: true,
17:39:37 web.1  |        disconnected: false,
17:39:37 web.1  |        handshake: [Object],
17:39:37 web.1  |        _events: [Object] },
17:39:37 web.1  |      { nsp: [Circular],
17:39:37 web.1  |        server: [Object],
17:39:37 web.1  |        adapter: [Object],
17:39:37 web.1  |        id: '7TEjGJjWzxObulClAAAD',
17:39:37 web.1  |        client: [Object],
17:39:37 web.1  |        conn: [Object],
17:39:37 web.1  |        rooms: [Object],
17:39:37 web.1  |        acks: {},
17:39:37 web.1  |        connected: true,
17:39:37 web.1  |        disconnected: false,
17:39:37 web.1  |        handshake: [Object],
17:39:37 web.1  |        _events: [Object] } ],
17:39:37 web.1  |   connected:
17:39:37 web.1  |    { RfgXeMgHeP_9SQC5AAAC:
17:39:37 web.1  |       { nsp: [Circular],
17:39:37 web.1  |         server: [Object],
17:39:37 web.1  |         adapter: [Object],
17:39:37 web.1  |         id: 'RfgXeMgHeP_9SQC5AAAC',
17:39:37 web.1  |         client: [Object],
17:39:37 web.1  |         conn: [Object],
17:39:37 web.1  |         rooms: [Object],
17:39:37 web.1  |         acks: {},
17:39:37 web.1  |         connected: true,
17:39:37 web.1  |         disconnected: false,
17:39:37 web.1  |         handshake: [Object],
17:39:37 web.1  |         _events: [Object] },
17:39:37 web.1  |      '7TEjGJjWzxObulClAAAD':
17:39:37 web.1  |       { nsp: [Circular],
17:39:37 web.1  |         server: [Object],
17:39:37 web.1  |         adapter: [Object],
17:39:37 web.1  |         id: '7TEjGJjWzxObulClAAAD',
17:39:37 web.1  |         client: [Object],
17:39:37 web.1  |         conn: [Object],
17:39:37 web.1  |         rooms: [Object],
17:39:37 web.1  |         acks: {},
17:39:37 web.1  |         connected: true,
17:39:37 web.1  |         disconnected: false,
17:39:37 web.1  |         handshake: [Object],
17:39:37 web.1  |         _events: [Object] } },
17:39:37 web.1  |   fns: [],
17:39:37 web.1  |   ids: 0,
17:39:37 web.1  |   acks: {},
17:39:37 web.1  |   adapter:
17:39:37 web.1  |    { nsp: [Circular],
17:39:37 web.1  |      rooms:
17:39:37 web.1  |       { '5MGPNOdO4th_dOuZAAAA': [],
17:39:37 web.1  |         '64rUhxxp--4Qk1MqAAAB': [],
17:39:37 web.1  |         RfgXeMgHeP_9SQC5AAAC: [Object],
17:39:37 web.1  |         '7TEjGJjWzxObulClAAAD': [Object] },
17:39:37 web.1  |      sids:
17:39:37 web.1  |       { RfgXeMgHeP_9SQC5AAAC: [Object],
17:39:37 web.1  |         '7TEjGJjWzxObulClAAAD': [Object] },
17:39:37 web.1  |      encoder: {} },
17:39:37 web.1  |   _events: { connection: [Function] } }

الكود الخاص بي هو:

"" "جافا سكريبت

إذا (game.scoreTeamTwo> game.scoreTeamOne && game.scoreTeamTwo> game.scoreTeamThree && game.scoreTeamTwo> game.scoreTeamFour) {
game.winner = 2 ؛
io.sockets.emit ('CTFEnd' ، لعبة) ؛
}

// إنها تبحث فقط عما إذا كان الفريق 1 قد فاز باللعبة وعندما يحدث ذلك ، يتم إصدار CTFEnd وجميع بيانات اللعبة الأخرى
"" "

التعليق الأكثر فائدة

ربما حدث هذا لأنك كنت تحاول إرسال كائن بمراجع دائرية مما أدى إلى استدعاءات متكررة تجاوزت حجم المكدس.

ال 32 كومينتر

وجدت "حلًا" لمشكلتي. يمكنني إرسال كل قطعة بيانات مفردة ، لكنها لا تعمل مع الكائنات

لقد تلقيت هذا الخطأ مؤخرًا أيضًا ، والفرق الوحيد هو أنه يحدث فقط في بعض الأحيان بالنسبة لي. تم الاختبار طوال الصباح ولم أتمكن من تكرار المشكلة.

بالنسبة لي ، كان الأمر أنه لم يكن قادرًا على الإرسال إلى أي شخص على الإطلاق ، عندما كان الهدف كبيرًا.

BenBals إذا كان الكائن كبيرًا جدًا ، فإن الحل المناسب هو إرساله في شكل سلسلة ، مثل تشغيل JSON.stringify() عليه

حصلت على عمل آخر ، لكنني اعتبرت ذلك.

: البكاء: النظر في هذا

لديه نفس المشكلة عند إصدار كائن من النوع:
{Success: file، content: file.content} حيث file.content هو كائن المخزن المؤقت ، وجميع الخصائص الأخرى للملف هي سلاسل.

اضطر إلى إضافة محتوى الحقل مباشرة إلى الكائنات لأن hasBin () يتحقق فقط من المستوى الأول من الكائن. ولكن عندما حاولت بعد ذلك إرسال المخزن المؤقت ، تم تجاوز الحد الأقصى لمكدس المكالمات

يمكنك تكرار هذا عن طريق إرسال كائن المقبس (بطريقة واحدة على الأقل) لذلك (أدناه سيكون الخادم إلى -> العميل)

socket.emit('crash', {socket:socket});

أنا أشعر بالفضول إذا كان هذا لديه إصلاح حقيقي بالرغم من ذلك.

أي تحديث بشأن هذه المسألة؟
تحرير: كانت مشكلتي أنني كنت أحاول إرسال كائنات متكررة.

ومن المثير للاهتمام ، أنني أتلقى نفس الخطأ عند محاولة تمرير بيانات Firebase إلى جانب العميل.

خطأ

node_modules/socket.io/node_modules/has-binary-data/index.js:46

for (var key in obj) {
                ^
RangeError: Maximum call stack size exceeded

جانب الخادم

var DB = new Firebase('https://1234abcd.firebaseIO.com');
var USERS = DB.child("users");

io.sockets.on('connection', function(socket){

    socket.emit('test', {
        db: USERS
    });

});

العثور على الحل...

آسف ، لكن لغتي الصينية ليست رائعة. هل تتفضل بترجمة هذا إلى الإنجليزية.

فعلت ترجمة جوجل وخرجت إلى "العثور على الحل ..." ... لا يستحق الرد عليه. للتسجيل ، الحل هو عدم تمرير مثل هذا الكم الهائل من البيانات عبر socket.io ... إنه مقبس مصمم للاستجابات السريعة والقصيرة. افصل ردك أو أرسله عبر أياكس. إلغاء الاشتراك في هذا الموضوع.

الشيء الوحيد الذي رمز socket.io يمكن القيام به هو فقط بشكل غير متزامن تكرار الكائن وخصائصه، شيء من هذا القبيل:

var props = [];
var obj = { a: 1, b:2, c: { d: 3, e: 4 } };

function next_prop(callback){
  if (!props.length){
    setTimeout(callback);
    return;
  }
  var prop = props.shift();
  //do whatever with the prop, call parse_obj on it if it's an object
  setTimeout(next_prop);
}

function parse_obj(obj, callback){
  for (var i in obj){
    props.push(i);
  }
  setTimeout(function(){next_prop(callback);});
}

parse_obj(obj);

بالطبع ، هذا ليس رمزًا فعليًا يجب أن تستخدمه ، لأنه يجب أن يكون هناك التفاف للوظائف لكل كائن على حدة في حالة تداخلها ، وإلا فسوف تتعارض مع الكائن الذي يتم تحليله.

لقد تلقيت هذا الخطأ أيضًا ، فشفري يشبه: "io.sockets.emit ('key'، data)؛"
أحاول تبسيط كائن "البيانات" وإبقائه صغيرًا ، وقد نجح الأمر.
- و ، نظرت في كود src ، وجدت هذا:

image_20150306180547

عندما يحتوي كائن "البيانات" الخاص بك على سمة تكرارية ، فإن هذا الرمز سيتعطل.
على سبيل المثال ، proto > proto > proto ...

+1 هل سيعجب الفريق الأساسي بإصدار غير متزامن من الفحص الثنائي يمكنني المساعدة في الحصول على هذا الإعداد

يمكنني إعادة إنتاج المشكلة عن طريق إرسال كائن المقبس :)

يظهر +1 IE11 "خارج مساحة المكدس" في _hasBinary.

ظهر لي هذا الخطأ عندما كنت أحاول إرسال كائن المقبس بالكامل إلى العميل. كل ما أحتاجه حقًا هو socket.id لذا اختفى الخطأ عندما أعدت عنصرًا أصغر - في حالتي ، socket.id بدلاً من الكائن socket بالكامل

ربما حدث هذا لأنك كنت تحاول إرسال كائن بمراجع دائرية مما أدى إلى استدعاءات متكررة تجاوزت حجم المكدس.

تضمين التغريدة شكرا

GerbenHofman على الرحب والسعة

لقد واجهت نفس الخطأ في NodeJS v4.4.4 و socket.io v1.4.5.

في حالتي ، يحدث ذلك بعد حدث قطع الاتصال.
ويحدث ذلك فقط عندما اتصلت بـ socket.emit أكثر من 200000 مرة.

إذا كان عدد المكالمات socket.emit حوالي 100،000 ، فلن يحدث هذا الخطأ أبدًا.

المعلمة التي أستخدمها مع emit هي دائمًا سلسلة نصية

هل هذه المعلومات تساعدك؟

فقط للإضافة إلى shunjikonishi ، رأيت هذا يحدث بمجرد أن أرسلت 100000 حدث بالضبط عبر io.emit. لقد تم توصيل جورب واحد ، لذا يبدو أن 100000 عبارة عن غطاء صلب.

يبدو أن هذا هو الحد الذي تفرضه Node (أو وقت تشغيل JavaScript) ويحتفظ Socket.io بإشارة إلى شيء ما في كل مرة تقوم فيها باستدعاء emit ، لذلك عندما تصل إلى الرقم 100000 ، ينبعث منه فقط.

تم الاختبار مع Node 5.11.0 و Socketio 1.4.8. الإصدار الخاص بي من Node مختلف (بالإضافة إلى نظام التشغيل الخاص بي وما إلى ذلك ، في الحقيقة لا توجد فكرة من أين يأتي هذا 100000) من @ shunjikonishi والذي قد يفسر لماذا وصلت إلى الحد الأقصى عند 100000 بينما حصل على 200000.

لقد قمت بتشغيل نفس الكود باستخدام ws.js وعمل بشكل جيد ، وتجاوز 100000 إصدار من المقبس بدون مشكلة ، لذلك ربما تكون مشكلة في Socket.io.

هل هناك أي فرصة لتطبيق Socket IO لحماية ضد البيانات العودية المنبعثة من هذا الخطأ وفشلها؟ قد يمنع الاكتشاف البسيط حدوث هذا الخطأ ويصدر بدلاً من ذلك خطأ أكثر أهمية ، مثل "ربما تحاول إرسال بيانات دائرية". هذا من شأنه أن يجعل من السهل التصحيح.

هناك عدد غير قليل من الحلول المناسبة لاكتشاف البيانات الدائرية: https://stackoverflow.com/questions/14962018/detecting-and-fixing-circular-references-in-javascript

يعتمد أحد الحلول القصيرة على JSON.stringify للعثور على المشكلة:

function isObjectCircular(obj) {
    try {
        JSON.stringify(circularReference);
    } catch(err) {
        return (err.toString() === 'TypeError: Converting circular structure to JSON');
    }
    return false;
}

مزيد من التفاصيل: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Cyclic_object_value

adamreisnz أنتم مدعوون لإجراء العلاقات العامة ؛)

دائمًا ما يفاجئني عندما يذكرني شخص ما بعد 5 أشهر من إبداء تعليق 😆

التقيت هذا الخطأ أيضا. ولهذا السبب أضيع ساعتين للتحقق من أكوادي بالكامل:
أعتقد أنه ناتج عن كائن عودي مثل A = {B: {C: A}} ، ومن الواضح أن المقبس هو كائن عودي.
في الواقع ، أعتقد أن هذا حدث لأنه في buffer.js ، يستخدمون العودية للعثور على طول البيانات التي تريد إرسالها. ثم احصل على "تجاوز الحد الأقصى لحجم مكدس المكالمات". إذا استخدموا JSON.stringify () للحصول على الطول ، فسيكون هناك خطأ آخر واضح حول "البنية الدائرية". بالمناسبة ، لديها كلمة مفتاحية سيئة لجوجل!

أنا فقط واجهت هذا أيضا.

سوف يملأ hasBin المكدس بحلقة متكررة إذا حاولت إرسال كائن له مرجع دائري.

Shucks ، أرى أن هناك علاقات عامة مفتوحة لمدة عامين من شأنها إصلاح هذا:

dustingraham ،

أيضًا ، حتى إذا لم يتم طرح طريقة hasBinary بعد الآن ، أخشى أن طريقة JSON.stringify التي تم استدعاؤها لاحقًا في الكود ستظل تؤدي إلى حدوث خطأ:

> var a = {};
undefined
> var b = { a: a };
undefined
> a.b = b
{ a: { b: [Circular] } }
> JSON.stringify(a)
Thrown:
TypeError: Converting circular structure to JSON
    at JSON.stringify (<anonymous>)
هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات