2012-01-31 28 views
12

Tôi đang tạo trò chơi trực tuyến đơn giản dựa trên Web. trò chơi sử dụng Socket.io để chia sẻ lẫn nhau. nhưng tôi đã gặp sự cố.Làm cách nào để xử lý sự kiện Đóng trong Socket.io?

suy nghĩ về tình huống sau. Tôi đã chạy máy chủ Socket.io. một người chơi đặt phòng và người chơi khác tham gia vào phòng. họ chơi trò chơi một thời gian .. nhưng một người chơi rất tức giận và đóng tab trò chơi.

trong trường hợp này, làm thế nào tôi có thể nhận được sự kiện mà một khách hàng đã đóng trình duyệt ở phía máy chủ?

theo googling, người nói như thế này: "sử dụng sự kiện trình duyệt gần như onbeforeunload"

nhưng tôi biết rằng tất cả các trình duyệt không hỗ trợ sự kiện onbeforeunload. vì vậy tôi muốn giải pháp về việc kiểm tra sự kiện ngắt kết nối máy khách trong SERVER SIDE.

trong Socket.io (nodeJS) server-side console, khi kết nối của khách hàng đóng cửa, giao diện điều khiển nói như sau:

debug - loại bỏ phương tiện giao thông

phiên bản nodeJS tôi là 0.4.10 và Socket.io phiên bản là 0.8.7. và cả hai đều chạy trên Linux.

Bất cứ ai cũng có thể trợ giúp?

mã rút ngắn đáng đang ở đây:

var io = require ("socket.io").listen (3335); 
io.sockets.on ("connection" , function (socket) 
{ 
    socket.on ("req_create_room" , function (roomId) 
    { 
    var socketInstance = io 
    .of ("/" + roomId) 
    .on ("connection" , function (sock) 
    { 
     sock.on ("disconnect" , function() 
     { 
      // i want this socket data always displayed... 
      // but first-connected-client doesn't fire this event .. 
      console.log (sock); 
     } 
    }); 
    }); 
}); 
+0

Câu trả lời của tôi có hữu ích không? Nó có giải quyết được vấn đề của bạn không? –

Trả lời

7

Có một sự kiện disconnect mà cháy khi sự kết nối socket.io chết (lưu ý rằng bạn cần điều này, bởi vì bạn vẫn có thể có một trang wep mở, nhưng những gì nếu kết nối internet của bạn chết?). Hãy thử điều này:

var io = require('socket.io').listen(80); 

io.sockets.on('connection', function (socket) { 
    socket.on('disconnect', function() { 
    io.sockets.emit('user disconnected'); 
    }); 
}); 

tại máy chủ của bạn. Lấy từ Socket.IO website.

// EDIT

Vì vậy, tôi đã xem xét mã của bạn và làm một số xét nghiệm ở vị trí của tôi. Tôi nhận được kết quả rất giống như bạn và đây là lời giải thích của tôi. Bạn đang cố gắng để làm cho Socket.IO rất năng động bằng cách tự động buộc nó để lắng nghe các url khác nhau (được thêm vào lúc chạy). Nhưng khi kết nối đầu tiên được thực hiện, tại thời điểm đó máy chủ không nghe các url khác. Dường như chính xác tại thời điểm đó (khi kết nối được chấp nhận), trình xử lý disconnect được đặt cho kết nối đầu tiên và nó không được cập nhật sau (lưu ý rằng Socket.IO không tạo kết nối mới khi bạn gọi io.connect nhiều lần ở phía máy khách) . Tất cả trong tất cả điều này có vẻ là một lỗi! Hoặc có lẽ có một số giải thích lạ lùng tại sao hành vi này phải như vậy nhưng tôi không biết điều đó.

Hãy để tôi kể cho bạn một số điều khác. Trước hết, việc tạo ra những người nghe động này dường như không phải là một cách tốt. Theo tôi, bạn nên làm như sau: lưu trữ các phòng hiện có và sử dụng một url cho tất cả chúng. Giữ ID của một phòng và khi bạn phát ra ví dụ message sự kiện từ máy khách, thêm ID của phòng vào dữ liệu và xử lý điều này với một trình xử lý message tại máy chủ. Tôi nghĩ rằng bạn có được ý tưởng. Đẩy phần động vào dữ liệu chứ không phải url. Nhưng tôi có thể sai, ít nhất đó là ý kiến ​​của tôi.

Một điều khác là mã bạn viết có vẻ là xấu. Lưu ý rằng chạy .on('connection', handler) nhiều lần sẽ làm cho nó cháy nhiều lần. Trình xử lý xếp chồng lên nhau, chúng không thay thế lẫn nhau. Vì vậy, đây là cách tôi sẽ thực hiện điều này:

var io = require("socket.io").listen(app); 
var roomIds = []; 

function update_listeners(id) { 
    io.of("/"+id).on("connection", function(socket) { 
     console.log("I'm in room " + id); 
     socket.on("disconnect", function(s) { 
      console.log("Disconnected from " + roomId); 
     });    
    }); 
} 

var test = io.sockets.on("connection", function(socket) { 
    console.log("I'm in global connection handler"); 
    socket.on("req_create_room", function(data) { 
     if (roomIds.indexOf(data.roomId) == -1) { 
      roomIds.push(data.roomId); 
      update_listeners(data.roomId);  
     } 
     test.emit("room_created", {ok:true}); 
    }); 
    socket.on("disconnect", function(s) { 
     console.log("Disconnected from global handler"); 
    }); 
}); 

Hãy nhớ rằng vấn đề với việc tạo kết nối trước khi người nghe được xác định sẽ vẫn xảy ra.

+0

Cảm ơn !! nó hoạt động. nhưng tôi vẫn còn có một số vấn đề ở đây ... trên "ngắt kết nối" sự kiện cháy tốt nhưng ngoại trừ khách hàng kết nối đầu tiên. tôi muốn biết tại sao khách hàng được kết nối đầu tiên không thể kích hoạt sự kiện "ngắt kết nối"? –

+0

Không biết. Đăng một số mã và chúng ta sẽ thấy. – freakish

+0

Tôi đã đăng mã. đó là phiên bản ebridged .. cảm ơn bạn đã giúp đỡ của bạn –

17

Cập nhật: Tôi đã tạo a blog post cho giải pháp này. Bất kỳ thông tin phản hồi được hoan nghênh!

Tôi khuyên bạn nên sử dụng tùy chọn 'đồng bộ ngắt kết nối khi dỡ tải' cho Socket IO. Tôi đã gặp vấn đề tương tự, và điều này thực sự đã giúp tôi.

Trên client:

var socket = io.connect(<your_url>, { 
'sync disconnect on unload': true }); 

Không cần phải dây ở bất kỳ dỡ bỏ hoặc beforeunload sự kiện. Đã thử điều này trong một số trình duyệt, và nó hoạt động hoàn hảo cho đến nay.

+1

Bạn Sir đã làm cho ngày của tôi. Tôi đã lãng phí 7 giờ cố gắng tìm một giải pháp cho vấn đề này! –

+0

Liên kết bài đăng thay vì blog, vui lòng – laggingreflex

+0

Tôi đã cập nhật URL liên kết. –

Các vấn đề liên quan