Socket.IO จัดการเหตุการณ์ตัดการเชื่อมต่อ


90

ไม่สามารถจัดการกับเหตุการณ์ตัดการเชื่อมต่อนี้ไม่รู้ว่าทำไมซ็อกเก็ตไม่ส่งไปยังไคลเอนต์ / ไคลเอนต์ไม่ตอบสนอง!

เซิร์ฟเวอร์

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

  socket.on('NewPlayer', function(data1) {

    online = online + 1;
    console.log('Online players : ' + online);
    console.log('New player connected : ' + data1);
    Players[data1] = data1;
    console.log(Players);

  });

  socket.on('DelPlayer', function(data) {

    delete Players[data];
    console.log(Players);
    console.log('Adios' + data);

  });

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

      socket.emit('disconnected');
      online = online - 1;

  });

});

ลูกค้า

 var socket = io.connect('http://localhost');

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

        person_name = prompt("Welcome. Please enter your name");

        socket.emit('NewPlayer', person_name);

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

            socket.emit('DelPlayer', person_name);

        });

    });

ดังที่คุณเห็นเมื่อไคลเอ็นต์ยกเลิกการเชื่อมต่อ Array object [person_name] ควรถูกลบ แต่ไม่ใช่


คุณควรลองวิธีอื่นก่อนอื่นให้ลบเครื่องเล่นจากนั้นยกเลิกการเชื่อมต่อ เนื่องจากเมื่อคุณยกเลิกการเชื่อมต่อจากเซิร์ฟเวอร์เซิร์ฟเวอร์จะไม่สามารถรับเหตุการณ์ที่ไคลเอ็นต์ปล่อยออกมาได้ ติดตามซ็อกเก็ตมากกว่าผู้เล่นซึ่งคุณสามารถลบผู้เล่นได้อย่างง่ายดาย
code-jaff

ฉันจะลบเครื่องเล่นแล้วตัดการเชื่อมต่อได้อย่างไร? ฉันจะรู้ได้อย่างไรว่าเมื่อใดที่เครื่องเล่นจะตัดการเชื่อมต่อ?.
Raggaer

4
ไม่ควรจัดงานในไคลเอนต์'disconnect'แทน'disconnected'หรือไม่?
Sherlock

1
@Sherlock ในรหัสไคลเอนต์ดั้งเดิมของ OP พวกเขาพยายามที่จะฟังเหตุการณ์ที่กำหนดเองซึ่งพวกเขากำลังเรียกใช้เซิร์ฟเวอร์ไซด์สำหรับตรรกะที่ตัดการเชื่อมต่อ 'ตัดการเชื่อมต่อ' เป็นเหตุการณ์ตัดการเชื่อมต่อในตัว แต่ไม่ได้มีส่วนโดยตรงต่อปัญหาที่พบ
Jon Church

คำตอบ:


173

โอเคแทนที่จะระบุผู้เล่นด้วยแทร็กชื่อด้วยซ็อกเก็ตที่พวกเขาเชื่อมต่อ คุณสามารถใช้งานได้เช่น

เซิร์ฟเวอร์

var allClients = [];
io.sockets.on('connection', function(socket) {
   allClients.push(socket);

   socket.on('disconnect', function() {
      console.log('Got disconnect!');

      var i = allClients.indexOf(socket);
      allClients.splice(i, 1);
   });
});

หวังว่านี่จะช่วยให้คุณคิดในอีกแง่หนึ่ง


92
ใช้allClients.splice(i, 1)ลบองค์ประกอบได้ดีกว่า delete allClients[i]จะตั้งค่าตำแหน่งอาร์เรย์เป็นundefined
Yves

1
ทำไมมันถึงใช้งานได้ แต่การติดตามคนที่มีชื่อของพวกเขาไม่ทำงาน?
sha1

นี่ใช้ไม่ได้สำหรับฉัน นี่iมีค่า -1 ทุกครั้ง บอกได้ไหมว่าเกิดอะไรขึ้น.
Vinit Chouhan

1
@VinitChouhan คุณควรถามคำถามแยกกับปัญหาที่แท้จริงของคุณ
code-jaff

เมื่อคุณได้ค่า -1 หมายความว่าคุณกำลังพยายามต่อซ็อกเก็ตที่ไม่มีอยู่ (มีคนตัดการเชื่อมต่อ แต่คุณยังไม่ได้ลงทะเบียนบุคคลนั้นในallClientsอาร์เรย์ของคุณ) ฉันขอแนะนำให้คุณกลับมา: if (i === -1)return;ก่อนที่จะลองประกบมัน
Koen B.

23

สำหรับผู้ที่ชอบ @ sha1 สงสัยว่าทำไมรหัสของ OP ไม่ทำงาน -

ตรรกะของ OP ในการลบผู้เล่นที่ฝั่งเซิร์ฟเวอร์อยู่ในตัวจัดการสำหรับDelPlayerเหตุการณ์และรหัสที่ปล่อยเหตุการณ์นี้ ( DelPlayer) อยู่ในการdisconnectedเรียกกลับเหตุการณ์ของไคลเอนต์

รหัสฝั่งเซิร์ฟเวอร์ที่ปล่อยdisconnectedเหตุการณ์นี้อยู่ในการdisconnectเรียกกลับเหตุการณ์ซึ่งจะเริ่มทำงานเมื่อซ็อกเก็ตสูญเสียการเชื่อมต่อ เนื่องจากซ็อกเก็ตขาดการเชื่อมต่อdisconnectedเหตุการณ์จึงไม่สามารถเข้าถึงไคลเอ็นต์ได้


โซลูชันที่ยอมรับจะรันตรรกะในdisconnectเหตุการณ์ที่ฝั่งเซิร์ฟเวอร์ซึ่งจะเริ่มทำงานเมื่อซ็อกเก็ตตัดการเชื่อมต่อจึงใช้งานได้


6

สร้างแผนที่หรือชุดและใช้เหตุการณ์ "เชื่อมต่อ" ที่ตั้งไว้กับซ็อกเก็ตที่เชื่อมต่อแต่ละซ็อกเก็ตที่เชื่อมต่อในทางกลับกันเหตุการณ์ "เมื่อตัดการเชื่อมต่อ" ลบซ็อกเก็ตนั้นออกจากแผนที่ที่เราสร้างไว้ก่อนหน้านี้

import * as Server from 'socket.io';

const io = Server();
io.listen(3000);

const connections = new Set();

io.on('connection', function (s) {

  connections.add(s);

  s.once('disconnect', function () {
    connections.delete(s);
  });

});

1
และใคร ๆ ก็คาดหวังคำตอบโดยละเอียดพร้อมคำอธิบายและความคิดเห็นจากทหารผ่านศึก แต่ฉันเดาว่าเราต้องจัดการกับรหัสเพียงชุด
Cemal

แจ้งให้เราทราบหากคุณมีคำถามฉันจำไม่ได้ว่าเขียนคำตอบ
Alexander Mills

1
ที่จริงฉันไม่มีคำถามใด ๆ เป็นเพียงการวิจารณ์เชิงสร้างสรรค์สำหรับผู้เขียนซึ่งรู้ดีกว่าที่จะใช้ความคิดเห็นและวางคำอธิบายในคำตอบเพื่อให้ทุกคน (อย่างน้อยที่สุด) เข้าใจตัวอย่างของคุณโดยไม่ทำให้คุณเสีย สวัสดีปีใหม่ครับ ..
Cemal

0

นอกจากนี้คุณยังสามารถใช้รหัสซ็อกเก็ตเพื่อจัดการรายชื่อผู้เล่นได้เช่นนี้

io.on('connection', function(socket){
  socket.on('disconnect', function() {
    console.log("disconnect")
    for(var i = 0; i < onlineplayers.length; i++ ){
      if(onlineplayers[i].socket === socket.id){
        console.log(onlineplayers[i].code + " just disconnected")
        onlineplayers.splice(i, 1)
      }
    }
    io.emit('players', onlineplayers)
  })

  socket.on('lobby_join', function(player) {
    if(player.available === false) return
    var exists = false
    for(var i = 0; i < onlineplayers.length; i++ ){
      if(onlineplayers[i].code === player.code){
        exists = true
      }
    }
    if(exists === false){
      onlineplayers.push({
        code: player.code,
        socket:socket.id
      })
    }
    io.emit('players', onlineplayers)
  })

  socket.on('lobby_leave', function(player) {
    var exists = false
    for(var i = 0; i < onlineplayers.length; i++ ){
      if(onlineplayers[i].code === player.code){
        onlineplayers.splice(i, 1)
      }
    }
    io.emit('players', onlineplayers)
  })
})
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.