VB .NET - Pingando o servidor periodicamente


No artigo de hoje vamos mostrar como pingar um servidor remoto usando a linguagem VB .NET.

Vamos supor que você precisa criar uma aplicação VB .NET que envie um ping a um servidor remoto periodicamente para verificar o estado do servidor.

Neste artigo você vai aprender:

O VB .NET possui o namespace System.Net.NetWorkInterface que fornece acesso a dados de tráfego de rede, informações de endereço de rede e notificação de mudança de endereço para o computador local. O namespace também contém classes que implementam o utilitário Ping. Você pode usar Ping e as classes relacionadas para verificar se um computador está acessível através da rede.

Os métodos de Send e SendAsync da classe Ping enviam um solicitação Internet Control Protocol (ICMP) de eco para um computador remoto e aguarda uma mensagem de resposta de eco ICMP a partir desse computador.

O protocolo de mensagens de controle da Internet (ICMP) é um padrão TCP/IP necessário definido na RFC 792 "Internet Control Message Protocol (ICMP)" (disponível apenas em inglês). Com o ICMP, os hosts e roteadores que usam a comunicação IP podem relatar erros e trocar informações de status e controle limitado.

Geralmente, as mensagens ICMP são enviadas automaticamente em uma das seguintes situações:

  • Um datagrama IP não consegue chegar ao seu destino.
  • Um roteador IP (gateway) não consegue encaminhar datagramas na atual taxa de transmissão.
  • Um roteador IP redireciona o host remetente para usar uma rota melhor para o destino.

Fonte: http://technet.microsoft.com/pt-br/library/cc758065%28v=ws.10%29.aspx

A topologia da rede pode determinar se o ping pode conseguir contato com um host remoto. A presença e a configuração dos proxies, a existência de network address translation(NAT) ou firewalls podem impedir que o ping tenha sucesso.

Um ping bem sucedido indica apenas que o host remoto pode ser alcançado na rede, a presença de serviços de nível superior (como um servidor Web) no host remoto não está garantida.

A classe PingReplay fornece a informação sobre o status e dados resultantes de uma operação Send ou SendAsync.

O VB .NET também possui o objeto My.Computer.NetWork que fornece propriedades, eventos e métodos para interagir com a rede à qual o computador está conectado.

O método My.Computer.NetWork.Ping pode ser usado para pingar uma máquina remota conectada a máquina local e retorna um valor boleano indicando se a operação foi realizada com sucesso ou não.

Abaixo temos a sintaxe das sobrecargas disponíveis para este método:

Dim valor1 As Boolean = My.Computer.Network.Ping(nomeOuEnderecoHost)
Dim valor2 As Boolean = My.Computer.Network.Ping(endereco)
Dim valor3 As Boolean = My.Computer.Network.Ping(nomeOuEnderecoHost, timeout)
Dim valor4 As Boolean = My.Computer.Network.Ping(endereco, timeout)

Neste artigo eu vou mostrar duas maneiras bem simples de realizar um ping a um servidor remoto periodicamente.

Recursos usados:

Ping remoto com My.Computer.NetWork

Abra o Microsoft Visual Basic 2010 Express e clique em New Project;

Selecione o template Windows Forms Application e informe o nome PingarPeriodicamente1;

No formulário form1.vb inclua os seguintes controles:

Conforme o leiaute da figura abaixo:

A seguir no formulário form1.vb declare as variáveis

'variavel para controlar o numero de ticks
Private intervaloTempo As Integer = 0
Private _enderecoHostRemoto As String = "192.18.245.19"

A seguir basta declarar o código no evento Tick do controle Timer - pingTimer conforme abaixo:

Private Sub pingTimer_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles pingTimer.Tick
        '' verifica o tempo que passou
        If intervaloTempo >= 2 Then
            ' a cada 2 minutos reinicia o contador do tempo
            intervaloTempo = 0
            ' e faz o ping
            If My.Computer.Network.Ping(_enderecoHostRemoto) Then
                ' avisa que pingou
                lbPing.Items.Add("Ping no servidor " &_enderecoHostRemoto & " as " & Now.TimeOfDay.ToString())
            Else
                lbPing.Items.Add("Ping falhou (timeout) : " & Now.TimeOfDay.ToString())
            End If
        Else
            'se não passou 2 minutos incrementa o contador
            intervaloTempo += 1
        End If
    End Sub

O código irá ser executado após o intervalo de tempo definido na propriedade Interval do controle Timer.

No código estamos usando My.Computer.Network.Ping(_enderecoHostRemoto) para realizar o ping no endereço definido por _enderecoHostRemoto que no exemplo esta fixo no código.

Executando o projeto iremos obter o seguinte resultado:

Tudo bem ! O código funciona mas esta longe de ser um código que 'cheira bem'.

O que eu quero dizer com: "o código não cheira bem" ?

Para responder a essa pergunta temos que fazer outra: "Aonde quero chegar com este código?"

O seu objetivo foi organizar seu código para torná-lo mais fácil de escrever, de entender e de alterar depois ?

Se esse foi o objetivo, fracassamos, pois o código acima não pode ser reutilizado.

Ele pode até servir para um protótipo ou teste rápido que será descartado em seguida.

Ping remoto melhorado

