Socket.io: مآخذ متعددة مفتوحة بعد إعادة الاتصال

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

لقد لاحظت هذا في تطبيق socket.io الخاص بي وفي تطبيق شخص آخر. عند حدوث إعادة الاتصال ، من الشائع أن يتم فتح أكثر من مقبس داخل العميل ، وهو ما لا يجب أن يحدث أبدًا.

هذا سجل حصلت عليه من تطبيق الاختبار الخاص بي عندما كان لدي قطع / إعادة الاتصال.

** قطع الاتصال* * إعادة الاتصال مع تأخير 1000 محاولة: 1
** إعادة الاتصال مع تأخير 2000 محاولات: 2* * الاتصال مع الاستقصاء xhr
** التواصل مع الاستقصاء xhr* * إعادة الاتصال بنوع النقل xhr- المحاولات: 2
** متصل* * متصل

عندما يحدث هذا ، أحصل على رسائل مكررة مرسلة ، واحدة لكل مقبس متصل ، على الرغم من أنه يجب أن يكون هناك واحد فقط. أكد Firebug أن هناك ، في الواقع ، مآخذ توصيل من العميل. أفضل تخميني هو أن هذا موجود في رمز العميل ، وربما لا يتم إغلاق محاولة إعادة الاتصال الأولى.

بالطبع ، قد يكون السؤال الحقيقي هو لماذا كان هناك انقطاع في المقام الأول؟

Socket.IO client bug

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

بعد التحقيق في هذا الأمر قليلاً ، يبدو أنني وجدت سبب مشاكلي. إنه ليس خطأ ، ولكنه تنفيذ خاطئ للرمز من جانب العميل من جانبي. فيس بالم وهذا ما كان في الأصل:

مشكلة:

var socket = io.connect();

socket.on('connect', function () {

  console.log('User connected!');

  socket.on('message', function(message) {

    console.log(message);

  });

});

تسبب JavaScript من جانب العميل أعلاه في إجراء مكالمات متعددة إلى console.log () عند إعادة اتصال العميل (العملاء). هذا ما استبدلت به أعلاه بـ:

المحلول:

var socket = io.connect();

socket.on('connect', function () {

  console.log('User connected!');

});

socket.on('message', function(message) {

  console.log(message);

});

الآن ، لا يتم إرسال رسائل متعددة ذهابًا وإيابًا عند إعادة اتصال العملاء بالخادم. هل يمكن لأي شخص آخر تأكيد أن تغيير الرمز من جانب العميل يؤدي إلى حل المشكلة؟

ال 54 كومينتر

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

لكن الباقي حشرة.

أعتقد أن هذا هو سبب وجود خطأ في طلبي أيضًا -

على جانب الخادم ، قمت بإنشاء مؤشر قابل للإمالة على mongodb لإطلاقه في كل مرة يوجد فيها إدخال جديد. ثم يتم إرسال هذه الرسالة عبر io.sockets.emit () إلى كل شخص متصل.

ولكن بدلاً من تلقي رسالة واحدة فقط لكل حدث ، أحصل على رسائل متكررة متعددة من جانب العميل.

أنا على اتصال إنترنت غير موثوق به للغاية ، لذا أعتقد أن هذا الخطأ يؤثر على الكود الخاص بي أيضًا.

هل كنتم تستخدمون Expressjs؟ واجهت هذه المشكلة مع التعبير السريع ، وأعدت كتابتها بدونها وعملت بشكل جيد.

لن يكون لـ Express أي علاقة على الإطلاق بهذا mfkp ، لا بد أنه كان يفعل شيئًا غريبًا

متفق عليه مع visionmedia ، إنه خطأ في socket.io وليس مع Express. نظرًا لأن تنفيذ إعادة الاتصال الحالي كان لا يزال مصممًا لـ 0.6 ، لذلك فقد بعض عمليات الفحص والتنظيف.

آه لقد فهمت. لا تهتم ، استمر ؛-)

