Socket.io: لماذا لا يقوم socket.disconnect () على جانب العميل بإطلاق حدث قطع الاتصال على الخادم؟

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

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

جانب العميل

 var socket = io.connect('http://' + serverAddress ,{ reconnection: false, forceNew: true  }  );

 socket.emit('monitorAddedNotify' , { video: sourceVideo , socketId: socket.id});

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

من جانب الخادم:

  io.on('connection', function (socket) {
    console.log('a user connected');


    socket.on('disconnect', function () {
        console.log('user disconnected');
    });
 });

طريقة socket.disconnect () لا تعمل لماذا؟

Unable to reproduce

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

هل انت غبي؟ أنت تنتظر إصدارًا على العميل ولكن لا ينبعث على الخادم. اللعنة من هنا

ال 23 كومينتر

بقدر ما اختبرت ، فهي تعمل بشكل جيد. كيف يمكننا إعادة إنتاج المشكلة؟

حاول إدخال الصفحة وإعادة التحميل السريع عن طريق الضغط على زر F5 عدة مرات.

إنه يعمل بشكل جيد بالنسبة لي أيضًا.

أي متصفح تستخدم؟ أنا أستخدم أحدث إصدار من Firefox وعندما أقوم بإعادة تحميل bage سريعًا ، لا يعمل "المستخدم غير متصل": خائب الأمل:

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

المتصفح: Chrome 55.0.2883.95 (64 بت)
socket.io: "^ 1.7.2"

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

