segunda-feira, 13 de fevereiro de 2017

Node.js SNMP Socket.io

Neste post farei um "upgrade" do post anterior:


No post acima foi dado uma sugestão de como se criar um agente com o serviço do windows para poder escrever scripts do gerente e testar.
Vamos agora ler 02 OIDs de uma MIB e apresentá-la em um navegador através de uma simples interface gráfica.

Através de um diagrama de blocos podemos mostrar o funcionamento:



























Como pode ser observado o navegador através do request ao servidor recebe um response usando o protocolo HTTP na porta 80, nesta requisição é passado os scripts de HTML, CSS e Javascript para o navegador.
Uma vez que estes arquivos passem a rodar no navegador temos a interface gráfica e o socket.io cliente que efetuará a conexão com o socket.io server  na porta 3000 usando um protocolo que não necessita de ficar realizando request e response todo o tempo, pois é conectado full time.
Quando  o socket.io cliente solicita ao socket.io server este aciona o net-snmp que faz a requisição de dados de uma MIB no Agent.
Deixei a interface gráfica muito simples para não complicar a ideia da lógica dos trabalhos dos scripts:























Neste caso fornecemos o IP onde está o agente e 02 OIDs separados por "/" como pode ser observado na figura e obtemos a resposta do agente SNMP.
O socket.io cliente passa a string ip/oid/oid para o socket.io server e  é tratada através da função split.
O IP do gerente quando carregado a página por default é o mesmo IP do servidor que forneceu a página HTML porém se quiser acionar outro gerente em outro IP é possivel pois o botão Conectar estabelece a conexão do socket.io cliente com o server usando o IP que está na caixa de dialogo IP Gerente.
Para este projeto criei uma pasta web_Socket.io_Snmp e foi colocado duas pastas e um arquivo dentro:






















A pasta node_modules é criada a partir do momento que se instala os modulos através do comamdo npm install.
Para isto estando com o prompt do Dos e dentro da pasta criada digite um comando por vez:

> npm install express --save
>npm install net-snmp --save
>npm install request --save
>npm install socket.io --save

A pasta node_modules será criada com estes arquivos dentro.
O arquivo server.js é um script que vamos escrever e será comentado abaixo
A pasta do navegador tem os arquivos que serão transferidos para o navegador e pode ser vista na figura abaixo:






















Na pasta navegador temos os arquivos index.html, index.css, e index.js que são scripts que escreveremos e será comentada abaixo.
A pasta socket.io deve ser copiada da pasta node_modules como ser visto na figura abaixo:






















Na figura acima mostra a pasta onde está o arquivo socket.io cliente que rodará no navegador

Uma vez que todos os módulos estão carregados podemos analisar os scripts.
A parte da interface gráfica feita pelo index.html  e index.css bastante trivial e por isto poucos comentários a respeito:

<!DOCTYPE html>
<html>
<head>
<title>Page Title</title>
<META HTTP-EQUIV="Pragma" CONTENT="no-cache">

<link rel="stylesheet" href="index.css">

<script src= "https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"> </script>

<script type= "text/javascript" src= "/socket.io-client/socket.io.js"> </script> 

<script type= "text/javascript" src= "index.js"> </script> 

</head>


<body>


<div id="divComando">

<span style="color:blue" id="spIpAgent"> IP Agent </span>
<input type="text" id="txtIpAgent" value= "192.168.0.30"> <br>
<span style="color:blue" id="spIpGerente"> IP Gerente </span>
<input type="text" id="txtIpGerente" value= "127.0.0.1"> <br>
<span style="color:blue" id="spOID"> OIDs </span>
<input type="text" id="txtOID" value= "1.3.6.1.2.1.1.1.0/1.3.6.1.2.1.1.3.0"> <br>
<input type="submit" id="btPesquisar" value="Pesquisar" />
 <input type="submit" id="btConectar" value="Conectar" />

<textarea id="txtMsg">Envia IP e OIDs e recebe as leituras do Agent   </textarea>
  
    </div>

</body>
</html>

Podemos observar que o Jquery foi baixado através da tag: 
<script src= "https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"> </script>
Pode-se optar por adicionar o arquivo da Jquery na pasta do navegador e baixar do servidor que estamos escrevendo
O socket.io cliente foi baixado através da tag:
<script type= "text/javascript" src= "/socket.io-client/socket.io.js"> </script> 
Esta tag leva ao endereço da pasta que foi copiada do node_modules para a pasta do navegador.

Com relação aos arquivo index.css foi usado somente tratamento aos IDs dos elementos do HTML e segue abaixo:

#divComando
  
    background:#ccccdd;
    color: #000000;
    position:absolute;
    float: left;
    float: top;
    left:1px;
    top:10px;
    width:1000px;
    height:600px;
    border: 2px solid;
    border-radius: 0px;    
}