+1 لهذا. مشكلة متقطعة في تطبيق الدردشة حيث يفتح socket.io اتصالات متعددة. ثم يتلقى العميل المغفلين من جميع المنبعث.

+1. مآخذ الويب والكروم. يذهب الكمبيوتر المحمول إلى وضع السكون -> يعيد التطبيق الاتصال بعد الاستيقاظ -> الأحداث المزدوجة. يحدث فقط عند الاتصال بالخادم البعيد. لا يمكن إعادة إنتاج هذا محليًا ، يجب أن يكون هناك مشكلة في إعادة الاتصال / زمن انتقال الشبكة.

هل هناك أي حل بديل للتخلص من الاتصال المتعدد بعد ذلك ؟، على سبيل المثال من جانب العميل ، إذا قمت بفصل socket.disconnect () ، فهل سيفصل جميع الاتصالات؟ لأنني أريد تجنب تحديثات متعددة. هل متابعة العمل؟
مقبس = io.connect (url)
socket.on ('connect'، function () {
إذا (اتصال متعدد) {
socket.donnect () ؛
socket.removeAllListeners ('connect') ؛
io.sockets = {} ؛
المقبس = io.connect (url) ؛
socket.on ('connect'، functionToConnect) ؛
}
})

من فضلك ، اقرأ هذا https://github.com/LearnBoost/socket.io/issues/474#issuecomment -2833227.
يشرح سبب حدوث هذا الخطأ وكيف يمكن إعادة إنتاجه.

@ 3rd-Eden - أي فكرة حيث يقع هذا الإصلاح في قائمة المهام / أولوياتك؟ لدي تطبيق أقوم ببنائه وكنت أخطط لاستخدامه من أجله ، وأود أن أكون قادرًا على إخبار عميلي بأنه سيعيد الاتصال بشكل صحيح من أجهزة iOS. يتم قطع الاتصال بعد وضع التطبيق في الخلفية أو وضع الجهاز في وضع السكون.

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

شكر!

cris لست متأكدًا من أن هذا هو نفس الخطأ الذي

يمكنني إعادة إظهار هذه المشكلة بوضوح من خلال:

  1. قم بتطبيق عميل نبضات بسيط يرسل دقات القلب على فترات زمنية تبلغ ثانية واحدة.
  2. عد عدد الاتصالات الجديدة من جانب الخادم.
  3. حساب عدد حالات قطع الاتصال من جانب الخادم.
  4. ابدأ الخادم وقم بإجراء اتصال مع العميل.
  5. قطع اتصال الشبكة بين العميل والخادم.
  6. انتظر حتى تنتهي مهلة الخادم ويصدر حدث قطع الاتصال.
  7. أعد توصيل اتصال الشبكة.

لاحظ أنه عندما يعيد العميل الاتصال فإنه ينشئ 2-4 اتصالات ينبعث منها حدث "اتصال" لكل منها. يتلقى الخادم 2-4 اتصالات من العميل ويصدر حدث اتصال لكل منها. لا يقوم العميل أبدًا بإغلاق أي من الاتصالات التي تم تشغيلها بشكل غير صحيح.

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

davidfooks ، theyak. لقد أصلحت هذه المشكلة بالنسبة لي منذ فترة طويلة ، وهي تعمل دون ضجة.

لإصلاح ذلك ، يجب عليك:

  1. قم بتطبيق هذا التصحيح: https://github.com/LearnBoost/socket.io-client/pull/342
  2. قم بتعطيل AJAX-handshake (ودع المصافحة تكون فقط عبر JSONP) ، كما هو موضح في تعليق طلب السحب.

كيف تقوم بتعطيل مصافحة AJAX؟ أفترض أنه لا يزال بإمكانك استخدام جميع أنواع الاتصال ، فهذا سيؤثر فقط على المصافحة؟

+1 الرجاء إصلاح هذا :)

