Websocket-突然下降后重新建立连接

Websocket-突然下降后重新建立连接,websocket,Websocket,我开发了一个使用websocket连接的小型数据库系统。 有时连接可能会突然中断,而不是因为电缆或电力问题,我现在不清楚原因 我增加了心跳,每3秒检查一次连接,在服务器端,我给连接超时5秒,以防连接突然变慢 问题: 在客户端意识到连接丢失后,它将尝试重新连接。有时它能工作,但有时它会反复失败——也许是因为连接断开了???怎么会?在重新连接之前,我正在尝试确保连接完全关闭。我做错了什么 JS来源(部分): EF.WS=new EF_WebSocketInterface(); 函数EF_WebSoc

我开发了一个使用websocket连接的小型数据库系统。 有时连接可能会突然中断,而不是因为电缆或电力问题,我现在不清楚原因

我增加了心跳,每3秒检查一次连接,在服务器端,我给连接超时5秒,以防连接突然变慢

问题: 在客户端意识到连接丢失后,它将尝试重新连接。有时它能工作,但有时它会反复失败——也许是因为连接断开了???怎么会?在重新连接之前,我正在尝试确保连接完全关闭。我做错了什么

JS来源(部分):

EF.WS=new EF_WebSocketInterface();
函数EF_WebSocketInterface(){
var=this,QS={},QR={},ito,hb;
window.onunload=function(){
如果(!| |!|.con)返回;
//向服务器发送终止命令
}
_.Init=函数(p,f){Run(f);}
函数运行(f){
if(&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&;
如果(!hb)hb=setInterval(u.SMInt,3000,“-”,“);//心跳
}
试一试{
_.con=new WebSocket('wss://'+document.domain+':'+/*端口*/+'/?C='+/*凭据已检查为OK*/+'&L=EN-US');
_.con.onerror=函数(e){console.log(e);}
_.con.onopen=function(){{{uu.con.tmt=Date.now();}
_.con.onclose=function(){setTimeout(Run,1);}//立即重新连接!
_.con.onmessage=函数(e){
var V=new FileReader(),C,I;
_.con.tmt=Date.now();//来自服务器的任何输入消息(包括心跳信号)都在更新时间戳!
V.addEventListener(“loadend”,函数(){
V=V.result.replace(/\n/g')。replace(/\r/g');
if(V='-')返回;//忽略服务器心跳信号进行处理。
/*消息(命令)处理*/
});
V.readAsText(即数据);
}
}
catch(e){console.log(e);if(u.con)u.con.onclose();}
}
/*这是发送命令的官方功能。
这将在特殊队列中为案例连接丢失注册消息,以便在不重复用户交互的情况下重新发送它们。
参数:
p=命令代码
c=命令内容的参数
f=接收消息时要执行的函数回调(可选)
x=保留供内部使用
*/
_.SM=函数(p,c,f,x){
变量d=“”+(QS.++);而(d.长度1,
on_tick=>sub{
my@l=keys%CON;#这是主连接数据库,每个数据库都有自己的属性
我的$i;我的$j;我的@m;
$\u TPC->[2]+;如果($\u TPC->[2]==5){$\u TPC->[2]=0;}
如果($\u TPC->[2]==0){
对于($i=0;$ireq->资源名称;
我的$ns=substr($nsn,4,索引($nsn,&L=')-4);
$cid=($ns eq“”)?整数(兰特(100000000)):$ns;
如果(!defined$CON{$cid}){$CON{$cid}={“QS”=>0},“QR”=>{},“T”=>time(),“L”=>substr($nsn,index($nsn,&L=')+3)}
elsif(定义为$CON{$cid}{“C”}){$CON{$cid}{“C”}->disconnect();}
$CON{$cid}{“C”}=$conn;
},
二进制=>sub{
#对于任何输入消息-更新活动时间戳。
$CON{$cid}{“T”}=time();my$c$msg)=@;
#忽略客户端心跳
if($msg eq'-'){return;}
#处理消息(命令)
},
断开连接=>sub{}#没有什么特别的事情要做。
);
}
)->开始;
子CX{
$CON{$\[0]}{“C”}->disconnect();
删除$CON{$\[0]}{“C”};如果($\[1]==1&&$CON{$\[0]}{'U'}eq”“){&XX($\[0]);}
}
sub XX{删除$CON{$\[0]};}
注意: 1.作为JS变量存储在客户端的凭据不会丢失,除非客户端刷新浏览器,但情况并非如此。
2.在这样的“连接断开”上检查的readystate变量仍然显示1-但是消息没有被转发到服务器。
3.在重复连接失败的情况下,如果我刷新浏览器并重新连接,它将正常工作(奇怪…)。 4.在PERL中,如果有帮助的话,我将使用Net::Websocket::Server和IO::Socket::SSL

PERL命令断开与连接的连接是否可能需要更长的时间才能关闭? 任何关于连接突然中断或我无法重新连接的想法都将不胜感激

EF.WS=new EF_WebSocketInterface();
function EF_WebSocketInterface() {
    var _=this,QS={_:0},QR={},ito,hb;
    window.onunload=function() {
         if(!_||!_.con) return;
         // send termination command to the server
    }
    _.Init=function(p,f) { Run(f); }
    function Run(f) {
        if(_.con&&_.con.readyState!==3) return setTimeout(Run,1,f);
        if(!hb) hb=setInterval(_.SMInt,3000,'-',''); // Heartbeat
    }
    try {
        _.con=new WebSocket('wss://'+document.domain+':'+/* port */+'/?C='+ /* credentials been checked as OK */+'&L=EN-US');
        _.con.onerror=function(e) { console.log(e); }
        _.con.onopen=function() { _.con.tmt=Date.now(); }
        _.con.onclose=function() { setTimeout(Run,1); } // immediate reconnection!
        _.con.onmessage=function(e) {
            var V=new FileReader(),C,I;
            _.con.tmt=Date.now(); // Any incomming messages from the server including the heartbeat are updating the time stamp!
            V.addEventListener("loadend", function() {
                V=V.result.replace(/\n/g,'').replace(/\r/g,'');
                if(V=='-') return; // ignore server heartbeat for processing.
                /* Message (command) processing */
            });
            V.readAsText(e.data);
        }
    }
    catch(e){ console.log(e); if(_.con) _.con.onclose(); }
}
/* This is the official function to send commands.
   This will register the message in special queue for a case connection lost, to resend them without repeated user interaction.

     Parameters:
     p = Command code
     c = Parameters content for command
     f = function callback to be done on message receive (optional)
     x = reserved for internal use
*/
_.SM=function(p,c,f,x) {
     var d=""+(QS._++); while(d.length<5) d="0"+d; QS[d]=[(x?"":EF.ON([p,c])),Date.now(),f]; _.SMInt((x?x:"A"),d);
}

/* This is internal command sender*/
_.SMInt=function(b,c) {
    /* Command preparation and message ID management */

    // Preparation for sending the message
    if(_.con&&_.con.readyState==1) 

        // If pass more than 5 seconds, the connection probably closed.
        if(_.con.tmt+5000<Date.now()) { _.con.close(); }
        else {
            // Sending of heartbeat to the server, also checking if has got any pending messages in queue since last failed session.
            if(b=='-') {
                if(ito) return; ito=1; var n=Object.keys(QS);
                for(var i=0 ; i<n.length ; i++) if(n[i]!=='_' && QS[n[i]][1]+5000<Date.now()) _.SMInt("C",n[i]);
                    ito=0;
                }
                try { _.con.send(new Blob([m],{type:'text/html',charset:'utf-8'}),{ binary:true }); }
                catch(e) { }
            }
    }
    _.Get=function(p,m,r,c) { _.SM(m,r,function(e) { _.xQ(p,EF.Data,e); c(); }); 
}
}
Net::WebSocket::Server->new(
    listen => $ssl,
    silence_max=> 14400,
    tick_period => 1,
    on_tick => sub {
        my @l=keys %CON; # This is the main connections DB, each with its own properties
        my $i; my $j; my @m;

        $_TPC->[2]++; if($_TPC->[2]==5) { $_TPC->[2]=0; }
        if($_TPC->[2]==0) {
            for($i=0 ; $i<@l ; $i++) {
                # Resend pending messages in queue

                # If connection passed 10 seconds without any message, it is clearly lost: &CX is closing the connection and deleting the session from %CON.

                if($CON{$l[$i]}{"C"}) {
                    if($CON{$l[$i]}{"T"}+10<time()) { &CX($l[$i],($CON{$l[$i]}{"T"}+300<time())?1:0); }
                else { &SMInt($l[$i],'-',''); }
            }
            elsif($CON{$l[$i]} && $CON{$l[$i]}{"T"}+14400<time()) { &XX($l[$i]); }
        }
    },
    on_connect => sub {
        my($serv,$conn)=@_; my $cid;
        $conn->on(
            handshake => sub {
                my($conn,$handshake)=@_;
                my $nsn=$handshake->req->resource_name;
                my $ns=substr($nsn,4,index($nsn,'&L=')-4);
                $cid=($ns eq "")?int(rand(1000000000)):$ns;
                if(!defined $CON{$cid}) { $CON{$cid}={"QS"=>{"_"=>0},"QR"=>{},"T"=>time(),"L"=>substr($nsn,index($nsn,'&L=')+3)}; }
                elsif(defined $CON{$cid}{"C"}) { $CON{$cid}{"C"}->disconnect(); }
                $CON{$cid}{"C"}=$conn;
            },
            binary => sub {
                # for any incomming messages - update the active time stamp. 
                $CON{$cid}{"T"}=time(); my($c,$msg)=@_;

                # ignore client side heartbeat here
                if($msg eq '-') { return; } 

                # Process the message (command)
            },
            disconnect => sub {} # Nothing special to be done.
        );
    }
)->start;

sub CX {
    $CON{$_[0]}{"C"}->disconnect();
    delete $CON{$_[0]}{"C"}; if($_[1]==1 && $CON{$_[0]}{'U'} eq "") { &XX($_[0]); }
}
sub XX { delete $CON{$_[0]}; }