#divComando #spIpAgent
{
    width: 100px; 
    position:absolute;
    float: left;
    float: top;
    left:1px;
    top:5px;
    font-size: 15px;
    font-family: Arial Black;
    font-style: oblique;
    text-align: center; 
}

#divComando #txtIpAgent
{
    width: 20%; 
    position:absolute;
    float: left;
    float: top;
    left:100px;
    top:5px;
    font-size: 15px;
    font-family: Arial Black;
    font-style: oblique;
    text-align: center; 
}

#divComando #spIpGerente
{
    width: 100px; 
    position:absolute;
    float: left;
    float: top;
    left:450px;
    top:5px;
    font-size: 15px;
    font-family: Arial Black;
    font-style: oblique;
    text-align: center; 
}

#divComando #txtIpGerente
{
    width: 20%; 
    position:absolute;
    float: left;
    float: top;
    left:550px;
    top:5px;
    font-size: 15px;
    font-family: Arial Black;
    font-style: oblique;
    text-align: center; 
}
#divComando #spOID
{
    width: 20px; 
    position:absolute;
    float: left;
    float: top;
    left:1px;
    top:35px;
    font-size: 15px;
    font-family: Arial Black;
    font-style: oblique;
    text-align: center; 
}
#divComando #txtOID
{
    width: 90%; 
    position:absolute;
    float: left;
    float: top;
    left:50px;
    top:35px;
    font-size: 15px;
    font-family: Arial Black;
    font-style: oblique;
    text-align: left; 
}

#divComando #btConectar
{
    position:absolute;
    float: left;
    float: top;
    left:390px;
    top:65px;
    width: 10%;
    font-size: 13px;
    font-family: Arial Black;
    font-style: oblique;
    text-align: center;
}
#divComando #btPesquisar
{
    position:absolute;
    float: left;
    float: top;
    left:510px;
    top:65px;
    width: 10%;
    font-size: 13px;
    font-family: Arial Black;
    font-style: oblique;
    text-align: center;
}
#divComando #txtMsg
{
    width: 90%; 
    height:450px;
    position:absolute;
    float: left;
    float: top;
    left:50px;
    top:100px;
    font-size: 10px;
    font-family: Arial Black;
    font-style: oblique;
    text-align: left; 
}

Agora vamos ao arquivo do server.js:

//========Variaveis Globais e  Modulos =======================
var  static = require( 'node-static' );
var  http = require( 'http' );
var  snmp = require ("net-snmp");

var   port = 80;


var app = require('express')()
var server = require('http').createServer(app);
var io = require('socket.io').listen(server);


var msgOid=[];
var msgValue=[];
var oids = [];
var ipAgent;

var soquete;
var session;




//===Servidor HTML arquivos da pasta navegador sao enviados ao cliente=========
var file = new static.Server( './navegador', {
    cache: 3600,
    gzip: true
} );

http.createServer( function ( request, response ) {
    request.addListener( 'end', function () {
        file.serve( request, response );
    } ).resume();
} ).listen( port );

//===============Servidor socket.io===================

server.listen(3000, function(){
   console.log("Socket.io Escutando a porta 3000...");
 });


io.sockets.on('connection', function (socket) {

   soquete=socket;//soquete variavel global socket variavel local

    socket.on('toServer', function (data) {//Recebe mensagem de algum Cliente Conectado

    console.log("Do Cliente--> " + data);
    snmpSolicitado(data);

      //socket.broadcast.emit('toClient', data);//Emite para todos clientes menos o emitente
      //socket.emit('toClient', data);//Somente o emitente recebe retorno do Servidor
    
   }); 


    socket.on('toLogin', function (data) {//Recebe mensagem de login

    console.log("Do Cliente--> " + data);
    
   });  



   
});

//============Analisa a mensagem que vem do cliente==========================

function snmpSolicitado(msgSnmp)
{

  var vetorMsg=msgSnmp.split("/");
  var ipAgent=vetorMsg[0].trim();

  var strOid1=vetorMsg[1].trim();
  var strOid2=vetorMsg[2].trim();

  oids[0]=strOid1;
  oids[1]=strOid2;

  session = snmp.createSession (ipAgent, "public");

  getSecaoSnmp();

}


//========Conexao com o Agent SNMP================================

function getSecaoSnmp()
{

  session.get (oids, function (error, varbinds)
 {
    if (error) 
    {
        console.error (error);
    } 
    else
    {
        for (var i = 0; i < varbinds.length; i++)
        {
            if (snmp.isVarbindError (varbinds[i]))
            {
                console.error (snmp.varbindError (varbinds[i]));

            }
               
            else
            {
                //console.log (varbinds[i].oid + " = " + varbinds[i].value);

                msgOid[i]=varbinds[i].oid.toString();
                msgValue[i]=varbinds[i].value.toString();

                //console.log(msgOid[i] + "-->" + msgValue[i] ); 

                soquete.emit('toClient', msgOid[i] + "-->" + msgValue[i]);//Envia ao cliente


            }                
        }                  
    }
});


}