Vamos então tentar melhorar um pouco o nosso código. Para isso vamos incluir outro projeto na solução clicando no menu File -> Add -> New Project;

Selecione o template Windows Forms Application e informe o nome PingarPeriodicamente2;

No formulário form1.vb inclua os seguintes controles:

Conforme o leiaute da figura abaixo:

Vamos então criar uma classe que será responsável por realizar o ping no servidor e logar o resultado em um arquivo texto.

No menu Project clique em Add Class e informe o nome Pingador.vb incluindo o código abaixo neste arquivo:

Imports System.IO
Imports System.Net.NetworkInformation

Public Class Pingador

    'variavel para controlar o numero de ticks 
    Private intervaloTempo As Integer = 0
    Private _logArquivoWriter As StreamWriter
    Private _enderecoHostRemoto As String
    Private _ping As Ping
    Private WithEvents _pingTimer As New System.Windows.Forms.Timer()

    'construtor da classe 
    Sub New(ByVal enderecoIP As String)

        'define o IP
        _enderecoHostRemoto = enderecoIP

        'define as propriedades e habilita o timer
        _pingTimer.Interval = 500
        _pingTimer.Enabled = True
        _pingTimer.Start()

        'cria a instãncia da classe FileStream
        Dim fileStream As IO.FileStream = File.Open("logPingServidor_" & Now.Day & Now.Month & Now.Year & ".txt",
 FileMode.Append, FileAccess.Write)
        Me._logArquivoWriter = New StreamWriter(fileStream)
        'cria uma instância da classe Ping
        _ping = New Ping()

    End Sub

    ' Este método que é executado quando o timer for disparado
    Private Sub TimerEventProcessor(ByVal myObject As Object, ByVal myEventArgs As EventArgs) Handles _pingTimer.Tick
        If intervaloTempo >= 2 Then
            ' a cada 2 minutos resta o o contador do tempo
            intervaloTempo = 0
            ' faz o ping e loga o ping
            PingarHostRemoto()
        Else
            'se não passou 2 minutos incrementa o contador
            intervaloTempo += 1
        End If
    End Sub
    Private Sub PingarHostRemoto()

        ' Exibe a data hora que tentemos pingar no servidor
        Me._logArquivoWriter.Write("[")
        Me._logArquivoWriter.Write(System.DateTime.Now.ToString())
        Me._logArquivoWriter.Write("] ")

        Try
            Dim reply As PingReply = Me._ping.Send(Me._enderecoHostRemoto, 3000)

            If reply.Status = IPStatus.Success Then
                Me._logArquivoWriter.Write("Resposta ICMP recebida com sucesso de  ")
                Me._logArquivoWriter.Write(Me._enderecoHostRemoto)
                Me._logArquivoWriter.Write(". Tempo de ida e volta : ")
                Me._logArquivoWriter.Write(reply.RoundtripTime)
                Me._logArquivoWriter.Write(" milisegundos.")
            Else
                Me._logArquivoWriter.Write("Resposta ICMP não foi concluída com sucesso de  ")
                Me._logArquivoWriter.Write(Me._enderecoHostRemoto)
                Me._logArquivoWriter.Write("Status da resposta ICMP : ")

                Me._logArquivoWriter.Write(reply.Status)
            End If
        Catch ex As Exception
            Me._logArquivoWriter.Write("Foi encontrado um problema durante o ping ")
            Me._logArquivoWriter.Write(Me._enderecoHostRemoto)
            Me._logArquivoWriter.Write(". Mensagem de Erro: ")
            Me._logArquivoWriter.Write(ex.Message)

        End Try

        Me._logArquivoWriter.WriteLine()
        Me._logArquivoWriter.Flush()

    End Sub

End Class

Neste código instanciando via código um controle Timer e tratando o evento Tick na classe Pingador logando os resultados em um arquivo texto.

O código do formulário onde no evento Click estamos criando uma instância da classe Pingador e disparando assim o ping no servidor remoto para o IP informado:

Imports System.IO
Imports System.Net.NetworkInformation

Public Class Form1

    Private Sub btnPing_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnPing.Click
        Dim pinga As Pingador
        If String.IsNullOrEmpty(txtIPServidor.Text) Then
            MessageBox.Show("Informe o número IP do servidor remoto. ", "IP", MessageBoxButtons.OK, MessageBoxIcon.Information)
        Else
            lbPing.Items.Add("Iniciando o ping no servidor " & txtIPServidor.Text & Now.Date.ToString())
            pinga = New Pingador(txtIPServidor.Text)
        End If
    End Sub

End Class

Abaixo vemos o resultado da execução deste projeto:

Podemos melhorar ainda mais o código separando a responsabilidade de logar no arquivo da classe Pingador dessa forma a classe saberia apenas pingar no servidor e outra classe saberia apenas criar o arquivo de log com responsabilidades bem distintas e código independente.

Pegue o projeto completo aqui: PingarPeriodicamente.zip

João 8:45 Mas porque eu digo a verdade, não me credes.

João 8:46 Quem dentre vós me convence de pecado? Se digo a verdade, por que não me credes?

João 8:47 Quem é de Deus ouve as palavras de Deus; por isso vós não as ouvis, porque não sois de Deus.

             Gostou ?   Compartilhe no Facebook   Compartilhe no Twitter

Referências:


José Carlos Macoratti