Delphi CAP 9 Desenvolvendo utilitários para Internet

download Delphi CAP 9 Desenvolvendo utilitários para Internet

of 32

Transcript of Delphi CAP 9 Desenvolvendo utilitários para Internet

  • 8/2/2019 Delphi CAP 9 Desenvolvendo utilitrios para Internet

    1/32

    Desenvolvendo utilitrios para Internet 127

    Captulo 9

    Desenvolvendo utilitrios para Internet

    Neste captulo, iremos desenvolver uma srie de utilitrios para Internet.

    Portas Abertas: Seja Bem-Vindo

    O primeiro utilitrio visa alertar aos amigos leitores sobre um grave problema:Portas Abertas.

    Quantos de vocs trancam a porta de suas casas ao anoitecer, ou at mesmo luz do dia? Acredito que a maioria. Com o forteavano da Internet em todo o planeta, nos deparamos com o mesmo problema em nossos computadores:Portas Abertas.Nestecaptulo iremos desenvolver um aplicativo parascanneare apresentar as portas que esto abertas num determinado servidor.

    Para facilitar a compreenso de todos, estou apresentando um exemplo muito simples, onde o usurio informa o Nome doServidor (ou endereo IP) e o intervalo de portas a serem scanneadas. Os leitores com conhecimentos mais avanados ouknow-how em Threads iro me crucificar por falta das benditas. Acontece que o principal objetivo deste exemplo demonstraro uso do componente TCPClient, e no do uso de Threads. Isso iria complicar um pouco a compreenso dos nossos amigosleitores. Aos amigos que se encaixam neste perfil, minhas sinceras desculpas. Bem, continuando, agora vem a parte boa: mo-na-massa.

    Vamos iniciar um novo projeto no Delphi (grave a unitcomo un_scan.pas e o projeto comopscan.drp) e inserir os objetos queseguem:

    OBJETO

    pnTopo TPanel

    Objeto Propriedade Valor

    TPanel Align alTop

    Caption

    Name pnTopo

    127

  • 8/2/2019 Delphi CAP 9 Desenvolvendo utilitrios para Internet

    2/32

    128 Delphi 7 Internet e Banco de Dados

    Com o foco no objetopnTopo insira os seguintes objetos:

    OBJETO

    Label1 TLabel

    Objeto Propriedade Valor

    TLabel Caption HOST

    Left 16

    Top 14

    OBJETO

    Label2 TLabel

    Objeto Propriedade Valor

    TLabel Caption Porta Inicial

    Left 16

    Top 43

    OBJETO

    Label3 TLabel

    Objeto Propriedade Valor

    TLabel Caption Porta Final

    Left 232

    Top 43

    Agora vamos inserir os objetos de controle e interatividade com o usurio. Mantenha o foco no objeto pnTopo e insira osseguintes objetos:

    OBJETO

    NomeServidor TEdit

    Objeto Propriedade Valor

    TEdit Name NomeServidor

    Left 104

    Top 10

    Width 290

    OBJETO

    Inicio TSpinEdit [Samples]

    Objeto Propriedade Valor

    TSpinEdit Name Inicio

    Left 104

    Top 40

  • 8/2/2019 Delphi CAP 9 Desenvolvendo utilitrios para Internet

    3/32

    Desenvolvendo utilitrios para Internet 129OBJETO

    Fim TSpinEdit [Samples]

    Objeto Propriedade Valor

    TSpinEdit Name Fim

    Left 320Top 40

    Neste ponto vamos inserir o boto para iniciar o processo descanner de portas.

    OBJETO

    btScan TButton

    Objeto Propriedade Valor

    TButton Name btScan

    Caption Scan

    Left 416

    Top 8

    Com isso conclumos a primeira etapa do projeto.

    Prosseguindo, vamos criar o mdulo de sada das informaes. Agora com o foco no formulrio e no mais no objetopnTopo,insira um objeto do tipo Tpanelalterando as seguintes propriedades:

    OBJETO

    pnDados TPanel

    Objeto Propriedade Valor

    TPanel Align alClientName pnDados

    Vamos inserir os objetos deste painel, como segue:

    OBJETO

    ListadePortas TMemo

    Objeto Propriedade Valor

    TMemo Name ListadePortas

    Height 180

    Left 16Top 76

    Width 500

    Dentro deste mesmo painelpnDados, insira outro objeto do tipo TPanelalterando as propriedades que seguem:

  • 8/2/2019 Delphi CAP 9 Desenvolvendo utilitrios para Internet

    4/32

    130 Delphi 7 Internet e Banco de Dados

    OBJETO

    PnProgresso TPanel

    Objeto Propriedade Valor

    TPanel Name pnProgresso

    CaptionHeight 65

    Left 16

    Top 8

    Width 500

    Amigos, sei que um pouco cansativo, mas estamos quase no final. Com o foco no objeto pnProgresso insira os seguintesobjetos:

    OBJETO

    btParar TButton

    Objeto Propriedade Valor

    TButton Name btParar

    Caption Parar

    Left 400

    Top 32

    OBJETO

    ProgressBar1 TProgressBar

    Objeto Propriedade Valor

    TProgressBar Name ProgressBar1

    Left 16

    Top 8

    Width 470

    OBJETO

    Label4 TLabel

    Objeto Propriedade Valor

    TLabel Caption Scaneando Porta...

    Left 16

    Top 36

  • 8/2/2019 Delphi CAP 9 Desenvolvendo utilitrios para Internet

    5/32

    Desenvolvendo utilitrios para Internet 131OBJETO

    porta TLabel

    Objeto Propriedade Valor

    TLabel Caption 0

    Left 112Top 36

    Ufa!!! E para concluir a enorme lista de objetos, insira um do tipo TTCPClientque se encontra na seoInternet.

    OBJETO

    TCPClient1 TTCPClient [Internet]

    Objeto Propriedade Valor

    TTCPClient Name TCPClient1

    Finalmente vamos codificar o nosso projeto. Crie uma varivel global pertencente nossa classe Form1., com o nomeParar,do tipoInteger; veja:

    var

    Form1: TForm1;parar:integer; // variavel auxiliar

    implementation

    A varivel Pararser utilizada para finalizar o processo de Scanner das Portas. Neste ponto que poderamos criar umaThread, mas no vamos complicar.

    S para aliviar um pouco a forte tenso, vamos dar uma olhadinha na interface do nosso projeto (figura 9.1):

    Figura 9.1 Projeto Port Scanner

  • 8/2/2019 Delphi CAP 9 Desenvolvendo utilitrios para Internet

    6/32

    132 Delphi 7 Internet e Banco de Dados

    Vamos codificar o boto btScan, responsvel pelo ncleo do nosso projeto. No evento onClickdo objeto btScan, insira ocdigo que segue (para facilitar, numerei as linhas de programao, de forma que possamos analisar melhor o cdigo).

    001002003004

    005006007008009010011012013014015016017018019

    020021022023024025026027028029

    030031

    032033034035036037038039

    040041042

    procedure TForm1.BtScanClick(Sender: TObject);var i:integer;begintry

    ListadePortas.Clear; // Limpa a Lista de Portas

    parar:=0; // 0 = continua, 1 = conclui

    // Definies da barra de progresso

    ProgressBar1.Max:=Fim.Value;ProgressBar1.Min:=Inicio.Value;

    PainelProgresso.Visible:=True;TcpClient1.RemoteHost := NomeServidor.Text;

    for i := Inicio.Value to Fim.Value dobeginif parar=1 then break; // finaliza o lao

    ProgressBar1.Position:=i;porta.Caption:=inttostr(i);

    Application.ProcessMessages;TcpClient1.RemotePort := inttostr(i);TcpClient1.Active:=true;

    if TcpClient1.Connect thenListadePortas.Lines.Add('Porta ['+ inttostr(i) + ']

    aberta');

    TcpClient1.Disconnect; // disconeta porta

    end; //for loopexcepton E:Exception dobegin

    ListadePortas.Lines.Add('Erro: ' + E.Message);end; // end on do begin

    end; //try block

    ListadePortas.Lines.Add('Scaneamento das portas finalizado !');

    PainelProgresso.Visible:=False;end;

    Vamos ao detalhamento do cdigo:A linha 002 declara uma varivel i que ir auxiliar no lao de contagem das portas.

    var i:integer;

    Na linha 004 iniciamos uma proteo de erros da aplicao.

  • 8/2/2019 Delphi CAP 9 Desenvolvendo utilitrios para Internet

    7/32

    Desenvolvendo utilitrios para Internet 133try

    A linha 005 limpa o contedo do objetoListaPortas.

    ListadePortas.Clear

    Na linha 007 inicializamos a varivelpararcom o valor 0, de forma que o sistema continue scanneando as portas at o limitesolicitado pelo usurio, ou atravs do pressionamento da tecla Parar, fazendo com que a varivel receba o valor 1.

    parar:=0;

    As linhas 011 e 012 configuram o objeto ProgressBar1 de maneira que o mesmo fique compatvel com as informaes portainicial e final. Com isso temos um progresso adequado.

    ProgressBar1.Max:=Fim.Value;ProgressBar1.Min:=Inicio.Value;

    A linha 014 torna visvel o objetoPainelProgresso.

    PainelProgresso.Visible:=True;

    A linha 015 configura o servidor remoto do objeto TcpClient1.

    TcpClient1.RemoteHost := NomeServidor.Text;

    A linha 017 inicia um loop baseado nas informaesPorta Inicial e Final.

    for i := Inicio.Value to Fim.Value do

    J na linha 019 nossa aplicao verifica se existe a obrigao de paralisar o loop. Esta informao vem do boto btParar.

    if parar=1 then break;

    A linha 021 posiciona a barra de progresso em relao ao andamento do loop.

    ProgressBar1.Position:=i;

    Na linha 022 apenas mostramos ao usurio atravs do objetoPorta, qualporta est sendoscanneada no momento.

    porta.Caption:=inttostr(i);

    A linha 024 solicita ao Windows que processe as informaes da aplicao, de maneira que a mesma no tenha o efeitocongelamento.

    Application.ProcessMessages;

    A linha 025 configura a porta que deve serscanneada, a 026 tenta ativar, e a 028 verifica se houve sucesso na ativao, e emcaso afirmativo, a linha 029 adiciona no objetoListadePortas a informao de que aPorta est aberta.

    TcpClient1.RemotePort := inttostr(i);TcpClient1.Active:=true;

    if TcpClient1.Connect thenListadePortas.Lines.Add('Porta ['+ inttostr(i) + '] aberta');

    A linha 031 desconecta a porta independente do seu estado (aberta ou fechada).

  • 8/2/2019 Delphi CAP 9 Desenvolvendo utilitrios para Internet

    8/32

    134 Delphi 7 Internet e Banco de Dados

    TcpClient1.Disconnect;

    A linha 032 finaliza o loop. As linhas 033, 034 e 035 tratam qualquer exceo ocorrida no bloco protegido (try...except...end).

    end; //for loopexcept

    on E:Exception dobeginListadePortas.Lines.Add('Erro: ' + E.Message);end; // end on do begin

    end; //try block

    Concluindo esta rotina, a linha 039 apresenta uma mensagem indicando o fim do scanneamento das portas e a 041 torna oobjetoPainelProgresso invisvel.

    ListadePortas.Lines.Add('Scaneamento das portas finalizado !');

    PainelProgresso.Visible:=False;

    Para concluir o nosso projeto, devemos codificar o boto btPararcom o seguinte cdigo (no evento OnClick):

    Parar:=1;

    Amigos, agora s executar o aplicativo, informar o nome do servidor (caso seja seu prprio equipamento, digite localhost, nocampoNome do Servidor), e o intervalo de portas a serem scanneadas. A figura 9.2 ilustra nosso utilitrio scanneando umservidor.

    Figura 9.2 Scanner em ao

    IMPORTANTE

    Embora seja possvel, no recomendo o uso deste aplicativo parascannearportasde servidores no-autorizados.

    Normalmente utilizamos este tipo de aplicativo para vigiar nosso quintal e no odo vizinho.

    Artigo originalmente publicado na Revista The Club, n 94

  • 8/2/2019 Delphi CAP 9 Desenvolvendo utilitrios para Internet

    9/32

    Desenvolvendo utilitrios para Internet 135Listagem 9.1

    unit un_scan;

    interface

    uses

    Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,Dialogs, StdCtrls, IdBaseComponent, IdComponent, IdTCPConnection,IdTCPClient, Sockets, ComCtrls, ExtCtrls, Spin;

    typeTForm1 = class(TForm)TcpClient1: TTcpClient;pnTopo: TPanel;BtScan: TButton;NomeServidor: TEdit;Label2: TLabel;Panel2: TPanel;ListadePortas: TMemo;PainelProgresso: TPanel;ProgressBar1: TProgressBar;Label1: TLabel;porta: TLabel;Inicio: TSpinEdit;Label3: TLabel;Label4: TLabel;Fim: TSpinEdit;btParar: TButton;procedure BtScanClick(Sender: TObject);procedure btPararClick(Sender: TObject);

    private{ Private declarations }

    public{ Public declarations }

    end;

    varForm1: TForm1;parar:integer; // variavel auxiliar

    implementation

    {$R *.dfm}

    procedure TForm1.BtScanClick(Sender: TObject);var i:integer;begintry

    ListadePortas.Clear; // Limpa a Lista de Portas

    parar:=0; // 0 = continua, 1 = conclui

    // Definies da barra de progresso

    ProgressBar1.Max:=Fim.Value;ProgressBar1.Min:=Inicio.Value;

  • 8/2/2019 Delphi CAP 9 Desenvolvendo utilitrios para Internet

    10/32

    136 Delphi 7 Internet e Banco de Dados

    PainelProgresso.Visible:=True; // Visualiza painel progresso

    TcpClient1.RemoteHost := NomeServidor.Text; // define o HOST

    for i := Inicio.Value to Fim.Value dobegin

    if parar=1 then break; // finaliza o lao

    ProgressBar1.Position:=i; // atualiza ProgressBarporta.Caption:=inttostr(i); // atualiza Label Porta

    Application.ProcessMessages; // solicita ao Windows prioridade noprocessamento da aplicao

    TcpClient1.RemotePort := inttostr(i); // define porta a ser scaneada

    TcpClient1.Active:=true; // tenta ativar a porta

    if TcpClient1.Connect thenListadePortas.Lines.Add('Porta ['+ inttostr(i) + '] aberta');

    TcpClient1.Disconnect; // disconecta porta

    end; //for loopexcepton E:Exception do begin

    ListadePortas.Lines.Add('Erro: ' + E.Message);end; // end on do begin

    end; //try block

    ListadePortas.Lines.Add('Scaneamento das portas finalizado!');

    PainelProgresso.Visible:=False;end;

    procedure TForm1.btPararClick(Sender: TObject);

    begin Parar:=1;end;

    end.

    Ping

    Neste tpicovamos desenvolver uma nova verso para o ping. Mas Facunte, o que ping? O utilitrio ping,encontrado namaioria dos sistemas operacionais, como Windows e Linux, utilizado para ouvir uma resposta de um determinado servidor,e medir o tempo da mesma. Esta resposta pode ser nula, quando no se consegue estabelecer uma comunicao com o servidor,ou terminal remoto. Normalmente os testes de pingso feitos emservidores de Internet, firewall, roteadores e servidores de

    banco de dados. Vejamos um exemplo deste utilitrio rodando no sistema operacional Windows:

  • 8/2/2019 Delphi CAP 9 Desenvolvendo utilitrios para Internet

    11/32

    Desenvolvendo utilitrios para Internet 137

    Figura 9.3 Ping sendo executado no Windows XP

    Neste exemplo, executamos o utilitriopingno sistema operacional Windows XP, solicitando uma resposta do computadorServidor. Repare que o pingdispara um pacote de 32 bytes no endereo IP (200.173.173.142), relacionado ao Servidor, eouvequatro respostas num tempo menor que 1ms (um milesegundo). Com isso poderemos medir a eficincia no trfego dedados entre cliente/servidor, seja l qual for a sua origem (servidor de banco de dados, aparelho celular, servidor Internet,PDA, entre outros). Veja alguns exemplos ilustrativos do utilitrioPing (figuras 9.4, 9.5 e 9.6).

    Figura 9.4 Ping disparado contra o Servidor com resultado satisfatrio

    Figura 9.5 Ping disparado contra o Servidor sem resposta

    Figura 9.6 Ping disparado contra o Servidor com resultado nada agradvel (lento)

    Ping Servidor (32 bytes)

    Estou aqui (1ms 32 bytes)

    Ping Servidor (32 bytes)

    Mudo (sem resposta)

    Ping Servidor (32 bytes)

    Estou aqui (estouro tempo)

  • 8/2/2019 Delphi CAP 9 Desenvolvendo utilitrios para Internet

    12/32

    138 Delphi 7 Internet e Banco de Dados

    Como vimos, existem trs possibilidades de resultado: satisfatrio, sem resposta e lento. Com isso podemos fazer testes deperformance em diversos tipos de servidores, e descobrir, em alguns casos, onde est o problema de lentido.

    Bem, amigos, agora vem a parte boa: mo-na-massa.

    Inicie um projeto do tipo CLX (Delphi 6 ou superior), pois poderemos executar nossa aplicao no Linux, compilando oprojeto no Kylix. Grave a unitcom o nome un_ping.pas e o projeto como ping.dpr. Insira o seguinte objeto, alterando suas

    propriedades.

    Objeto TPanel [Standard]Align alTop

    Name pnEndereco

    Com o foco no objetopnEndereco, insira os objetos que seguem, alterando suas respectivas propriedades:

    Objeto TLabel[Standard]Caption EndereoLeft 12Top 20

    Objeto TEdit [Standard]Left 72

    Name edEnderecoTop 16Width 210

    Objeto TBitBtn [additional]Caption PingLeft 296

    Name btPingTop 16Width 75

    Agora com o foco no formulrio, insira outro objeto do tipo TPanele altere as propriedades que seguem:

    Objeto TPanel [Standard]Align AlClient

    Name PnResultado

    Com o foco no objetopnResultado insira um objeto do tipo TMemo e altere as seguintes propriedades:

    Objeto TMemo [standard]Height 160Left 16

    Name mmResultadoLines (deixe em branco)Top 16

    Width 500

    Com isso teremos um formulrio parecido com afigura 9.7.

  • 8/2/2019 Delphi CAP 9 Desenvolvendo utilitrios para Internet

    13/32

    Desenvolvendo utilitrios para Internet 139

    Figura 9.7 Aplicao Ping em tempo de projeto

    Neste ponto iremos inserir o nosso objeto chave: TidICMPClient. Muita hora nesta calma, ou melhor, muita calma nestahora, amigos, no mais um imposto do governo, apenas o nosso componente chave.

    Facunte, que nome complicado de componente! O que quer dizer ICMP? ICMP quer dizerInternet Control Message Protocol,ou Protocolo Internet de Controle de Mensagens. Este protocolo normalmente utilizado pelos utilitrios que iremosdesenvolver, e basicamente serve para enviar mensagens a servidores remotos.

    Ok, ento vamos inserir o nosso objeto TidICMPClient, e alterar as seguintes propriedades:

    Objeto TPanel [Standard]Name NossoICMPReceiveTimeout 10000

    Perceba que alteramos a propriedade ReceiveTimeout. Esta propriedade indica o tempo mximo em milessegundos para umaresposta do servidor, gerando um timeoutquando ultrapassado este tempo.

    Vamos codificar o boto btPing, inserindo o cdigo que segue no evento OnClick:

    var

    i: integer;begin

    btPing.Enabled:=False;try

    NossoICMP.Host := edEndereco.Text;for i := 1 to 4 dobegin

    NossoICMP.Ping;Application.ProcessMessages;

    end;finally

    btPing.Enabled := True;end;

    end;

    Vamos analisar o cdigo. Primeiro, estamos declarando uma varivel do tipo integerpara nos auxiliar no lao doping.

    var

    i: integer;

    Em seguida desabilitamos o boto btPing, impedindo o usurio de clicar vrias vezes e causar um efeito redundante.

    btPing.Enabled:=False;

  • 8/2/2019 Delphi CAP 9 Desenvolvendo utilitrios para Internet

    14/32

    140 Delphi 7 Internet e Banco de Dados

    No prximo ponto, protegemos o cdigo com try para que eventuais erros sejam ignorados em nossa aplicao.

    try

    Em seguida configuramos a propriedadeHostdo nosso objetoNossoICMPde acordo com a informao do usurio extrada doobjeto edEndereco.

    NossoICMP.Host := edEndereco.Text;

    Finalmente iniciamos o lao, executando o comandoPing4 vezes (padro), e solicitando ao S.O. uma atualizao da aplicao.

    for i := 1 to 4 dobegin

    NossoICMP.Ping;Application.ProcessMessages;

    end;

    E para concluir esta parte do cdigo, finalizamos o bloco protegido, habilitando novamente o boto btPing.

    finally

    btPing.Enabled := True;end;

    Agora, iremos codificar o evento OnReply do objetoNossoICMP. Este evento responsvel pelas informaes de resposta.

    Coloque o cdigo a seguir no evento OnReply:

    var

    sTime:string;begin

    if (AReplyStatus.MsRoundTripTime = 0) thensTime := '

  • 8/2/2019 Delphi CAP 9 Desenvolvendo utilitrios para Internet

    15/32

    Desenvolvendo utilitrios para Internet 141Esta uma declarao padro para o evento OnReply do objetoNossoICMP. Com relao propriedade MsRoundTripTime,ela representa o tempo em milessegundos do resultado de retorno do pacote. Caso o resultado seja 0, ento atribumos o valor < 1 nossa varivelsTime, seno, atribumos o valor = .

    Prosseguindo com a nossa anlise, agora vem o ponto forte da nossa aplicao: a linha de resultado.

    mmResultado.Lines.Add(Format('%d bytes de %s: sequencia#=%d tempo-de-vida(ttl)=%d

    tempo%s%d ms',[AReplyStatus.BytesReceived,AReplyStatus.FromIpAddress,AReplyStatus.SequenceId,AReplyStatus.TimeToLive,sTime,AReplyStatus.MsRoundTripTime]));

    Percebam que estamos adicionando contedo ao nosso objeto mmResultado:

    mmResultado.Lines.Add

    Estamos nos aproveitando da funo Format para facilitar a composio da linha de resultado. Para quem no conhece afuno Format, sugiro uma breve visita no Help do Delphi, onde sempre encontramos ricas informaes. Vejamos ossignificados das propriedades da constante AReplyStatus.

    BytesReceived = bytes recebidosFromIpAddress = endereo do HostSequenceId = nmero da sequnciaTimeToLive = Tempo de vida do pacote

    Agora vamos executar o nosso projeto e ver o resultado. Afigura 9.8 ilustra o nosso projeto em execuo.

    Figura 9.8 Projeto Ping em execuo

  • 8/2/2019 Delphi CAP 9 Desenvolvendo utilitrios para Internet

    16/32

    142 Delphi 7 Internet e Banco de Dados

    Misso Cumprida

    Ao final deste tpico, espero ter esclarecido a todos a utilidade do Ping, bem como tertransmitido com clareza as funcionalidades do objeto TidICMPClient.

    Artigo originalmente publicado na Revista Clube Delph, n 33

    Listagem 9.2 unit un_ping

    unit un_ping;

    interface

    usesSysUtils, Types, Classes, QGraphics, QControls, QForms, QDialogs,QStdCtrls, QExtCtrls, QButtons, IdBaseComponent, IdComponent, IdRawBase,IdRawClient, IdIcmpClient;

    typeTForm1 = class(TForm)pnEndereco: TPanel;PnResultado: TPanel;edEndereco: TEdit;btPing: TBitBtn;Label1: TLabel;mmResultado: TMemo;NossoICMP: TIdIcmpClient;procedure btPingClick(Sender: TObject);procedure NossoICMPReply(ASender: TComponent;const AReplyStatus: TReplyStatus);

    private

    { Private declarations }public{ Public declarations }

    end;

    varForm1: TForm1;

    implementation

    {$R *.xfm}

    procedure TForm1.btPingClick(Sender: TObject);vari: integer;

    beginbtPing.Enabled:=False;tryNossoICMP.Host := edEndereco.Text;for i := 1 to 4 dobeginNossoICMP.Ping;

  • 8/2/2019 Delphi CAP 9 Desenvolvendo utilitrios para Internet

    17/32

    Desenvolvendo utilitrios para Internet 143Application.ProcessMessages;

    end;finally

    btPing.Enabled := True;end;

    end;

    procedure TForm1.NossoICMPReply(ASender: TComponent;const AReplyStatus: TReplyStatus);

    varsTime:string;

    beginif (AReplyStatus.MsRoundTripTime = 0) thensTime := '

  • 8/2/2019 Delphi CAP 9 Desenvolvendo utilitrios para Internet

    18/32

    144 Delphi 7 Internet e Banco de Dados

    Figura 9.9 Simulao do Trace Route

    Com o trace routepoderemos descobrir falhas ou lentido de resposta em todos os servidores envolvidos no processo de envioe recebimento de pacotes. Normalmente falamos que o site X est extremamente lento. Nem sempre o prprio site, pode serum dos servidores envolvidos (conhecido como hope) no processo.

    Nosso utilitrio uma adaptao de um programa de demonstrao que vem no pacote da INDY Components. Vamos iniciar odesenvolvimento do nosso utilitrio.

    Atravs das opesFile/New...CLX Application, crie uma nova aplicao. Grave a unitcom o nome un_tracert.pas e o projetocomo tracert.dpr. Insira os objetos que seguem alterando suas respectivas propriedades.

    Objeto TPanel [Standard]Align alTop

    Name pnTopoHeight 155

    Cliente (Brasil)

    tempo de resposta: 2ms

    Provedor de Acesso

    tempo de resposta: 3ms

    BackBone Embratel

    tempo de resposta: 1ms

    Servidor Final: Japo

  • 8/2/2019 Delphi CAP 9 Desenvolvendo utilitrios para Internet

    19/32

    Desenvolvendo utilitrios para Internet 145Com o foco no objetopnTopo, insira os objetos que seguem, alterando suas respectivas propriedades:

    Objeto TPanel [Standard]Align alTop

    Name pnDadosHeight 60

    Ainda com o foco noPnTopo,insira um objeto do tipo TMemo, e altere as seguintes propriedades.

    Objeto TListBox [Standard]Align alClient

    Name lbLog

    Agora com o foco no objetoPnDados, insira os objetos que seguem, alterando suas respectivas propriedades:

    Objeto TLabel[Standard]Caption Host DestinoLeft 12Top 8

    Objeto TLabel[Standard]Caption Mximo HopesLeft 12Top 40

    Objeto TEdit [Standard]Left 110

    Name edTargetText (deixar em branco)Top 5Width 280

    Objeto TSpindEdit [Common Controls]

    Left 110Name seMaxHopsTop 32Value 50Width 65

    Objeto TButton [Standard]Caption ExecutaLeft 184

    Name btExecutaTop 32Width 75

  • 8/2/2019 Delphi CAP 9 Desenvolvendo utilitrios para Internet

    20/32

    146 Delphi 7 Internet e Banco de Dados

    Objeto TButton [Standard]Caption CancelaLeft 270

    Name btCancelaTop 32Width 75

    Agora com o foco no Formulrio, insira outro componente do tipo TPanelalterando as seguintes propriedades.

    Objeto TPanel [Standard]Align AlClient

    Name PnInfo

    Com o foco no objetopnInfo insira um componente do tipo TListView, alterando as seguintes propriedades.

    Objeto TListView [Common Controls]Align alClientColumns insira trs colunas como ilustra afigura 9.10

    Name LvTraceViewStyle vsReport

    Figura 9.10 Columns.items do listview1

    Insira os objetos que seguem, alterando as respectivas propriedades.

    Objeto idICMPClient [Indy Clients]Name idICMPClient

    Objeto idAntiFreeze [Indy Misc]Name idAntiFreeze

    Afigura 9.11 ilustra nosso formulrio.

  • 8/2/2019 Delphi CAP 9 Desenvolvendo utilitrios para Internet

    21/32

    Desenvolvendo utilitrios para Internet 147

    Figura 9.11 Formulrio do projeto Tracert

    Para facilitar a organizao das nossasprocedures e aes, vamos utilizar o componenteActionList. Insira um objeto do tipoTActionListe atravs do duplo-clique insira as seguintes aes (figura 9.12).

    :Figura 9.12 Aes do projeto

    Agora vamos codificar nosso projeto. Na seo private insira o cdigo que segue.

    bResolved: Boolean;ResolvedHost: String;Stopped: Boolean;

    function PingHost(Host: string; TTL: Integer): boolean;function FindItem(TTL: Integer; Add: boolean): TListItem;

    Nesta seo, definimos algumas variveis e funes com o objetivo de auxiliar em alguns processos.

    bResolved: Boolean;ResolvedHost: String;Stopped: Boolean;

  • 8/2/2019 Delphi CAP 9 Desenvolvendo utilitrios para Internet

    22/32

    148 Delphi 7 Internet e Banco de Dados

    bResolved para atribuirtrue oufalse na operao depingResolvedHost para atribuir o host (hope) em operaoStopped atribui o valortruepara informar a paralisao das operaes.

    function PingHost(Host: string; TTL: Integer): boolean;function FindItem(TTL: Integer; Add: boolean): TListItem;

    Na clusula uses insira as seguintes Units.

    uses idStack, IdException;

    Agora vamos codificar as aes: No evento OnExecute daAction acGO, insira o cdigo que segue:

    tryStopped := false;acGo.Enabled := false;acStop.enabled := true;acResolve.execute;if bResolved and not stopped thenbeginacPing.execute;if not stopped then

    acTrace.Execute;end;acGo.Enabled := true;acStop.enabled := false;

    finally{ ok }

    end; { try/finnaly }

    Nesta rotina estamos atribuindo as definies iniciais do nosso projeto, e executando as rotinas de pinge trace. No eventoOnExecute daActionacResolve, insira o cdigo que segue:

    bResolved := false;lbLog.Items.Append(Format('resolvendo %s', [edTarget.text]));try

    Application.ProcessMessages;ResolvedHost := gStack.WSGetHostByName(edTarget.text);bResolved := true;lbLog.Items.Append(format('%s resolvido %s',[edTarget.text, ResolvedHost]));

    excepton e: EIdSocketError dolbLog.Items.text := lbLog.Items.text + e.message;

    end;

    Neste cdigo estamos resolvendo um host(hope), ou melhor, verificando informaes e possibilidade de contato com o host.Repare que estamos utilizando a funo WSGetHostByName, da unit IdStack,para mapear e resolvero host.

    ResolvedHost := gStack.WSGetHostByName(edTarget.text);

    Se a operao for bem sucedida, adicionamos no lbLogo resultado; caso contrrio, a mensagem de erro.Operao bem sucedida

    lbLog.Items.Append(format('%s resolvido %s',[edTarget.text, ResolvedHost]));

  • 8/2/2019 Delphi CAP 9 Desenvolvendo utilitrios para Internet

    23/32

    Desenvolvendo utilitrios para Internet 149Erro.

    excepton e: EIdSocketError dolbLog.Items.text := lbLog.Items.text + e.message;

    No evento OnExecute daAction acPing, insira o seguinte cdigo.

    PingHost(ResolvedHost, seMaxHops.value);Application.ProcessMessages;

    Aqui estamos executando a chamada da funo PingHost (ser criada posteriormente), com o host atual, e o mximo dehopes. No evento OnExecute daAction acTrace, insira o cdigo que segue.

    varTTL: Integer;Reached: boolean;aItem: TListItem;

    beginTTL := 0;reached := false;lvTrace.Items.Clear;

    repeatinc(TTL);IdIcmpClient.Host := ResolvedHost;IdIcmpClient.TTL := TTL;IdIcmpClient.ReceiveTimeout := 5000;IdIcmpClient.Ping;aItem := FindItem(TTL, True);aItem.SubItems.Clear;case IdIcmpClient.ReplyStatus.ReplyStatusType ofrsEcho:beginaItem.SubItems.Append(IdIcmpClient.ReplyStatus.FromIpAddress);aItem.SubItems.Append(format('Reached in : %d ms',

    [IdIcmpClient.ReplyStatus.MsRoundTripTime]));

    reached := true;end;rsError:beginaItem.SubItems.Append(IdIcmpClient.ReplyStatus.FromIpAddress);aItem.SubItems.Append('Unknown error.');

    end;rsTimeOut:beginaItem.SubItems.Append('?.?.?.?');aItem.SubItems.Append('Timed out.');

    end;rsErrorUnreachable:begin

    aItem.SubItems.Append(IdIcmpClient.ReplyStatus.FromIpAddress);aItem.SubItems.Append(format('Destination network unreachable',[IdIcmpClient.ReplyStatus.MsRoundTripTime]));

    break;end;rsErrorTTLExceeded:beginaItem.SubItems.Append(IdIcmpClient.ReplyStatus.FromIpAddress);

  • 8/2/2019 Delphi CAP 9 Desenvolvendo utilitrios para Internet

    24/32

    150 Delphi 7 Internet e Banco de Dados

    aItem.SubItems.Append(format('TTL=%d',[IdIcmpClient.ReplyStatus.TimeToLive]));

    end;end; // caseApplication.ProcessMessages;

    until reached or (TTL > seMaxHops.value) or Stopped;

    Este cdigo um pouco mais complexo, mas vamos analisar passo a passo. Inicialmente, estamos definindo algumas variveisauxiliares.

    TTL define o hope atual.Reached define se o TTL atual foi resolvidoaItem objeto do tipo TListItempara ser adicionado em nossoLvTrace.

    varTTL: Integer;Reached: boolean;aItem: TListItem;

    Em seguida temos a atribuio inicial das variveis.

    TTL := 0;

    reached := false;lvTrace.Items.Clear;

    O bloco que segue inicia um lao, at que uma das trs situaes (resolvido reached = true, TTL > hopes, ou solicitao decancelamento) seja verdadeira. Incrementamos o TTL, e atribumos ao objeto idICMPClientalgumas configuraes, comoHoste TTL. Executamos o mtodopingdo idICMPClient, e em seguida preparamos o objeto aItempara receber a informaodo resultado da operao.

    repeatinc(TTL);IdIcmpClient.Host := ResolvedHost;IdIcmpClient.TTL := TTL;IdIcmpClient.ReceiveTimeout := 5000;IdIcmpClient.Ping;

    aItem := FindItem(TTL, True);aItem.SubItems.Clear;

    Os prximos blocos tratam os diversos tipos de resultado do mtodoping. O bloco que segue trata o tipo de resposta (rsEcho)e adiciona um subitem ao objeto aItem.

    case IdIcmpClient.ReplyStatus.ReplyStatusType ofrsEcho:beginaItem.SubItems.Append(IdIcmpClient.ReplyStatus.FromIpAddress);aItem.SubItems.Append(format('Reached in : %d ms',

    [IdIcmpClient.ReplyStatus.MsRoundTripTime]));reached := true;

    end;

    O bloco seguinte recebe um tipo de resposta de erro (rsError) e tambm adiciona um subitem ao objeto aItem.

    rsError:beginaItem.SubItems.Append(IdIcmpClient.ReplyStatus.FromIpAddress);aItem.SubItems.Append('Unknown error.');

    end;

  • 8/2/2019 Delphi CAP 9 Desenvolvendo utilitrios para Internet

    25/32

    Desenvolvendo utilitrios para Internet 151O prximo bloco trata o TimeOutexcedido (rsTimeOut), definido como 5000 milesegundos.

    rsTimeOut:

    beginaItem.SubItems.Append('?.?.?.?');aItem.SubItems.Append('Timed out.');

    end;

    Em seguida, temos o tratamento de uma operao no resolvida (rsErrorUnreachable).

    rsErrorUnreachable:

    beginaItem.SubItems.Append(IdIcmpClient.ReplyStatus.FromIpAddress);aItem.SubItems.Append(format('Destination network unreachable',

    [IdIcmpClient.ReplyStatus.MsRoundTripTime]));break;

    end;

    E por fim, temos o tratamento de erro (rsErrorTTLExceeded), onde excedido o nmero mximo de tentativas.

    rsErrorTTLExceeded:

    begin

    aItem.SubItems.Append(IdIcmpClient.ReplyStatus.FromIpAddress);aItem.SubItems.Append(format('TTL=%d',

    [IdIcmpClient.ReplyStatus.TimeToLive]));end;

    end; // caseApplication.ProcessMessages;

    until reached or (TTL > seMaxHops.value) or Stopped;

    um cdigo realmente complexo, mas estudando com calma e ateno, entenderemos cada mtodo implementado.

    Agora no evento OnExecute daAction acStop, insira o cdigo que segue.

    Stopped := true;

    acStop.enabled := false;

    Com isso estamos solicitando uma parada nas operaes.

    Agora vamos atribuir as Actions acGO e acStop, ao objeto btExecuta e btCancela, respectivamente. Para tanto, bastaselecionar aAction desejada do objeto em questo. Para finalizar nosso projeto, devemos criar as rotinas que seguem.

    function PingHost(Host: string; TTL: Integer): boolean;function FindItem(TTL: Integer; Add: boolean): TListItem;

    Primeiro vamos criar a rotina PingHost. Insira o cdigo que segue em nossa unit.

    function Tform1.PingHost(Host: string; TTL: Integer): Boolean;begin

    result := false;IdIcmpClient.Host := Host;IdIcmpClient.TTL := TTL;IdIcmpClient.ReceiveTimeout := 5000;IdIcmpClient.Ping;case IdIcmpClient.ReplyStatus.ReplyStatusType ofrsEcho:begin

  • 8/2/2019 Delphi CAP 9 Desenvolvendo utilitrios para Internet

    26/32

    152 Delphi 7 Internet e Banco de Dados

    lbLog.Items.Append(format('resposta do host %s in %d milesegundos',[IdIcmpClient.ReplyStatus.FromIpAddress,IdIcmpClient.ReplyStatus.MsRoundTripTime]));

    result := true;end;rsError:lbLog.Items.Append('Erro desconhecido');

    rsTimeOut:lbLog.Items.Append('Timed out.');

    rsErrorUnreachable:lbLog.Items.Append(format('Host %s no resolvido',[IdIcmpClient.ReplyStatus.FromIpAddress]));

    rsErrorTTLExceeded:lbLog.Items.Append(format('Hope %d %s: TTL expirou',[IdIcmpClient.TTL,idIcmpClient.ReplyStatus.FromIpAddress]));

    end; // caseend;

    Repare que muito parecida com aAction acTrace, s que neste caso, estamos resumindo o resultado das operaes em nossoobjeto lbLog. Agora vamos criar a rotina FindItem. Insira o cdigo que segue em nossa unit.

    function Tform1.FindItem(TTL: Integer; Add: boolean): TListItem;vari: Integer;

    beginresult := nil;// Find the TTL itemif lvTrace.Items.Count < TTL Thenbeginfor i := 0 to lvTrace.Items.Count - 1 dobeginif StrToIntDef(lvTrace.Items[i].Caption, -1) = TTL thenbeginresult := lvTrace.Items[i];Break;

    end;end;

    end;if not assigned( result ) thenbegin// Not found, add itresult := lvTrace.Items.Add;result.Caption := IntToStr(TTL);

    end;end;

    O objetivo desta funo retornar informaes adicionadas no objeto lvTrace,baseada na TTL atual, e utilizada pelaActionacTrace.

    Agora vamos gravar e compilar nossa aplicao. Afigura 9.13 ilustra nossa aplicao sendo executada.

  • 8/2/2019 Delphi CAP 9 Desenvolvendo utilitrios para Internet

    27/32

    Desenvolvendo utilitrios para Internet 153

    Figura 9.13 Tracert em ao

    Listagem 9.3 un_tracert.pas

    unit un_tracert;

    interface

    uses

    SysUtils, Types, Classes, Variants, QTypes, QGraphics, QControls, QForms,QDialogs, QStdCtrls, QExtCtrls, QComCtrls, QActnList, IdComponent,IdRawBase, IdRawClient, IdIcmpClient, IdBaseComponent, IdAntiFreezeBase,IdAntiFreeze;

    typeTForm1 = class(TForm)pnTopo: TPanel;pnInfo: TPanel;pnDados: TPanel;Label1: TLabel;edTarget: TEdit;Label2: TLabel;

    seMaxHops: TSpinEdit;btExecuta: TButton;btCancela: TButton;lvTrace: TListView;ActionList1: TActionList;acGo: TAction;acResolve: TAction;

  • 8/2/2019 Delphi CAP 9 Desenvolvendo utilitrios para Internet

    28/32

    154 Delphi 7 Internet e Banco de Dados

    acPing: TAction;acTrace: TAction;acStop: TAction;IdAntiFreeze1: TIdAntiFreeze;IdIcmpClient: TIdIcmpClient;lbLog: TListBox;procedure acGoExecute(Sender: TObject);procedure acResolveExecute(Sender: TObject);procedure acPingExecute(Sender: TObject);procedure acTraceExecute(Sender: TObject);procedure acStopExecute(Sender: TObject);

    private{ Private declarations }bResolved: Boolean;ResolvedHost: String;Stopped: Boolean;function PingHost(Host: string; TTL: Integer): boolean;function FindItem(TTL: Integer; Add: boolean): TListItem;

    public{ Public declarations }

    end;

    varForm1: TForm1;

    implementation

    uses idStack, IdException;{$R *.xfm}

    procedure TForm1.acGoExecute(Sender: TObject);begintry

    Stopped := false;acGo.Enabled := false;

    acStop.enabled := true;acResolve.execute;if bResolved and not stopped thenbeginacPing.execute;if not stopped thenacTrace.Execute;

    end;acGo.Enabled := true;acStop.enabled := false;

    finally{ ok }

    end; { try/finally }

    end;

    procedure TForm1.acResolveExecute(Sender: TObject);beginbResolved := false;lbLog.Items.Append(Format('resolvendo %s',[edTarget.text]));

  • 8/2/2019 Delphi CAP 9 Desenvolvendo utilitrios para Internet

    29/32

    Desenvolvendo utilitrios para Internet 155try

    Application.ProcessMessages;ResolvedHost := gStack.WSGetHostByName(edTarget.text);bResolved := true;

    lbLog.Items.Append(format('%s resolvido %s',[edTarget.text, ResolvedHost]));excepton e: EIdSocketError dolbLog.Items.text := lbLog.Items.text + e.message;

    end;

    end;

    procedure TForm1.acPingExecute(Sender: TObject);beginPingHost(ResolvedHost, seMaxHops.value);Application.ProcessMessages;

    end;

    procedure TForm1.acTraceExecute(Sender: TObject);varTTL: Integer;

    Reached: boolean;aItem: TListItem;

    beginTTL := 0;reached := false;lvTrace.Items.Clear;repeatinc(TTL);IdIcmpClient.Host := ResolvedHost;IdIcmpClient.TTL := TTL;IdIcmpClient.ReceiveTimeout := 5000;IdIcmpClient.Ping;aItem := FindItem(TTL, True);aItem.SubItems.Clear;

    case IdIcmpClient.ReplyStatus.ReplyStatusType ofrsEcho:beginaItem.SubItems.Append(IdIcmpClient.ReplyStatus.FromIpAddress);aItem.SubItems.Append(format('Reached in : %d ms',

    [IdIcmpClient.ReplyStatus.MsRoundTripTime]));reached := true;

    end;rsError:beginaItem.SubItems.Append(IdIcmpClient.ReplyStatus.FromIpAddress);aItem.SubItems.Append('Unknown error.');

    end;rsTimeOut:beginaItem.SubItems.Append('?.?.?.?');aItem.SubItems.Append('Timed out.');

    end;rsErrorUnreachable:beginaItem.SubItems.Append(IdIcmpClient.ReplyStatus.FromIpAddress);aItem.SubItems.Append(format('Destination network unreachable',

  • 8/2/2019 Delphi CAP 9 Desenvolvendo utilitrios para Internet

    30/32

    156 Delphi 7 Internet e Banco de Dados

    [IdIcmpClient.ReplyStatus.MsRoundTripTime]));break;

    end;rsErrorTTLExceeded:beginaItem.SubItems.Append(IdIcmpClient.ReplyStatus.FromIpAddress);aItem.SubItems.Append(format('TTL=%d',

    [IdIcmpClient.ReplyStatus.TimeToLive]));end;

    end; // caseApplication.ProcessMessages;

    until reached or (TTL > seMaxHops.value) or Stopped;

    end;

    procedure TForm1.acStopExecute(Sender: TObject);beginStopped := true;acStop.enabled := false;

    end;

    function TForm1.PingHost(Host: string; TTL: Integer): Boolean;

    beginresult := false;IdIcmpClient.Host := Host;IdIcmpClient.TTL := TTL;IdIcmpClient.ReceiveTimeout := 5000;IdIcmpClient.Ping;case IdIcmpClient.ReplyStatus.ReplyStatusType ofrsEcho:beginlbLog.Items.Append(format('response from host %s in %d millisec.',

    [IdIcmpClient.ReplyStatus.FromIpAddress,IdIcmpClient.ReplyStatus.MsRoundTripTime]));

    result := true;end;rsError:lbLog.Items.Append('Unknown error.');

    rsTimeOut:lbLog.Items.Append('Timed out.');

    rsErrorUnreachable:lbLog.Items.Append(format('Host %s reports destination network unreachable.',

    [IdIcmpClient.ReplyStatus.FromIpAddress]));

    rsErrorTTLExceeded:lbLog.Items.Append(format('Hope %d %s: TTL expired.',

    [IdIcmpClient.TTL,IdIcmpClient.ReplyStatus.FromIpAddress]));

    end; // caseend;

  • 8/2/2019 Delphi CAP 9 Desenvolvendo utilitrios para Internet

    31/32

    Desenvolvendo utilitrios para Internet 157function TForm1.FindItem(TTL: Integer; Add: boolean): TListItem;vari: Integer;

    beginresult := nil;// Find the TTL itemif lvTrace.Items.Count < TTL Thenbeginfor i := 0 to lvTrace.Items.Count - 1 dobeginif StrToIntDef(lvTrace.Items[i].Caption, -1) = TTL thenbeginresult := lvTrace.Items[i];Break;

    end;end;

    end;if not assigned( result ) thenbegin// Not found, add itresult := lvTrace.Items.Add;result.Caption := IntToStr(TTL);

    end;end;

    end.

  • 8/2/2019 Delphi CAP 9 Desenvolvendo utilitrios para Internet

    32/32

    158 Delphi 7 Internet e Banco de Dados

    Anotaes de Dvidas

    Preciso Revisar

    Anotaes Gerais

    ?