Foi dividido em blocos para a melhor compreenção:
  • As variaveis globais e modulos.
  • O servidor estático que efetua a transferência de arquivos para o navegador.
  • O socket.io server que recebe e envia as mensagens para o socket.io client.
  • Analisa a mensagem chegada do Navegador.
  • Finalmente a parte que faz a conexão com o Agent de SNMP.
Vale ressaltar aqui que a linha: 

soquete.emit('toClient', msgOid[i] + "-->" + msgValue[i]);//Envia ao cliente

Envia a mensagem para o cliente e o script index.js que roda no navegador receberá este evento identificando através da palavra chave toCliente, veja o trecho que no script do navegador tratará este envio do servidor:

 socket.on('toClient', function (msg) {//Evento que recebe mensagem do socket.io   
    setLogs("Mensagem recebida-->" + msg + "\n");
    });

Então a função socket.emit associa uma chave que o receptor ( navegador ou servidor) identifica e sabe qual tratamento aplicar.
Desta forma com nome de chaves diferentes podemos identificar que tratamento queremos dar a mensagem enviada.

Por último vamos ao script do navegador que estará conectado através do socket.io ou seja o index.js:

var ipAgent,ipGerente,endereco;
var oids;
var msg;
var socket, io;


//==========Funcoes chamadas apos carregar HTML=================

$(document).ready(function () {//Aguarda carregar HTML

    ipGerente = location.host;//Ip onde o Navegador se conectou Default
    $("#txtIpGerente").val(ipGerente);//Preenche a caixa Ip Gerente


    $("#btConectar").click(function () {//Click no botao Conectar

        conectaServidor();//Estabelece conexao socket.io
       
    }); //fim click botao Conectar


$("#btPesquisar").click(function () {//Click no botao Pesquisar

  setLogs("\n");//Insere linha branca entre pesquisas
  ipAgent = $("#txtIpAgent").val().trim();//Le o IP da caixa texto
       oids = $("#txtOID").val().trim();//Le o OID da caixa texto
       msg=ipAgent + "/" + oids;//Mensagem a ser enviada para o servidor
       setLogs("Mensagem Enviada-->" + msg + "\n");//Mensagem enviada ao servidor
       socket.emit('toServer', msg);//Envia mensagem atraves do socket.io

    }); //fim click botao Pesquisar
  
});


//==Funcao para conectar o Servidor Node.js para receber/Enviar WS==============
function conectaServidor()
{

    ipGerente=$("#txtIpGerente").val().trim();//Le a caixa IP Gerente

    endereco= "http://" + ipGerente + ":3000";//Endereco do servidor socket.io

    setLogs("Conectado-->"+ endereco + "\n" );

    socket = io.connect(endereco);

    socket.emit('toLogin', "Entrou um  cliente \n" );//Log no Servidor de Entrada de Cliente

    socket.on('toClient', function (msg) {//Evento que recebe mensagem do socket.io   
    setLogs("Mensagem recebida-->" + msg + "\n");

    });

}

//========Funcao para Imprimir na Area de Texto======================
function setLogs(msg)
{

$("#txtMsg").append(msg);

}

Foi usado o Jquery para tratar a lógica dos elementos HTML e podemos ver que esperamos carregar todos os elementos HTML antes de chamar funções que vão manipular os mesmos.

Fazemos a requisicão dos arquivos HTML,CSS, Javascript através da porta 80 e a conexão com o socket.io através da porta 3000.

Tive alguns problemas quando o navegador armazenava os scripts em cache e não atualizava quando modificava o código as vezes foi necessário limpar os dados de navegação da máquina.

Estes scripts podemos ver 02 OIDs mas dá para ser alterado no trecho do server.js onde analisa as mensagens recebidas do navegador colocando-se um loop for para ler um array maior, mas isto vou deixar para os programadores.....

function snmpSolicitado(msgSnmp)
{

  var vetorMsg=msgSnmp.split("/");
  var ipAgent=vetorMsg[0].trim();

  var strOid1=vetorMsg[1].trim();
  var strOid2=vetorMsg[2].trim();

  oids[0]=strOid1;
  oids[1]=strOid2;

  session = snmp.createSession (ipAgent, "public");

  getSecaoSnmp();

}

Os códigos estão bem comentados e é fácil de implementar.

Espero ter contribuido com alguma ideia.

Até a próxima.











Nenhum comentário:

Postar um comentário