socket.io 如何准确判断server与client之间断开连接
发布于 2年前 作者 babata 4823 次浏览

1、如果client端断开网络,我在Server端如何准去判断client端断开连接了!!!!
2、disconnect不管用,只有在client端关闭浏览器的时候 ,server端才能检测到。 好纠结 !麻烦遇到这样问题的告诉一下解决方案 qq:929541303

14 回复

根据 https://github.com/LearnBoost/socket.io-spec 文档中说是在transport连接 (就是TCP)Close后再等一段时间(15秒,可配置)释放资源。我们知道一般TCP 不会轻易Close,网站没数据,可能连接一直存在着。 所以有两种思路,一个是自己在在Scoket.io的业务层设置定时器,超过一段时间无业务数据,释放socket.io的资源。另一种就是把TCP连接超时时间设短,不过要注意socket.io的socket不是node.js的socket,可以参考以下代码: io.sockets.on('connection’, function (socket) { socket.manager.transports[socket.id].socket.setTimeout(15000); //… } 如果client关闭后,大约15+15秒之后会释放资源。

这样做还是达不到我想要的效果! 比如 聊天室,如果有一个人的网线断了(不是关闭浏览器),我在服务器端怎么监听? 他掉了了我就不用给他发消息?

socket.io就没有自己的api event? 我找了好久就是没有,自己想的思路就是在发送消息的时候发一个字节给client端 如果client端有反应 就表示在 !但是这样不是我想要的结果!我想的是server端主动监听,实时返回client断开了,而不是等我需要发发送消息的时候才去验证client的端是否在线!

你先要明确你所谓“client断开了”的含义。 socket.io也并不知道你需要什么逻辑?event有connection和disconnect就足够了。 之前已经说过了,所谓用户是否在线,是应用层的,比如聊天室的是否在线标准是看用户是否有输入。 而对于socket.io是transport层没断,它就一直给你保持通路。因为实际上transport是通的,那么断开socket.io连接的工作由client或server端负责都可以。一旦断socket.io的连接,实际上是断transport层的连接,对端也可以检测到。

以下例子是依据是否Server端根据是否接受到client端的数据判断是否“client断开了”,发命令给client端的socket.io, 由client端负责断连接。

== Server Side var app = require(‘http’).createServer(handler) , io = require(‘socket.io’).listen(app) , fs = require(‘fs’)

app.listen(80);

function handler (req, res) { fs.readFile(__dirname + '/index.html’, function (err, data) { if (err) { res.writeHead(500); return res.end(‘Error loading index.html’); }

res.writeHead(200);
res.end(data);

}); }

function Client(socket) { var self = this; this.socket = socket; this.timeout;

this.timeoutProc = function timeoutProc() {
    console.log('timeouted');
    self.socket.emit('DisconnectReq');       
};
this.datain = function(data) {
    clearTimeout(this.timeout);
    //......... Your processing
    this.timeout = setTimeout(this.timeoutProc, 15000); 
}
this.timeout = setTimeout(this.timeoutProc, 15000);

}

io.sockets.on('connection’, function (socket) { var client = new Client(socket); socket.emit('news’, { hello: ‘world’ }); socket.on('my other event’, function (data) { console.log(data); client.datain(data);
}); socket.on('disconnect’, function(){ console.log(‘receive disconnect event’); delete client; }) });

== Client Side

<script src="/socket.io/socket.io.js"></script> <script> var socket = io.connect('http://localhost'); socket.on('news', function (data) { console.log(data); socket.emit('my other event', { my: 'data' }); socket.on('DisconnectReq', function() { socket.disconnect(); }); }); </script>

网线断的情况,socket.manager.transports[socket.id].socket.setTimeout(15000);应该能检测。会触发transport层的close–> socket.io的disconnect事件

刷新浏览器也是会触发disconnect事件的,所以个人觉得用延时的方法去判断比较好。

socket.on 'disconnect', ->
  setTimeout ->
   refresh_online()
   empty_room()
  ,10

我原来也发现不好使,不过貌似这样就行了

可以试试哈

10毫秒?太短了吧?如果客户端是因为刷新浏览器的话你也会认为是短线了吧?

@thesadboy 对啊 刷新就断线,不过会直接再次连接上啊

@q1270989 所以个人觉得应该加入防抖的机制,这样就不会刷新一下就提示下线,然后又上线。

@thesadboy 嗯嗯 也是 当时没多想 哈哈 3Q

@q1270989 呵呵,不客气,相互学习

@thesadboy (●’◡’●)ノ♥

@q1270989 请教下你这里的 empty_room()是什么啊?

回到顶部