I'm making simple online game which based on Web. the game uses Socket.io for netwoking each other. but I encountered the problem.
我正在做一个基于网络的简单的在线游戏。游戏使用套接字。我感谢你们彼此。但我遇到了问题。
think about following situation . I ran Socket.io server. one player making the room , and other player join the room. they played game some time .. but one player so angry and close the game tab.
考虑以下情况。我跑的套接字。io服务器。一名玩家进入房间,另一名玩家进入房间。他们有时也做游戏。但是一个玩家很生气,关闭了游戏标签。
in this situation , how can I get the event which one client have been closed the browser in server-side ?
在这种情况下,如何获得一个客户端已经在服务器端关闭浏览器的事件?
according to googling , peoples say like this : "use browser-close event like onBeforeUnload"
根据谷歌搜索,人们会这样说:“使用像onBeforeUnload这样的浏览器关闭事件”
but I know that All browser don't support onBeforeUnload event. so i want solution about checking the client disconnection event in SERVER SIDE.
但是我知道所有的浏览器都不支持onBeforeUnload事件。所以我想要服务器端检查客户端断开事件的解决方案。
in Socket.io ( nodeJS ) server-side console , when client's connection closed , the console say like following :
在套接字。io (nodeJS)服务器端控制台,当客户端连接关闭时,控制台说:
debug - discarding transport
调试,丢弃运输
My nodeJS version is 0.4.10 and Socket.io version is 0.8.7. and both are running on Linux.
我的nodeJS版本是0.4.10和Socket。io版本是0.8.7。两者都在Linux上运行。
Anyone can help please ?
谁能帮忙吗?
shortend codes are here :
短代码在这里:
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 );
}
});
});
});
2 个解决方案
#1
17
Update: I created a blog post for this solution. Any feedback is welcome!
更新:我为这个解决方案创建了一个博客文章。任何反馈是受欢迎的!
I recommend using the 'sync disconnect on unload' option for Socket IO. I was having similar problems, and this really helped me out.
我建议在Socket IO中使用“同步断开卸载”选项。我也遇到过类似的问题,这对我很有帮助。
On the client:
在客户端:
var socket = io.connect(<your_url>, {
'sync disconnect on unload': true });
No need to wire in any unload or beforeunload events. Tried this out in several browsers, and its worked perfectly so far.
不需要在任何卸载事件或卸载事件之前连接。在几个浏览器中尝试过,到目前为止效果还不错。
#2
7
There's an event disconnect
which fires whenever a socket.io
connection dies (note that you need this, because you may still have a wep page open, but what if your internet connection dies?). Try this:
当一个套接字被触发时,就会出现一个事件断开。io连接死(注意您需要这个,因为您可能仍然打开wep页面,但是如果您的internet连接死了怎么办?)试试这个:
var io = require('socket.io').listen(80);
io.sockets.on('connection', function (socket) {
socket.on('disconnect', function () {
io.sockets.emit('user disconnected');
});
});
at your server. Taken from Socket.IO website.
在你的服务器。从插座。IO的网站。
//EDIT
/ /编辑
So I looked at your code and did some tests at my place. I obtained the very same results as you and here's my explanation. You are trying to make Socket.IO very dynamic by dynamically forcing it to listen to different urls (which are added at runtime). But when the first connection is made, at that moment the server does not listen to the other url. It seems that exactly at that point (when connection is accepted) the disconnect
handler is set for the first connection and it is not updated later (note that Socket.IO does not create new connections when you call io.connect
many times at the client side). All in all this seems to be a bug! Or perhaps there is some fancy explanation why this behaviour should be as it is but I do not know it.
所以我查看了你的代码并在我的地方做了一些测试。我得到了和你一样的结果,这是我的解释。你在试着做插座。IO非常动态,动态地迫使它侦听不同的url(在运行时添加)。但是,当建立第一个连接时,此时服务器不会侦听另一个url。似乎正是在这一点(当连接被接受时),为第一个连接设置了断开处理程序,之后不会更新它(请注意套接字)。当您调用IO时,IO不会创建新的连接。在客户端连接多次)。所有这些似乎都是一个错误!或者可能有一些奇怪的解释,解释为什么这种行为应该是现在的样子,但我不知道。
Let me tell you some other things. First of all this dynamical creation of listeners does not seem to be a good way. In my opinion you should do the following: store the existing rooms and use one url for all of them. Hold the ID of a room and when you emit for example message
event from client add the ID of a room to the data and handle this with one message
handler at the server. I think you get the idea. Push the dynamic part into the data, not urls. But I might be wrong, at least that's my opinion.
让我告诉你一些其他的事情。首先,这种动态创建听众的方式似乎并不好。在我看来,您应该这样做:存储现有的房间并为所有房间使用一个url。保存一个房间的ID,当您从客户端发出消息事件时,将一个房间的ID添加到数据中,并在服务器上使用一个消息处理程序处理它。我想你懂的。将动态部分推入数据,而不是url。但我可能错了,至少这是我的观点。
Another thing is that the code you wrote seems to be bad. Note that running .on('connection', handler)
many times will make it fire many times. Handlers stack one onto another, they do not replace each other. So this is how I would implement this:
另一件事是你写的代码看起来很糟糕。注意,多次运行.on('connection', handler)会使它多次触发。处理程序将一个堆栈到另一个,它们不会互相替换。这就是我如何实现的
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");
});
});
Keep in mind that the problem with creating connections before the listeners are defined will still occure.
请记住,在定义侦听器之前创建连接的问题仍然会发生。
#1
17
Update: I created a blog post for this solution. Any feedback is welcome!
更新:我为这个解决方案创建了一个博客文章。任何反馈是受欢迎的!
I recommend using the 'sync disconnect on unload' option for Socket IO. I was having similar problems, and this really helped me out.
我建议在Socket IO中使用“同步断开卸载”选项。我也遇到过类似的问题,这对我很有帮助。
On the client:
在客户端:
var socket = io.connect(<your_url>, {
'sync disconnect on unload': true });
No need to wire in any unload or beforeunload events. Tried this out in several browsers, and its worked perfectly so far.
不需要在任何卸载事件或卸载事件之前连接。在几个浏览器中尝试过,到目前为止效果还不错。
#2
7
There's an event disconnect
which fires whenever a socket.io
connection dies (note that you need this, because you may still have a wep page open, but what if your internet connection dies?). Try this:
当一个套接字被触发时,就会出现一个事件断开。io连接死(注意您需要这个,因为您可能仍然打开wep页面,但是如果您的internet连接死了怎么办?)试试这个:
var io = require('socket.io').listen(80);
io.sockets.on('connection', function (socket) {
socket.on('disconnect', function () {
io.sockets.emit('user disconnected');
});
});
at your server. Taken from Socket.IO website.
在你的服务器。从插座。IO的网站。
//EDIT
/ /编辑
So I looked at your code and did some tests at my place. I obtained the very same results as you and here's my explanation. You are trying to make Socket.IO very dynamic by dynamically forcing it to listen to different urls (which are added at runtime). But when the first connection is made, at that moment the server does not listen to the other url. It seems that exactly at that point (when connection is accepted) the disconnect
handler is set for the first connection and it is not updated later (note that Socket.IO does not create new connections when you call io.connect
many times at the client side). All in all this seems to be a bug! Or perhaps there is some fancy explanation why this behaviour should be as it is but I do not know it.
所以我查看了你的代码并在我的地方做了一些测试。我得到了和你一样的结果,这是我的解释。你在试着做插座。IO非常动态,动态地迫使它侦听不同的url(在运行时添加)。但是,当建立第一个连接时,此时服务器不会侦听另一个url。似乎正是在这一点(当连接被接受时),为第一个连接设置了断开处理程序,之后不会更新它(请注意套接字)。当您调用IO时,IO不会创建新的连接。在客户端连接多次)。所有这些似乎都是一个错误!或者可能有一些奇怪的解释,解释为什么这种行为应该是现在的样子,但我不知道。
Let me tell you some other things. First of all this dynamical creation of listeners does not seem to be a good way. In my opinion you should do the following: store the existing rooms and use one url for all of them. Hold the ID of a room and when you emit for example message
event from client add the ID of a room to the data and handle this with one message
handler at the server. I think you get the idea. Push the dynamic part into the data, not urls. But I might be wrong, at least that's my opinion.
让我告诉你一些其他的事情。首先,这种动态创建听众的方式似乎并不好。在我看来,您应该这样做:存储现有的房间并为所有房间使用一个url。保存一个房间的ID,当您从客户端发出消息事件时,将一个房间的ID添加到数据中,并在服务器上使用一个消息处理程序处理它。我想你懂的。将动态部分推入数据,而不是url。但我可能错了,至少这是我的观点。
Another thing is that the code you wrote seems to be bad. Note that running .on('connection', handler)
many times will make it fire many times. Handlers stack one onto another, they do not replace each other. So this is how I would implement this:
另一件事是你写的代码看起来很糟糕。注意,多次运行.on('connection', handler)会使它多次触发。处理程序将一个堆栈到另一个,它们不会互相替换。这就是我如何实现的
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");
});
});
Keep in mind that the problem with creating connections before the listeners are defined will still occure.
请记住,在定义侦听器之前创建连接的问题仍然会发生。