这是我的服务器端websocket脚本:
var clients = [ ];
//sample request: ****:8080/?steamid=123456789
var connection;
var aqsteamid = getParameterByName("steamid",request.resource);
connection = request.accept(null, request.origin);
connection.ID = aqsteamid;
connection.balRefreshes = 0;
connection.clientIndex = clients.push(connection) - 1;
//check if this user is already connected. If yes, kicks the previous client ***====EDITED====***
for(var i = 0; i < clients.length; i++)
{
if(clients[i].ID === aqsteamid){
var indx = clients.indexOf(clients[i]);
clients[indx].close();
}
}
console.log('ID',connection.ID,' connected.');
socket.on('close', function(webSocketConnection, closeReason, description){
try{
console.log('ID',webSocketConnection.ID,'disconnected. ('+closeReason+';'+description+')');
webSocketConnection.balRefreshes = 0;
webSocketConnection.spamcheck = false;
clients.splice(webSocketConnection.clientIndex, 1);
}catch(e)
{
console.log(e);
}
});
基本上我想要的是使用相同的ID启动所有连接(例如,连接多个浏览器选项卡)。
但是,它不是踢旧客户端,而是踢两个客户端,或者在某些情况下两个客户端都保持连接相同的ID。
我的剧本中是否有其他方式或有任何错误?
由于
答案 0 :(得分:1)
使用Array的对象instad来键入clients
池,使其更快更简单:
var clients = {};
//sample request: ****:8080/?steamid=123456789
var connection;
var aqsteamid = getParameterByName("steamid",request.resource);
connection = request.accept(null, request.origin);
connection.ID = aqsteamid;
connection.balRefreshes = 0;
clients[aqsteamid]=connection;
socket.on('close', function(webSocketConnection, closeReason, description){
try{
console.log('ID',webSocketConnection.ID,'disconnected. ('+closeReason+';'+description+')');
webSocketConnection.balRefreshes = 0;
webSocketConnection.spamcheck = false;
delete clients[aqsteamid];
}catch(e)
{
console.log(e);
}
});
//check if this user is already connected. If yes, kicks the previous client
if(clients[aqsteamid]) clients[aqsteamid].close();
console.log('ID',connection.ID,' connected.');
使用对象池,我们可以删除所有数组池循环和比较逻辑,我们的索引永远不会失去同步。
答案 1 :(得分:0)
听起来多个具有相同ID的连接可能是具有多个标签的真正工作流程的一部分(不像是,恶意用户故意用多个线程抓取数据......)
而不是&#34;踢&#34;来自其他标签的用户然后必须处理它们重新连接,一个更优雅的解决方案是在多个标签中引入业务流程层。
您可以依靠localstorage api选择一个主标签来处理与服务器的通信(如果它的websocket或ajax并不重要)并与其他标签共享响应 - 再次通过localstorage 。如果您在共享数据时打开1或20个选项卡并不重要,因为您关心相同的邮件通知或股票代码更新等等。
来自another stackoverflow answer:
storage
事件允许您在标签之间传播数据,同时保持一个 单个SignalR连接打开(从而防止连接 饱和)。致电localStorage.setItem('sharedKey', sharedData)
将在所有其他选项卡(而不是调用者)中引发storage
事件:$(window).bind('storage', function (e) { var sharedData = localStorage.getItem('sharedKey'); if (sharedData !== null) console.log( 'A tab called localStorage.setItem("sharedData",'+sharedData+')' ); });
根据上面的代码,如果在加载页面时已经有sharedKey
值,则假设主选项卡处于活动状态并从localstorage获取共享值。您可以检查是否需要重新选举主选项卡(即,浏览器选项卡已关闭或导航),间隔或依赖于page visibility api等更复杂的内容。
请注意,您不仅限于分享&#34;相同&#34;跨多个标签的数据,而是通过共享渠道批量处理任何请求。