كان لدي نفس الاتصال المتعدد في مشكلة إعادة الاتصال. أعتقد أن هذه قضية خطيرة ...
والسبب هو أنه يتم استدعاء طريقة Socket.connect ولكن يتم تعيين علامة conneting فقط على true بعد اكتمال المصافحة ، في حالة استيقاظ أحد أجهزة ضبط الوقت matbeReconnect (أجهزة ضبط الوقت التي تتعامل مع إعادة الاتصال) أثناء عملية المصافحة ، فسيتم استدعاء مقبس. الاتصال مرة أخرى مما تسبب في إعادة الاتصال متعددة.
لقد قمت بحل المشكلة عن طريق استدعاء self.reconnecting في بداية طريقة Socket.connect.

أي فرصة لدمج هذا؟
هذا الخطأ يسبب خطأ سيئًا في تطبيقي أيضًا.

هذا الخطأ لا يزال موجودا. حاولت كلا البقع. لا نجاح.

+1 لدي هذه المشكلة كثيرًا باستخدام الاستقصاء xhr لم أجرب التصحيحات بعد

+1 ، لدي أيضًا هذه المشكلة مع عمليات إعادة الاتصال المكررة.

عندما يتم إعادة تشغيل Node.js (أي عند التشغيل من خلال المشرف) ، يقوم موكلي (عملائي) بإعادة الاتصال X أضعاف عدد المرات التي تم فيها إعادة تشغيل Node.js من النقطة التي تم فيها توصيل العميل (العملاء) في البداية. يتسبب الخطأ في إصدار الأحداث مرة واحدة لكل إعادة اتصال من جانب العميل - هذه ليست مجرد مسألة تكرار.

لقد حاولت socket.on('disconnect', function() { socket.disconnect(); }); جانب العميل ، لكن هذا لا يعمل. : /

بعد التحقيق في هذا الأمر قليلاً ، يبدو أنني وجدت سبب مشاكلي. إنه ليس خطأ ، ولكنه تنفيذ خاطئ للرمز من جانب العميل من جانبي. فيس بالم وهذا ما كان في الأصل:

مشكلة:

var socket = io.connect();

socket.on('connect', function () {

  console.log('User connected!');

  socket.on('message', function(message) {

    console.log(message);

  });

});

تسبب JavaScript من جانب العميل أعلاه في إجراء مكالمات متعددة إلى console.log () عند إعادة اتصال العميل (العملاء). هذا ما استبدلت به أعلاه بـ:

المحلول:

var socket = io.connect();

socket.on('connect', function () {

  console.log('User connected!');

});

socket.on('message', function(message) {

  console.log(message);

});

الآن ، لا يتم إرسال رسائل متعددة ذهابًا وإيابًا عند إعادة اتصال العملاء بالخادم. هل يمكن لأي شخص آخر تأكيد أن تغيير الرمز من جانب العميل يؤدي إلى حل المشكلة؟

مرحبا. كان لي نفس القضية. عندما كنت أقوم بإعادة تشغيل العقدة (أو عندما انتهت مهلة الاتصال) وأعاد العميل الاتصال ، كنت أتلقى نفس الرسالة التي أرسلها الخادم بحلول n مرة (حيث كان n هو عدد مرات إعادة الاتصال).
لقد قمت بحل هذا عن طريق تحريك كل معالجاتي من داخل socket.on (وظيفة 'connect' () {...})؛ تعمل خارجها.

الكود أعلاه يفعل ما يتطلبه الأمر.
هذا هو إجابتي الكاملة من القائمة البريدية:
https://groups.google.com/forum/؟hl=ar&fromgroups#!topic/socket_io/X9FRMjCkPco

xdanx ، رائع ، شكرًا على الرد.

نعم ، يبدو أن هذا يعمل بالنسبة لي أيضًا: وضع رمز socket.on ('message') منفصلاً عن رمز حدث 'connect'

ولكن ماذا عن "الاتصال"؟
وماذا عن كائن "المقبس" في رد الاتصال؟

