2014-12-08 4 views
0

게임 서버에 node.js를 사용하고 있습니다. 여기 Node.js를 사용하여 클라이언트 측 인터넷 연결을 감지하는 방법

는 ================================== 내 서버 스크립트

var net = require('net'); 
var http = require('http'); 

var host = '192.168.1.77'; 
var portNum = 12345;// 


    function policy() 
{ 
    var xml = '<?xml version="1.0"?>\n<!DOCTYPE cross-domain-policy SYSTEM' + 
      '"http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd">\n<cross-domain-policy>\n'; 

    xml += '<allow-access-from domain="*" to-ports="*"/>\n'; 
    xml += '</cross-domain-policy>\n\0' + "\0"; 
    return xml; 
} 



var server = net.createServer(function (stream) 
{ 
stream.setEncoding('utf8'); 

stream.on('data', function (data) { 

    if (data == '<policy-file-request/>\0') 
    { 
     var x = policy(); 
     stream.write(x); 
     var server_date = new Date(); 
     var serv_sec = server_date.getSeconds(); 
     return; 
    } 

    var comm = JSON.parse(data); 
    if (comm.action == "Join_Request" && comm.gameId =="game1") // join request getting from client 
    { 
     var reply0 = new Object(); 
     reply0.message = "WaitRoom"; 
     stream.write(JSON.stringify(reply0) + "\0"); 
    } 
}); 

stream.on('disconnect', function() 
{ 
    console.log("disconnect"); 
}); 
stream.on('close', function() 
{ 
console.log("Close"); 
}); 

//stream.setNoDelay(true); 
//stream.setKeepAlive(true, 200); 
//stream.setTimeout(10, function(){ 
// console.log('timeout'); 
//}); 
stream.on('connect', function() { 
console.log('check 2', stream.connected); 
} ); 
    stream.on('error', function() { 
    console.log("Error"); 
    }); // close function 

    }); // ===== create server end 
    server.listen(portNum,host,{'heartbeat interval':1, 'heartbeat timeout' : 2} ); 

입니다 ========================================================================================================== ===========

클라이언트 측 스크립트

using UnityEngine; 
    using System.Collections; 
    using System; 
    using System.Xml; 
    using System.Linq; 
    using System.Threading; 
    using Boomlagoon.JSON; 
    using JsonFx.Json; 
    using System.Net.Sockets; 

         try 
         { 

          tcpClient.Connect (host,portNum); 
          serverStream = tcpClient.GetStream(); 
          serverStream.Flush(); 

          ThreadPool.QueueUserWorkItem(new WaitCallback(ReceiveFromServer)); 



          isConnectionActive = true; 
          isReadyToJoinRoom = true; 
          connected = 1; 
          disconnected =0; 
          c_global.isClientConnectOn = false; 
          c_global.isClientDisconnectOn = false; 

         } 
         catch(ArgumentException l_exception) 
         { 
          c_global.isClientDisconnectOn = true; 
          isConnectionActive = false; 
         } 

         catch(SocketException l_exception) 
         { 
          c_global.isClientDisconnectOn = true; 
          isConnectionActive = false; 
         } 

         catch(Exception e) 
         { 
          c_global.isClientDisconnectOn = true; 
          isConnectionActive = false; 
          connected = 0; 
          disconnected =1; 

         } 


       public void ReceiveFromServer(object stateInfo) // Please call this function once 
       { 
        print (" $$$$$$$$$$$ ReceiveFromServer and isConnectionActive"+isConnectionActive); 

        while(isConnectionActive) // receive message continuously 
        { 
         try 
         { 
          byte [] inStream = new byte[tcpClient.ReceiveBufferSize]; 

          serverStream.Read (inStream,0,(int)tcpClient.ReceiveBufferSize); 
          string returnData = System.Text.Encoding.UTF8.GetString(inStream); 

          print ("*^^^^^^^^^^* returnData"+returnData); 
          Decide_Action(returnData); 


         } 
         catch (Exception e) 
         { 
          c_global.isClientDisconnectOn = true; 
         } 


        } 

       } 



      public void Decide_Action(string returnData) 
      { 
      try 
      { 

      var r_Msg = JSONObject.Parse(returnData); // recieved message r_Msg 

      string msg = r_Msg.GetString("message") ; 

      print ("Message = "+msg); 

      switch(msg) // check the action to do 
      { 
      case "Players_List": 
      break; 
      } 

      } 

      catch (Exception e) 
      { 
          c_global.isClientDisconnectOn = true; 
      } 


      } 

게임이 가깝거나 서버에 의해 감지 클라이언트 연결 해제, 게임에서 종료합니다. 그것은 "닫기"기능이고 ​​"오류"기능은 그 시간을 호출합니다.

그러나 클라이언트 시스템이나 장치의 인터넷 연결이 끊어지면 그 "닫기"기능 또는 "오류"기능을 호출하지 않습니다.

하는 클라이언트 분리

클라이언트 순 단선 Node.js를 서버에서 감지되지 않는 이런 종류의를 감지하는 방법.

누구든지 해결책을 알고 있다면 도와주세요.

답변

0

가장 좋은 방법은 너무 많은 활동이 없을 때 발생하는 'timeout'이벤트를 처리하는 것입니다. 합리적인 기본값이 있지만 얼마나 오래 원하는지 설정할 수 있습니다.

http://nodejs.org/api/net.html#net_event_timeout

+0

timeout 이벤트를 사용하면 유휴 연결 또는 연결이 끊어진 연결을 구분할 수 없습니다. – Brad

+0

위의 좋은 점과 좋은 대답. – Paul

7

유휴 연결에서 잃어버린 연결을 구별 할 수 없습니다.

적어도, 직접적으로 약간의 수정없이 ...

TCP 연결은 데이터가 전송되지 않은 경우에도 살 수 있도록 설계되었습니다. 이제는 지금 연결하고 12 시간 동안 아무것도 보내지 않고 나중에 데이터를 다시 보낼 수 있습니다. 서버가 연결이 더 이상 존재하지 않는다고 가정해야합니까? 설계 상, 전송 장애가없는 한 연결이 있다고 가정합니다. 즉, 데이터가 전송되고 ACK가 없으면 연결은 결국 닫히고 적절한 이벤트 이됩니다.

해결 방법은 TCP 연결 유지를 사용하는 것입니다.socket.setKeepAlive(true, 10000)으로 전화를 걸면 유휴 상태가 된 후 10 초 후에 유휴 소켓에서 Keepalive 프로브 패킷 (데이터 페이로드가 0 바이트 인 TCP 패킷)을 유휴 소켓으로 보낼 수 있습니다. 원격 시스템은 이러한 패킷을 ACK합니다. 그렇지 않으면 연결이 끊어진 것으로 간주되고 찾고있는 이벤트가 실행됩니다.

더 많은 정보 :

+0

작동하지 않습니다. 동일한 문제가 존재합니다. –

+0

@LijuThomas 어떤 일이 발생했는지 알 수 있도록 패킷 캡처를 게시하십시오. – Brad

+0

누구든지 해결책을 알고 있다면 도와주세요. –

0

이 오래된 게시물입니다,하지만 난이 질문에 연습 할 수 있다고 생각 유래에 게시 새로운 오전입니다.따라서 여기에있다 : 연결이 유휴 상태 일 때마다 클라이언트가 서버에 명시 적으로 keep-alive 메시지 (전송 계층 대신 응용 프로그램 계층)를 보내는 일반적인 해결책이있다. 그런 다음 서버는 유휴 시간 초과를 추가하여 연결 및 클라이언트 상태를 식별 할 수 있습니다.

요약하면 연결이 끊어 졌는지 감지하기 위해 서버에 유휴 타이머가 필요합니다. 그리고 연결이 유휴 상태 일 때마다 연결 유지 메시지를 보내려면 클라이언트에 유휴 타이머가 필요합니다.

서버 의사 코드 :

const SERVER_TIMEOUT = 3000; 
var idle; 

function clientFailed() { 
    // Client has failed or the connection is bad 
} 

function onClientConnect() { 
    // Start connection health monitoring 
    idle = setTimeout(clientFailed, SERVER_TIMEOUT); 
} 

function onClientSendOrReceive() { 
    // make sure that the old timer does not trigger 
    clearTimeout(idle); 
    // Start a new idle timeout 
    idle = setTimeout(clientFailed, SERVER_TIMEOUT); 
} 

클라이언트 측 의사 코드 :

const CLIENT_TIMEOUT = 2000; // Should be less than the server timeout to account for normal network latency 
var idle; 

function sendKeepalive() { 
    // Send keepalive message to server 
} 

function onConnectToServer() { 
    // Start idle timer 
    idle = setTimeout(sendKeepalive, CLIENT_TIMEOUT); 
} 

function onSendOrReceiveMessage() { 
    // make sure that the old timer does not trigger 
    clearTimeout(idle); 
    // Start a new idle timeout 
    idle = setTimeout(sendKeepalive, CLIENT_TIMEOUT); 
} 
+0

이유가 없습니다. TCP keep-alive는 실제로 사용되면 정상적으로 작동합니다. 서버를 제어 할 때 응용 프로그램 계층을 활성 상태로 유지할 이유가 없습니다. – Brad

0

(현재)이 net.Servernet.Socket에서 방출되는 정의 된 disconnect 이벤트입니다. FIN 패킷을 받으면 net.Socket에서 해고 된 end event이 있습니다. keepalive을 사용하면 ACK이 정의 된 시간 제한 내에 있지 않으면 (소켓이 이 아니고이 자동으로 닫혀 있음) ACK이없는 경우 timeout이 트리거됩니다.