2014-12-08 3 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; 
      } 


      } 

Когда игра близка или выйти из игры, отключение клиента обнаружения сервера. Это функция «закрыть», и функция «ошибка» вызывает это время.

Но при отключении Интернета от клиентской системы или устройства функция «закрыть» этого времени или функция «ошибка» не звонит.

Как обнаружить этот вид клиента отключения

Client Net разъединение не обнаруживая на сервере Node.js.

Пожалуйста, помогите мне, если кто-нибудь знает решение.

ответ

0

Лучший способ - это, вероятно, обработать событие «тайм-аут», которое запускается, когда происходит слишком много бездействия. Вы можете установить, как долго вы хотите, чтобы это было так хорошо, хотя есть разумное значение по умолчанию.

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

+0

С событием тайм-аута невозможно провести различие между простоями или мертвым соединением. – Brad

+0

Справедливая точка, и хороший ответ выше. – Paul

7

Это не представляется возможным дифференцировать потерю соединения от простоя соединения.

По крайней мере, непосредственно не без некоторой модификации ...

соединения TCP предназначены, чтобы жить, даже если никакие данные не передаются. Вполне возможно сделать соединение сейчас, ничего не отправлять в течение 12 часов и отправлять данные позже. Должен ли сервер предположить, что соединение больше не существует? По дизайну он предполагает, что есть соединение, если нет отказа передачи. То есть, если данные отправляются и нет ACK, соединение в конечном счете будет закрыто, а соответствующие события будет пожара.

Решение заключается в использовании протокола TCP keepalive. Если вы вызываете socket.setKeepAlive(true, 10000), вы включаете контрольные пакеты keepalive (фактически пакеты TCP с 0 байтами полезной нагрузки данных), которые должны быть отправлены на нерабочее гнездо через 10 секунд после простоя. Удаленная система будет активировать эти пакеты. Если это не так, соединение в конечном итоге считается потерянным, и события, которые вы ищете, будут срабатывать.

Дополнительная информация:

+0

Не работает. Такая же проблема существует –

+0

@LijuThomas Опубликовать захват пакетов, чтобы мы могли видеть, что происходит. – Brad

+0

Пожалуйста, помогите мне, если кто-нибудь знает решение. –

0

Это старый пост, но так как я новичок размещения на StackOverflow я думал, что я мог бы практиковать по этому вопросу.Итак, вот так:

Общее решение заключается в том, чтобы клиент отправлял явное сообщение о сохранении (прикладной уровень вместо транспортного уровня) на сервер всякий раз, когда соединение простаивает. Затем сервер может идентифицировать проблемы с соединением (и клиентом), добавляя тайм-аут простоя.

Вкратце: на сервере требуется таймер простоя, чтобы определить, потерян ли соединение. И вам нужен таймер простоя в клиенте, чтобы обеспечить отправку сообщения 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

Существует (в настоящее время) нет disconnect событие определено, выход из net.Server ни net.Socket. Существует end event, уволен из net.Socket при получении пакета FIN. Когда используется keepalive, timeout будет запущен, если нет ACK с другого конца в течение установленного таймаута (также обратите внимание, что в этом случае автоматически закрывается сокет , а не).