/ edit Nevermind ، أرى أن "connect" موجود على العميل. كنت لا أزال أواجه مشكلة في إعادة الاتصال بالبريد العشوائي عندما لم أفعل ذلك. لكن ذلك كان عند 0.9.6

يبدو أن لدي نفس المشكلة أيضًا ... حاولت الإصلاح السابق لنقل رمز الرسالة إلى كتل منفصلة .. لكن لاحظت أنني لم أحصل عليه معًا.

أي أخبار عن طرق عمل أخرى لهذا في 0.9.8؟

لدي نفس المشكلة. لدي 0.9.10 مثبتة. هل يوجد طريقه لاصلاح هذا؟ :(
راجع للشغل لقد مر أكثر من عام ولا يوجد إصلاح حتى الآن .. :(

تعديل.

يبدو أن المشكلة قد ولت عندما أستخدم استقصاء jsonp فقط.
io.set ('النقل'، ['استقصاء jsonp'])؛

لدي نفس المشكلة.
قابس كهرباء. [email protected]
عقدة v0.8.8

semprom أعتقد أن استخدام jsonp-polling يعمل على إصلاحه لأنه قد يكون متعلقًا باتصالات websocket فقط.

لسوء الحظ بالنسبة لي ، يعتمد نوع التنفيذ الكامل الخاص بي على أن تكون التعليقات سريعة قدر الإمكان ، لذلك تعمل مآخذ الويب على عكس الاقتراع بشكل أفضل ، وبما أنني أتحكم في العملاء المتصلين ، لا أرى أي سبب سوى انتقال هذه المشكلة إلى أي شيء آخر.

لاحظ أن الاتصالات المتعددة من نفس العميل التي تقوم بإعادة الاتصال لها نفس socket.id . لذا يمكنك الاحتفاظ بقائمة معرفات مأخذ التوصيل الخاصة بك وتجاهل التكرارات لحل هذه المشكلة.

KasperTidemann شكرا. لقد حلت هذه المشكلة.

esanai لا مشكلة ، سعيد أنها عملت!

مرحبًا ، لدي نفس المشكلة ولاحظت أنه في كل مرة يتم فيها إعادة الاتصال ، يتم إنشاء معرف مقبس عميل جديد. الحل هو إما استخدام io.set ('transports'، ['jsonp-polling'])؛ أو استخدام حل KasperTidemann؟

KasperTidemann يا إلهي ، هذا هو بالضبط الجواب على مشاكلي! راجع هذا الالتزام: https://github.com/samuelclay/NewsBlur/commit/76cb”d8b2a787985bba724dc3562108492b017#L2L3887

يمكنني إعادة إنتاج حدث اتصال مزدوج بعد حدوث خطأ في الاتصال حسب الرغبة باستخدام رمز الخادم والعميل البسيط هذا في ملف node.js واحد:

"use strict";

var server = require('socket.io');
var client = require('socket.io-client');

setTimeout(function () {
    var io = server.listen(8888);

    io.of('/chat').on('connection', function (socket) {
        console.log('Server: /chat connection');
        socket.emit('greeting', 'Hello, who are you?');
    });

    io.sockets.on('connection', function (socket) {
        console.log('Server: connection');
    });
}, 2000);

var socketAddress = 'http://localhost:8888/chat';
var socket = client.connect(socketAddress);

socket.on('connect', function () {
    console.log("Client: connect");
});

socket.on('greeting', function (data) {
    console.log("Client: greeting: ", data);
});

socket.on('error', function () {
    console.log("Client: error");
    socket.socket.reconnect();
});

أي عمل جولات أو إصلاحات في الأفق؟

آسف ، لقد نشرت هذا أيضًا في الإصدار رقم 474.

يمكنني إعادة إنتاج هذا الخطأ باستمرار باستخدام iPhone مع iOS 9.3.2 و Chrome الإصدار 50.0.2661.95 وعلى Safari لنظام iOS مع الإصدار 1.4.6 من Socket.IO

أنا قادر فقط على إعادة إنتاج هذا على الهاتف المحمول ويعلق صفحتي عند طلب socket.io.

لدي بسيط on ('connect'، function (socket) {console.log ('Connected')؛})؛ ويقوم بتسجيل الاتصال مرتين عند حدوث الخطأ مما يقودني إلى الاعتقاد بأنه يحاول فتح اتصالات مقابس متعددة في نفس الوقت.

screenshot 2016-05-27 13 03 44

لا أحد يعرف حلا لهذه؟

لماذا تم اغلاق هذا الموضوع ؟؟

لم يعد رمز المثال الخاص بي بتاريخ 14 أبريل 2014 أعلاه ينتج أحداث اتصال مزدوجة. يوجد حدث اتصال لـ "/ chat" وآخر للمقبس نفسه. الذي يبدو معقولا.

لم يعد هناك خطأ حتى في العميل بعد الآن.

هذا مع socket.io 1.4.8 و node 6.3.0.

هذا الخطأ يؤثر علي أجهزة الصراف الآلي.

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

leemlwando يرجى فتح مشكلة جديدة إذا لزم الأمر.

واجهت نفس المشكلة التي فعلتها وهي إنشاء وظيفة إعادة الاتصال اليدوي على العميل واستدعاء io.destroy () ؛ داخل وظيفة إعادة الاتصال ، أدى هذا إلى حل المشكلة.

شكرًا جزيلاً leemlwando لقد جعل تعليقك الأخير يحل أشيائي.

ما زلت أتلقى هذا الخطأ ، هل هناك أي تحديث؟

أعتقد أن الخطأ الحقيقي الوحيد هنا هو أن الإنترنت مليء برموز أمثلة سيئة حيث يتم تغليف مكالمات socket.on () داخل معالج socket.on ('connect'). في كل مرة يعيد فيها المقبس الاتصال ، يتم تكديس مثيلات جديدة من المعالجات فوق مثيلاتها الحالية وهذا يؤدي إلى مكالمات متعددة عند كل حدث. لا تفعل هذا: انظر ردKasperTidemann من 25 يوليو 2012.

ربما أظهر DrLexO ، باستثناء الكود الذي قدمته أعلاه ، المشكلة. لا يحتوي على socket.on () ملفوف داخل أي معالج socket.on ('connect').

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

KasperTidemann شكرًا ، لقد حل المشكلة بالفعل.

كيف يمكنك تحديد مستمعي الحدث الخاص بك _ خارج_ من المستمع connect عندما لا يكون لديك حق الوصول إلى socket ؟

const app = express();
const http = require('http').createServer(app);
const io = require('socket.io')(http);

io.on('connect', function(socket) {

  // only now that we are inside the connect callback do we have access to the socket

  socket.on('join', function(room, user) {
  });

  socket.on('add_message', function(room, user) {
  });

  socket.on('disconnect', function(room, user) {
  });
});

يبدو أن الناس يقترحون أن مستمعي الحدث ( join ، add_message و disconnect ) يجب أن يعيشوا بشكل مستقل ، _ في الخارج _ المستمع connect ، لكن كيف يمكن ذلك بدون يتم تعريف socket ؟

io.on('connect', function(socket) {
  // socket is only available here
});

// socket is undefined here

socket.on('join', function(room, user) {
});

socket.on('add_message', function(room, user) {
});

socket.on('disconnect', function(room, user) {
});

هل هناك طريقة مختلفة لإنشاء مثيل socket حتى يكون ذلك ممكنًا؟

لماذا هذا مغلق؟ @ michael-lynch لديه نقطة صحيحة

أود أيضًا أن أعرف الإجابة على وجهة نظر @ michael-lynch.

@ DrLex0 على مثال موقع الويب socket.io حتى أنه يظهر للقيام بما يلي:

io.on('connection', function(socket){
  socket.on('chat message', function(msg){
    io.emit('chat message', msg);
  });
});
هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات