node.js 我如何处理 Socket.io 中的关闭事件?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/9077719/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How can i handle Close event in Socket.io?
提问by Jindong Jung
I'm making simple online game which based on Web. the game uses Socket.io for netwoking each other. but I encountered the problem.
我正在制作基于Web的简单在线游戏。游戏使用 Socket.io 互相联网。但我遇到了这个问题。
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.
想想下面的情况。我运行了 Socket.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 事件。所以我想要关于在 SERVER SIDE 中检查客户端断开连接事件的解决方案。
in Socket.io ( nodeJS ) server-side console , when client's connection closed , the console say like following :
在 Socket.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 );
}
});
});
});
回答by Carlos Atencio
Update:I created a blog postfor 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 unloador beforeunloadevents. Tried this out in several browsers, and its worked perfectly so far.
无需连接任何卸载或之前卸载事件。在几个浏览器中尝试了这一点,到目前为止它工作得很好。
回答by freakish
There's an event disconnectwhich fires whenever a socket.ioconnection dies (note that you need this, because you may still have a wep page open, but what if your internet connection dies?). Try this:
disconnect每当socket.io连接断开时都会触发一个事件(请注意,您需要这个,因为您可能仍然打开了一个网页,但是如果您的互联网连接断开怎么办?)。尝试这个:
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.
在您的服务器上。摘自Socket.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 disconnecthandler 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.connectmany 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.
所以我查看了你的代码并在我的地方做了一些测试。我得到了和你一样的结果,这是我的解释。您试图通过动态强制 Socket.IO 侦听不同的 url(在运行时添加)来使 Socket.IO 非常动态。但是当第一次连接建立时,此时服务器不会监听另一个 url。似乎正是在那个时候(当连接被接受时)disconnect为第一个连接设置了处理程序,并且以后不会更新(请注意,当您io.connect在客户端多次调用时,Socket.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 messageevent from client add the ID of a room to the data and handle this with one messagehandler 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,当您message从客户端发出例如事件时,将房间的 ID 添加到数据中,并使用message服务器上的一个处理程序来处理。我想你应该已经明白了。将动态部分推送到数据中,而不是 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.
请记住,在定义侦听器之前创建连接的问题仍然会发生。

