Socket.IO xử lý sự kiện ngắt kết nối


88

Không thể xử lý sự kiện ngắt kết nối này, không biết tại sao ổ cắm của nó không gửi đến máy khách / máy khách không phản hồi!

Người phục vụ

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;

  });

});

Khách hàng

 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);

        });

    });

Như bạn có thể thấy khi máy khách ngắt kết nối đối tượng Array [tên_người] sẽ bị xóa, nhưng nó không


Tốt hơn bạn nên thử cách khác, trước tiên hãy xóa trình phát sau đó ngắt kết nối. Bởi vì khi bạn đã ngắt kết nối khỏi máy chủ, máy chủ sẽ không thể nhận sự kiện mà máy khách phát ra. Theo dõi ổ cắm thay vì đầu phát, nhờ đó bạn có thể gỡ bỏ đầu phát dễ dàng.
code-jaff

Làm cách nào để xóa trình phát và sau đó ngắt kết nối? làm cách nào để biết khi nào người chơi sẽ ngắt kết nối ?.
Raggaer

4
không nên 'disconnect'thay vào đó là sự kiện trên máy khách 'disconnected'?
Sherlock

1
@Sherlock trong mã máy khách ban đầu của OP, họ đang cố gắng lắng nghe một sự kiện tùy chỉnh mà họ đang kích hoạt phía máy chủ cho logic bị ngắt kết nối. 'ngắt kết nối' thực sự là sự kiện ngắt kết nối được tích hợp sẵn, nhưng nó không góp phần trực tiếp vào vấn đề họ đang gặp phải.
Nhà thờ Jon

Câu trả lời:


169

Được, thay vì xác định người chơi theo bản tên bằng các ổ cắm mà họ đã kết nối. Bạn có thể có một triển khai như

Người phục vụ

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);
   });
});

Hy vọng điều này sẽ giúp bạn suy nghĩ theo một cách khác


90
Sử dụng tốt hơn allClients.splice(i, 1)để xóa một phần tử. delete allClients[i]sẽ chỉ đặt vị trí mảng thànhundefined
Yves

1
Tại sao nó hoạt động, nhưng giải pháp theo dõi mọi người với tên của họ không hoạt động?
sha1

Điều này không làm việc cho tôi. Ở đây icó giá trị là -1 mọi lúc. Bạn có thể cho tôi biết những gì đang xảy ra.
Vinit Chouhan

1
@VinitChouhan, bạn có thể nên đặt câu hỏi riêng với vấn đề thực tế của mình.
code-jaff

Khi bạn nhận được giá trị -1, có nghĩa là bạn đang cố nối một ổ cắm không tồn tại (ai đó ngắt kết nối nhưng bạn chưa đăng ký người đó trong allClientsmảng của mình ). Tôi đề nghị bạn chỉ cần quay lại: if (i === -1)return;trước khi cố gắng nối nó.
Koen B.

23

Đối với những người như @ sha1 tự hỏi tại sao mã OP không hoạt động -

Logic của OP để xóa trình phát ở phía máy chủ nằm trong trình xử lý cho DelPlayersự kiện và mã phát ra sự kiện này ( DelPlayer) nằm trong lệnh disconnectedgọi lại sự kiện bên trong của máy khách.

Mã phía máy chủ phát ra disconnectedsự kiện này nằm bên trong lệnh disconnectgọi lại sự kiện được kích hoạt khi ổ cắm mất kết nối. Vì ổ cắm đã bị mất kết nối, disconnectedsự kiện không đến được với máy khách.


Giải pháp được chấp nhận thực hiện logic về disconnectsự kiện ở phía máy chủ, được kích hoạt khi ổ cắm ngắt kết nối, do đó hoạt động.


6

Tạo một Bản đồ hoặc một Tập hợp và sử dụng sự kiện "khi kết nối" được đặt cho mỗi ổ cắm được kết nối, ngược lại sự kiện "một lần ngắt kết nối" sẽ xóa ổ cắm đó khỏi Bản đồ mà chúng tôi đã tạo trước đó

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
Và người ta sẽ mong đợi một câu trả lời chi tiết với lời giải thích và nhận xét từ cựu chiến binh, nhưng tôi đoán chúng tôi phải giải quyết chỉ với một bó mã
Cemal

cho tôi biết nếu bạn có thắc mắc, tôi không nhớ cách viết câu trả lời
Alexander Mills

1
Tôi thực sự không có bất kỳ câu hỏi. Đó chỉ là một lời chỉ trích mang tính xây dựng đối với một tác giả, người tốt hơn nên sử dụng nhận xét và mô tả trong câu trả lời để cho phép bất kỳ ai (ít nhất là) hiểu được ví dụ của bạn mà không làm bạn khó chịu. Dù sao, chúc mừng năm mới ..
Cemal,

0

Bạn cũng có thể sử dụng socket id để quản lý danh sách trình phát của mình như thế này, nếu bạn muốn.

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)
  })
})
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.