@ giathinh910 ألا يتم تشغيل الحدث disconnect بعد تأخير معين (قد يكون مرتبطًا بخيارات pingTimeout / pingInterval ، موثقة هنا

darrachequesne مشكلتي هي نفسها ventaquil الموصوفة أعلاه "حاول إدخال الصفحة وإعادة التحميل السريع بالضغط عدة مرات على الزر F5". عادة عندما تقوم بتحديث مقبس الصفحة سيطلق اتصال "قطع الاتصال" ثم "الاتصال" مرة أخرى. أعتمد على هذين الحدثين لتحديث أعداد المستخدمين عبر الإنترنت. ومع ذلك ، إذا تمت إعادة تحميل الصفحة بسرعة كافية ، فلن يتم تنشيط "قطع الاتصال" ، مما يؤدي إلى إضافة معرف مقبس مستخدم غير موجود. ستتم إزالة هؤلاء الأشخاص غير الواقعيين بعد pingTimeout بالطبع. حاليًا أقوم بتغيير طريقة حفظ معرف المقبس الذي سيظهر فقط للمستخدم عبر الإنترنت ، وليس رقم المقبس ويمكن حل المشكلة.

لقد تعاملت مع هذه المشكلة بهذه الطريقة. لقد قمت بعمل مرسل يرسل على العميل وهو يتصل بنبضات القلب على الخادم.
socket.on("heartbeat", function() { // console.log('heartbeat called!'); hbeat[socket.id] = Date.now(); setTimeout(function() { var now = Date.now(); if (now - hbeat[socket.id] > 5000) { console.log('this socket id will be closed ' + socket.id); if (addedUser) { --onlineUsers; removeFromLobby(socket.id); try { // this is the most important part io.sockets.connected[socket.id].disconnect(); } catch (error) { console.log(error) } } } now = null; }, 6000); });

لقد وجدت وظيفة الرمز هذه للاتصال:

io.sockets.connected[socket.id].disconnect();

لا يزال هذا يحدث. لا يجب أن يكون F5 / تحديث. يؤدي فتح علامة تبويب وإغلاقها سريعًا في مرحلة معينة إلى عدم بدء فصل الاتصال. من الصعب التكاثر لأن المقابس سريعة جدًا ، خاصة عند التشغيل محليًا. لاحظت أن فتح علامة التبويب في الخلفية وفتح علامات تبويب أخرى ساعد في إعادة إنتاج المشكلة (محليًا). أعتقد أن هذا خطأ مهم يجب معالجته.

وجود نفس المشكلة هنا. هذا هو إنشاء ألعاب أشباح على خادم اللعبة الخاص بي

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

العميل :

function ManualSocketDisconnect() {
    socket.emit("manual-disconnection", socket.id);

    socket.close();

    console.log("Socket Closed. ");
}

الخادم :

io.on("connection", function(socket) {
    console.log("User " + socket.id + " Connected. ");

    socket.on("manual-disconnection", function(data) {
        console.log("User Manually Disconnected. \n\tTheir ID: " + data);
    });
});

آسف ، ولكن ربما تركت بعض الثغرات في الكود الخاص بي. أنا لست محترفًا. 🙁

أواجه نفس المشكلة!
سأعطي المثال في ReactJS-ExpressJS.

هذا هو الموقف الذي سينطلق الحدث ، ومغلف بـ componentWillUnmount() .

سأقوم بمقارنة حدثين ، والذي سأطلقهما من componentWillUnmount()

  1. newMessage : - سيؤدي هذا إلى بث الرسالة إلى غرفة معينة
  2. disconnect :- (كنت آمل أن ينجح الأمر ، لكنه لا يعمل) قام مستمع الحدث هذا بإعادة الاتصال والذي سينقطع الاتصال. لقد احتوت على console.log() فقط لتأكيد ما إذا كانت معاودة الاتصال تصل.

الآن ، ها نحن ذا: -
عميل:-

يتم إطلاق هذه الأحداث: -

  componentDidMount() {
    console.log(this.props)
    chat.emit('authenticate', {
      token: localStorage.getItem('auth'),
      refreshToken: localStorage.getItem('refresh'),
      projectId: this.props.projectId,
      userId: this.props.userId,
    });
    chat.on('newMessage', (messageData) => {
      console.log('------------newMessageReceived-------------');
      this.props.messageReceived({ messages: this.props.messages, messageData }, () => {
        console.log('callback');
        this.setState({
          messages: this.props.messages
        })
      })
      console.log(messageData);
    })
  }

لن يتم إطلاق الحدث التالي.

  componentWillUnmount() {
    chat.emit('disconnect','just disconnect);
  }

سيتم تشغيل الحدث التالي. (مجرد اختبار ما إذا كان حدث الرسائل العادية ينبعث)

  componentWillUnmount() {
    chat.emit('newMEssage', {
      messageHeader: {
        sender: {
          user: {
            id: this.props.userId,
            name: this.props.name
          }
        }
      },
      messageBody: 'hello',
    });
  }

لا حظ

الخادم:-
هذا هو الكود في الواجهة الخلفية ExpressJS

// بعد التهيئة ، يتم استدعاءChatSocket في app.js

function initializeChatSocket(server) {
  projects.hasMany(projectTeam, { foreignKey: 'projectId' });

  const io = socketIO(server);
  const chat = io.of('/chat').on('connection', function (socket) {
    console.log(
      '----------------------------------------New Chat Connection Established-------------------------------------------------------------------------'
    );

    socket.auth = false;

    socket.on('authenticate', function (data) {
      console.log('\n\n\n\n', 'authenticate called', '\n\n\n\n', data, '\n\n\n');

      try {
        const dummyReq = {
          headers: {
            refreshtoken: data.refreshToken,
          },
        };
        console.log('\n\n\n\n', 'before verify', '\n\n\n\n');
        const userDetails = verifyJWTToken(dummyReq, data.token);
        console.log('\n\n\n\n', 'after verify', '\n\n\n\n');
        socket.userId = userDetails.userId;
        socket.projectId = data.projectId;

        projectTeam
          .findAll({
            where: {
              [Op.and]: {
                projectId: data.projectId,
                userId: data.userId,
              }
            }
          })
          .then(projects => {
            console.log('\n\n\n\n', JSON.stringify(projects), '\n\n\n\n');
            if (projects.length === 1) {
              socket.auth = true;
              socket.join(socket.projectId);
              console.log('User id:- ${userDetails.userId} linked to project id :- ${socket.projectId}');
            } else {
              console.log('User id:- ${userDetails.userId} not linked to project id :- ${socket.projectId}');
              throw { message: 'User not linked to project' };
            }
          });
      } catch (error) {
        console.log(String(error));

        socket.auth = false;
        socket.disconnect(String(error));
      }
    });

    socket.on('disconnectt', function() {
      console.log('Client Disconnecting'); // This is not being fired :/
      socket.removeAllListeners('newMessage');
      socket.removeAllListeners('disconnect');
      socket.removeAllListeners('authenticate');
      socket.removeAllListeners('connection');
      });

    socket.on('newMessage', async function (messageData) {
      console.log('-------------------------New Message----------------------', String(messageData));
      //TODO Save Message in Database

      try {
        socket.broadcast.to(socket.projectId).emit('newMessage', messageData);
        console.log('\n\n\n\n\n broadcast sent\n\n' + JSON.stringify(messageData) + '\n\n\n');
      } catch (error) {
        console.log('\n\n\n\n\n broadcast error\n\n\n\n\n');
        console.log(String(error));

        console.log(error);
        //TODO Handle Message Sending Error
      }
    });

  });
}

هل هذه مشكلة تتعلق بالمتصفح أو أي شيء آخر أحتاج أن أسأله من مجتمع Stack-overflow؟

manjotsk لست متأكدًا مما إذا كنت قد أصلحته الآن ، ولكن على الكود الجانبي للخادم ، فأنت تستمع لـ disconnectt (لاحظ المضاعفة t ) ولكن الواجهة الأمامية تصدر disconnect . أيضًا ، ربما لا تريد إرسال disconnect حيث من المفترض أن يتم إرسال هذا الحدث من العميل إلى الخادم عند قطع اتصال العميل.

لدي رمز يعتمد على المقبس الذي ينبعث منه حدث قطع الاتصال لمنع تكرار ips - يتم حظر المستخدمين الذين يعيدون تحميل تطبيقي بسرعة لأن قطع الاتصال لا ينطلق أبدًا!

manjotsk لست متأكدًا مما إذا كنت قد أصلحته الآن ، ولكن على الكود الجانبي للخادم ، فأنت تستمع لـ disconnectt (لاحظ المضاعفة t ) ولكن الواجهة الأمامية تصدر disconnect . أيضًا ، ربما لا تريد إرسال disconnect حيث من المفترض أن يتم إرسال هذا الحدث من العميل إلى الخادم عند قطع اتصال العميل.
كان disconnectt اسمًا مستعارًا لمحتال كنت أستخدمه! شكرا لك على الإشارة. سأعيد التحقق من هذا على كلا الجانبين. ومن الواضح أن التنفيذ كان خاطئًا! حصلت على رؤية أوضح! شكرا nathanheffley 👍 :)

@ manjotsk ماذا؟

واستخدم فقط socket.once بدلاً من ذلك socket.on
"مستوى العميل".
مثال:
socket.on ("connect")
استعمال
socket.once ("connect")
.

نفس هنا بلدي
socket.on ("message") {(dataArray، socketAck) -> Void in

  if let data = dataArray.first as? Data{
    do{
      let objc = try JSONDecoder.init().decode(GetChatConversation.self, from: data)
      completionHandler(objc,nil)
    }
    catch let error{
      return completionHandler(nil,error.localizedDescription)
    }
  }else{
    completionHandler(nil,"Cannot cast Array of Any to Data")
  }
}

لا تعيد الاتصال إذا كان أحد يعرف يخبرني

هل انت غبي؟ أنت تنتظر إصدارًا على العميل ولكن لا ينبعث على الخادم. اللعنة من هنا

هذه بعض الطاقة السلبية الحقيقية ، إحسان 666x.

لقد تعاملت مع هذه المشكلة بهذه الطريقة. لقد قمت بعمل مرسل يرسل على العميل وهو يتصل بنبضات القلب على الخادم.
hbeat [socket.id] = Date.now () ،

أتساءل ما هي hbeat التي يجب إرسالها من جانب العميل؟

بدلاً من socket.disconnect() أو socket.emit('disconnect') جرب socket.close(); في جانب العميل ويجب أن يؤدي ذلك إلى تشغيل الحدث 'disconnect' على جانب الخادم. عملت معي.

هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات