Buscado número de ips

Delphi

05/08/2023

Pessoal tudo bem?Alguém pode me indicar algum artigo de como fazer conexão Tcpi/ip, componentes próprios para isso.
Tenho algumas placas controladoras de acesso onde cada uma tem seu próprio IP fixo,e todas tem o IP do servidor 192.168.40.100 e a porta delas são 20050.
Como posso buscar o ip fixo de cada uma,de uma vez só listando o número de ips delas em algum componente,algo como um Treeview, ListView ou qualquer outro.
Exemplo:
IP
192.168.40.1
192.168.40.2
192.168.40. 10
192.168.40.17
Etc...

Todas as controladoras são ligadas em um Switch cada uma em uma porta e depois ligado na entrada de rede do notebook.
Alan

Alan

Curtidas 0

Melhor post

Arthur Heinrich

Arthur Heinrich

10/08/2023

Você está tentando fazer 3 coisas que, embora distintas, estão relacionadas:

1 - Diferenciar um item no tree view, através de um ícone, para indicar se a interface respondeu na última varredura, quando você vai considerá-la ativa, ou outro ícone de interface inativa, quando ela não responde.

2 - Alterar a posição do item no tree view, para dar visibilidade, indicando primeiro ou por último, aquela que tenha respondido mais recentemente.

3 - Persistir o dado em algum arquivo ou banco de dados para que, ao retornar ao programa, ele possa fazer uma carga inicial do status anterior.

Existem outras maneiras de se manipular a lista, para ordenar os itens. Não é necessário excluir e reincluir um item para isso, o que poderia modificar a forma como você obtém a funcionalidade 2. Você pode, por exemplo, guardar em uma estrutura separada, informações detalhadas sobre cada item, indicando para cada um o horário da última resposta, por exemplo, podendo utilizar essa informação para ordenar os registros usando os métodos de ordenação da classe.

Já a funcionalidade 1, você pode, por exemplo, utilizar um TStringList para armazenar todos os IPs que aparecem na lista com o ícone "Ativo", antes de iniciar a varredura.

À medida que as respostas vão chegando, você atualiza o item no tree view e remove do String List.

Passado o tempo que você considera suficiente para receber todas as respostas, você terá no String List todos os IPs que aparecem na lista como "ativos", mas que não responderam, podendo varrer esta lista para alterar o ícone para "inativo".

Quanto à persistência, imagino que não mude significativamente. Existe uma chance muito grande de que uma interface ativa, permaneça ativa na próxima varredura. O mesmo vale para as interfaces inativas.

Sendo assim, não haveria muito impacto atualizar a informação "individualmente" em um banco de dados, sempre que o status da interface mudar.

Ou seja, se uma interface respondeu e, ao atualizar o item no tree view ele já existe e está com o ícone de ativo, não precisa atualizar a base.

Logo, você só precisa atualizar a base em duas situações:

- Ao inserir um item novo, ou atualizar um pré-existente que estava com status "inativo"
- Ao tornar "inativo" um item que não respondeu (da lista do String List de controle)

Desta forma, sempre que entrar na aplicação, sua base conteria, não só os itens, mas o status de cada um na última varredura e você poderia ler esta lista considerando como ordenação o status e data de alteração do status contidos no banco.
GOSTEI 1

Mais Respostas

Arthur Heinrich

Arthur Heinrich

05/08/2023

Você parece ter dois problemas.

O primeiro deles é, como utilizar o Delphi para utilizar conexões TCP/IP.

Em linhas gerais, os componentes utilizados para abrir conexões TCP/IP são os sockets. O client socket é um componente que permite acessar um IP remoto, em determinada porta. Já o server socket, abre uma porta local e fica "escutando" a porta para que outros "clientes" se conectem a ela.

Ao utilizar estes componentes, que trabalham de forma assíncrona, ocorrerão inúmeros eventos. Assim que a conexão é estabelecida, você pode enviar e receber informações.

O problema de se utilizar sockets é que eles são os componentes básicos de todo o fluxo de rede. Mas, dependendo do serviço que a conexão atende, podem ser necessários protocolos específicos e até negociações, para estabelecer criptografia e autenticação de usuários. Não é tão simples como pode parecer.

O segundo problema é o entendimento mais aprofundado sobre redes.

Todo equipamento conectado à rede requer uma ou mais interfaces de rede. Desde que haja pelo menos uma interface real, por onde vão trafegar os dados, de fato, podem haver outras interfaces virtuais, criadas apenas via software, como as utilizadas em VPNs. Ao enviar dados por estas interfaces virtuais, pode haver um tratamento diferenciado, como uma camada de criptografia, por exemplo.

Toda interface, quando ativa, pode receber um IP, que pode ser tradicional de 4 octetos (IPV4) ou os novos IPs (IPV6).

As informações básicas de uma interface de rede são:
- IP
- Gateway
- Máscara

O IP é o endereço da interface. Dependendo da configuração, ele pode ser fixo ou dinâmico.
A máscara define um range de IPs.

Imagine o IP como um número inteiro de 32 bits. A máscara é um número especial que possui os primeiros X bits preenchidos com o valor 1 e seguido de (32-X) bits zero.
Para definir que IPs fazem parte do range, estes bits são combinados com os bits do IP, de forma que a rede aceita modificar todos os bits do IP cujo bit correspondente da máscara vale zero.

Vou dar um exemplo: IP: 192.168.0.10 e máscara 255.255.255.0

11000000 10101000 00000000 00001010 -- IP
11111111 11111111 11111111 00000000 -- Máscara

Neste caso, os 3 primeiros octetos não podem ser modificados e o último pode ser inteiramente modificado, indicando um range de IPs que vai do IP 192.168.0.0 a 192.168.0.255.

Por conta desta característica da máscara, de sempre começar por 1s e terminar por 0s, também é válida a notação: 192.168.0.0/24 (24 bits 1).

Além do range de IPs, podemos ter uma VLAN. Uma VLAN também possui um range de IPs. O propósito do range e das VLANs é distinto.

O range pode ser utilizado para identificar um conjunto contínuo de IPs para efeito de liberação de acesso no firewall. Já a VLAN define o range de IPs que é acessível diretamente, sem precisar ser desviado para outra rede por intermédio do gateway, que atua como ponte entre múltiplas redes (VLANs).

O gateway é, geralmente, o primeiro IP válido de uma VLAN.

Agora que eu dificultei seu problema, precisamos entender o seu objetivo.

Não creio que você esteja falando de BOND, onde uma interface virtual se utiliza de 2 ou mais interfaces físicas para o propósito de redundância ou aumento de tráfego.

Para visualizar as interfaces no Windows, use o comando "ipconfig", no Linux o comando "ifconfig".

Para ver que portas estão abertas e escutando, pode utilizar o comando "netstat -na", que lista as portas que estão abertas para conexão, bem como todas as conexões abertas no momento.

Se você possui mais de uma interface de rede, ao acessar um endereço fora das suas redes, terá que sair pelo gateway de uma das suas interfaces. A definição de que interface deve ser utilizada para cada IP é definida em rotas de rede, que podem ser acessadas com o comando "netstat -nr".
GOSTEI 0
Alan

Alan

05/08/2023

Você parece ter dois problemas.

O primeiro deles é, como utilizar o Delphi para utilizar conexões TCP/IP.

Em linhas gerais, os componentes utilizados para abrir conexões TCP/IP são os sockets. O client socket é um componente que permite acessar um IP remoto, em determinada porta. Já o server socket, abre uma porta local e fica "escutando" a porta para que outros "clientes" se conectem a ela.

Ao utilizar estes componentes, que trabalham de forma assíncrona, ocorrerão inúmeros eventos. Assim que a conexão é estabelecida, você pode enviar e receber informações.

O problema de se utilizar sockets é que eles são os componentes básicos de todo o fluxo de rede. Mas, dependendo do serviço que a conexão atende, podem ser necessários protocolos específicos e até negociações, para estabelecer criptografia e autenticação de usuários. Não é tão simples como pode parecer.

O segundo problema é o entendimento mais aprofundado sobre redes.

Todo equipamento conectado à rede requer uma ou mais interfaces de rede. Desde que haja pelo menos uma interface real, por onde vão trafegar os dados, de fato, podem haver outras interfaces virtuais, criadas apenas via software, como as utilizadas em VPNs. Ao enviar dados por estas interfaces virtuais, pode haver um tratamento diferenciado, como uma camada de criptografia, por exemplo.

Toda interface, quando ativa, pode receber um IP, que pode ser tradicional de 4 octetos (IPV4) ou os novos IPs (IPV6).

As informações básicas de uma interface de rede são:
- IP
- Gateway
- Máscara

O IP é o endereço da interface. Dependendo da configuração, ele pode ser fixo ou dinâmico.
A máscara define um range de IPs.

Imagine o IP como um número inteiro de 32 bits. A máscara é um número especial que possui os primeiros X bits preenchidos com o valor 1 e seguido de (32-X) bits zero.
Para definir que IPs fazem parte do range, estes bits são combinados com os bits do IP, de forma que a rede aceita modificar todos os bits do IP cujo bit correspondente da máscara vale zero.

Vou dar um exemplo: IP: 192.168.0.10 e máscara 255.255.255.0

11000000 10101000 00000000 00001010 -- IP
11111111 11111111 11111111 00000000 -- Máscara

Neste caso, os 3 primeiros octetos não podem ser modificados e o último pode ser inteiramente modificado, indicando um range de IPs que vai do IP 192.168.0.0 a 192.168.0.255.

Por conta desta característica da máscara, de sempre começar por 1s e terminar por 0s, também é válida a notação: 192.168.0.0/24 (24 bits 1).

Além do range de IPs, podemos ter uma VLAN. Uma VLAN também possui um range de IPs. O propósito do range e das VLANs é distinto.

O range pode ser utilizado para identificar um conjunto contínuo de IPs para efeito de liberação de acesso no firewall. Já a VLAN define o range de IPs que é acessível diretamente, sem precisar ser desviado para outra rede por intermédio do gateway, que atua como ponte entre múltiplas redes (VLANs).

O gateway é, geralmente, o primeiro IP válido de uma VLAN.

Agora que eu dificultei seu problema, precisamos entender o seu objetivo.

Não creio que você esteja falando de BOND, onde uma interface virtual se utiliza de 2 ou mais interfaces físicas para o propósito de redundância ou aumento de tráfego.

Para visualizar as interfaces no Windows, use o comando "ipconfig", no Linux o comando "ifconfig".

Para ver que portas estão abertas e escutando, pode utilizar o comando "netstat -na", que lista as portas que estão abertas para conexão, bem como todas as conexões abertas no momento.

Se você possui mais de uma interface de rede, ao acessar um endereço fora das suas redes, terá que sair pelo gateway de uma das suas interfaces. A definição de que interface deve ser utilizada para cada IP é definida em rotas de rede, que podem ser acessadas com o comando "netstat -nr".


Fala Arthur, meu querido como você esta?
Então deu uma esquentada aqui no crânio kkkkk
Eu adicionei o componente TidUDPServer com ele eu consegui buscar os Ips das controladoras que estao conectadas,ficou o seguinte codigo:

procedure TFrmGerenciador.UDPDiscoveryUDPRead(AThread: TIdUDPListenerThread;
const AData: TIdBytes; ABinding: TIdSocketHandle);
var
DataStringStream: TStringStream;
my_data, IP, host, info, mac: String;
var I : INTEGER;

begin
// Busca os Ips e adiciona no TreeView.
try
//DataStringStream:=TStringStream.Create('');
//DataStringStream.CopyFrom(AData,AData.Size); //
my_data := idGlobal.BytesToString(AData);//copy(DataStringStream.DataString, 1, AData.Size);
except
exit;
end;

if(my_data = 'Discovery: Who is out there?') then
exit;
IP := ABinding.PeerIP;

Nods:= treeview.items.Addchild(Node,ip);
dm.FDquery1.Close;
dm.FDquery1.SQL.Clear;
dm.FDquery1.sql.Add('SELECT controladoras.Id_controladora,controladoras.Descricao FROM controladoras');
dm.FDquery1.sql.Add('LEFT JOIN ingressos_evento ON controladoras.Id_controladora = ingressos_evento.Id_controladora');
dm.FDquery1.sql.Add('WHERE ingressos_evento.Tipo = "ENTRADA" and controladoras.ip = :Pdesc');
dm.FDquery1.ParamByName('Pdesc').Value := nods.Text;
dm.FDquery1.open;
treeview.Items.AddChild(nods,inttostr(dm.FDQuery1.RecordCount)) ;
treeview.FullExpand;
end;

procedure TFrmGerenciador.BtnIniciarClick(Sender: TObject);
begin
// inicia A listagem dos Ip Na treeView.
if (treeview.Items.Count = 0) then
begin
Node := treeview.Items.Add(nIL,'CONTROLADORAS');
UDPDiscovery.Active := true;
UDPDiscovery.Send('255.255.255.255', 30303 ,'Discovery: Who is out there?'); // Envia a mascara e a porta
treeview.FullExpand;
end;
end;

Meu problema agora,esta sendo atualizar os ips, caso tenha mais controladoras conectadas depois de clicar no botão iniciar, sem precisar parar e iniciar de novo. Eu ate coloquei um timer, para poder atualizar de tempo em tempo, mais o problema e que ele atualiza na treeView os novos ips e os antigos que ja estavam adicionados, preciso que ele so adicione os que nao estao na treeView ,os que ja existir não,acredito eu que resolveria com um If no timer,mas nao sei qual a forma de escrever ele.


procedure TFrmGerenciador.timerDicovererTimer(Sender: TObject);
begin
If ... // Aqui seria a condiçao
timerDicoverer.Interval := 5000;
UDPDiscovery.Send('255.255.255.255', 30303 ,'Discovery: Who is out there?');
end;

Tinha colocado para deletar os itens Da treeView No timer antes de ficar buscando, mais nao ficou legal,como elas sempre vao ficar conectadas durante o evento, acredito eu que deletando no timer possa perder a conexao durante essa atualizaçao.
GOSTEI 0
Arthur Heinrich

Arthur Heinrich

05/08/2023

Você está adicionando itens com:

Nods:= treeview.items.Addchild(Node,ip);

Antes de fazer isso, pode varrer a lista e ver se já existe o IP, antes de adicionar:

  i:=Pred(treeview.items.count);
  while ((i>=0) and (treeview.items[i].Text <> IP)) do
    Dec(i);
  if (i<0) then Nods:= treeview.items.Addchild(Node,ip);

GOSTEI 0
Alan

Alan

05/08/2023

Você está adicionando itens com:

Nods:= treeview.items.Addchild(Node,ip);

Antes de fazer isso, pode varrer a lista e ver se já existe o IP, antes de adicionar:

  i:=Pred(treeview.items.count);
  while ((i>=0) and (treeview.items[i].Text <> IP)) do
    Dec(i);
  if (i<0) then Nods:= treeview.items.Addchild(Node,ip);



Arthur meu Amigo Deu certo Aqui, Eu queria lhe agradecer muito,por me ajudar com as minhas duvidas,desde que comecei a aprender o delphi você foi a pessoa que mais me ajudou aqui no devi,obrigado mesmo.
Nao querendo aproveitar muito,consegue me ajudar com mais algumas coisinhas do TreeView?
1° Se eu desconectar alguma controladora ou ela perder a conexão ja estando no treeview eu queria que ela ficasse alternado entre imagens Para saber que esta sem conexao.
2° Eu tenho um botao onde eu adiciono mais um node na TreeView,onde digito o texto em um edit, depois eu seleciono o ip que quero e adiciono ele nesse novo node,assim que adicionado ele deleta o item(ip) selecionado no node antigo e fica so no novo,eu queria fazer isso com mais itens selecionados ,nao apenas 1 por vez, faço isso pra poder separar por grupos.
esse e o codigo de adicionar mais um node.
procedure TFrmGerenciador.BtncriarClick(Sender: TObject);
begin
Nads := treeview.Items.Add(Check,edit1.Text);
NADS.ImageIndex := 2;
NADS.SelectedIndex := 2;
end;


esse adiciono e deleto um por vez
 procedure TFrmGerenciador.BitBtn2Click(Sender: TObject);
//var i :integer;
  begin

      if (treeview.selected = nil) then
      begin
        ShowMessage('SELECIONE UM ITEM!');
      end ELSE
      BEGIN
    treeview.MultiSelect := true;
    NID := treeview.Items.AddChild(Nads,treeview.Selected.Text);
    NID.ImageIndex := 1;
    NID.SelectedIndex := 1;
    treeview.Selected.Delete;

    dm.FDquery1.Close;
    dm.FDquery1.SQL.Clear;
    dm.FDquery1.sql.Add('SELECT controladoras.Id_controladora,controladoras.Descricao FROM controladoras');
    dm.FDquery1.sql.Add('LEFT JOIN ingressos_evento ON controladoras.Id_controladora = ingressos_evento.Id_controladora');
    dm.FDquery1.sql.Add('WHERE  ingressos_evento.Tipo = "ENTRADA" and controladoras.Descricao = :Pdesc');
    dm.FDquery1.ParamByName('Pdesc').Value := NID.Text;
    dm.FDquery1.Open;

    treeview.Items.AddChild(nID,inttostr(dm.FDQuery1.RecordCount)) ;
    treeview.FullExpand;
     end;
    end;
 


3° e ultimo, se teria como salvar a treeView Do jeito que ficou montada,caso precise pausar ou fechar o forms e quando abrir e iniciar nao precisar fazer todo o procedimeto novamente?
GOSTEI 0
Alan

Alan

05/08/2023

Você está tentando fazer 3 coisas que, embora distintas, estão relacionadas:

1 - Diferenciar um item no tree view, através de um ícone, para indicar se a interface respondeu na última varredura, quando você vai considerá-la ativa, ou outro ícone de interface inativa, quando ela não responde.

2 - Alterar a posição do item no tree view, para dar visibilidade, indicando primeiro ou por último, aquela que tenha respondido mais recentemente.

3 - Persistir o dado em algum arquivo ou banco de dados para que, ao retornar ao programa, ele possa fazer uma carga inicial do status anterior.

Existem outras maneiras de se manipular a lista, para ordenar os itens. Não é necessário excluir e reincluir um item para isso, o que poderia modificar a forma como você obtém a funcionalidade 2. Você pode, por exemplo, guardar em uma estrutura separada, informações detalhadas sobre cada item, indicando para cada um o horário da última resposta, por exemplo, podendo utilizar essa informação para ordenar os registros usando os métodos de ordenação da classe.

Já a funcionalidade 1, você pode, por exemplo, utilizar um TStringList para armazenar todos os IPs que aparecem na lista com o ícone "Ativo", antes de iniciar a varredura.

À medida que as respostas vão chegando, você atualiza o item no tree view e remove do String List.

Passado o tempo que você considera suficiente para receber todas as respostas, você terá no String List todos os IPs que aparecem na lista como "ativos", mas que não responderam, podendo varrer esta lista para alterar o ícone para "inativo".

Quanto à persistência, imagino que não mude significativamente. Existe uma chance muito grande de que uma interface ativa, permaneça ativa na próxima varredura. O mesmo vale para as interfaces inativas.

Sendo assim, não haveria muito impacto atualizar a informação "individualmente" em um banco de dados, sempre que o status da interface mudar.

Ou seja, se uma interface respondeu e, ao atualizar o item no tree view ele já existe e está com o ícone de ativo, não precisa atualizar a base.

Logo, você só precisa atualizar a base em duas situações:

- Ao inserir um item novo, ou atualizar um pré-existente que estava com status "inativo"
- Ao tornar "inativo" um item que não respondeu (da lista do String List de controle)

Desta forma, sempre que entrar na aplicação, sua base conteria, não só os itens, mas o status de cada um na última varredura e você poderia ler esta lista considerando como ordenação o status e data de alteração do status contidos no banco.


Arthur eu entendi um pouco o conceito que vc citou,já estava um pouco em mente isso,mas vou ser sincero com você,não faço ideia de como executar isso, consegue me mandar alguns exemplos ,para eu poder dar uma estudada,e ver se entendo melhor ?
E que eu funciono melhor vendo os exemplos para poder entender,na teoria assim,sem exemplos sou meio lerdo para entender rsrs
GOSTEI 0
Arthur Heinrich

Arthur Heinrich

05/08/2023

Vamos imaginar um algoritmo ligeiramente modificado. O componente StringList funciona como um array, com duas propriedades: um texto e um endereço de 32 bits para um TObject. Vou utilizar este endereço para armazenar o ImageIndex de cada IP, utilizando um cast, antes de enviar o broadcast.

Vamos supor neste exemplo, que os IPs ativos são os representados por ImageIndex = 1 e os inativos por ImageIndex = 2.

var
  i : Integer;
  IPList : TStringList;
...
  IPList:=TStringList.Create;
  for i:=0 to Pred(TreeView.Items.Count) do
    if (TreeView.Items[i].ImageIndex=1) then IPList.AddObject(TreeView.Items[i].Text, TObject(TreeView.Items[i].ImageIndex));


Em seguida, você envia o broadcast, como você já fez.

Na sua rotina UDPDiscoveryUDPRead você recebe a resposta de uma interface e identifica seu IP, e precisa alterar o status desse IP.
A função DBUpdateIPStatus(IP, Status) deve fazer o update na sua base de dados.

var
  i : Integer;
...
  IP := ABinding.PeerIP;
  // Verificar se o IP já existe no TreeView
  i:=IPList.IndexOf(IP);
  if (i>=0) then
    begin
      // IP já existe e a posição i é a posição do item no TreeView

      // Verifica se o status do IP mudou de inativo para ativo e atualiza a base de dados
      if (TreeView.Items[i].ImageIndex = 2) then DBUpdateIPStatus(IP, 1);

      // Muda o ícone para ativo
      TreeView.Items[i].ImageIndex:=1;

      // Altera o Objeto do StringList para o ImageIndex = 2, para que no final, este item não seja desativado.
      IPList.Objects[i]:=TObject(2);
    end
  else
    begin
      // O IP ainda não está na lista
      Nods:= treeview.items.Addchild(Node,ip);
      Nods.ImageIndex:=1;

      // Adiciona no StringList com status inativo, para não desativar no final.
      IPList.AddObject(IP, TObject(2));
    end;
...


No final, quando todas as interfaces tiverem respondido, você inativa os IPs que estavam com status ativo e não responderam:

var
  i : Integer;
...
  for i:=0 to Pred(IPList.Count) do
    if (Integer[IPList.Objects[i]) = 1) then
      begin
        TreeView.Items[i].ImageIndex:=2;
        DBUpdateIPStatus(IPList[i], 2);
      end;
  IPList.Free;

GOSTEI 1
Arthur Heinrich

Arthur Heinrich

05/08/2023

Desculpe. Eu tinha pensado em fazer uma coisa no início e mudei de ideia. Acabei esquecendo de remover o if, e o string list deveria armazenar todos os IPs.

Onde se lê:

var
  i : Integer;
  IPList : TStringList;
...
  IPList:=TStringList.Create;
  for i:=0 to Pred(TreeView.Items.Count) do
    if (TreeView.Items[i].ImageIndex=1) then IPList.AddObject(TreeView.Items[i].Text, TObject(TreeView.Items[i].ImageIndex));


Era para ser:

var
  i : Integer;
  IPList : TStringList;
...
  IPList:=TStringList.Create;
  for i:=0 to Pred(TreeView.Items.Count) do
    IPList.AddObject(TreeView.Items[i].Text, TObject(TreeView.Items[i].ImageIndex));

GOSTEI 0
Alan

Alan

05/08/2023

Vamos imaginar um algoritmo ligeiramente modificado. O componente StringList funciona como um array, com duas propriedades: um texto e um endereço de 32 bits para um TObject. Vou utilizar este endereço para armazenar o ImageIndex de cada IP, utilizando um cast, antes de enviar o broadcast.

Vamos supor neste exemplo, que os IPs ativos são os representados por ImageIndex = 1 e os inativos por ImageIndex = 2.

var
  i : Integer;
  IPList : TStringList;
...
  IPList:=TStringList.Create;
  for i:=0 to Pred(TreeView.Items.Count) do
    if (TreeView.Items[i].ImageIndex=1) then IPList.AddObject(TreeView.Items[i].Text, TObject(TreeView.Items[i].ImageIndex));


Em seguida, você envia o broadcast, como você já fez.

Na sua rotina UDPDiscoveryUDPRead você recebe a resposta de uma interface e identifica seu IP, e precisa alterar o status desse IP.
A função DBUpdateIPStatus(IP, Status) deve fazer o update na sua base de dados.

var
  i : Integer;
...
  IP := ABinding.PeerIP;
  // Verificar se o IP já existe no TreeView
  i:=IPList.IndexOf(IP);
  if (i>=0) then
    begin
      // IP já existe e a posição i é a posição do item no TreeView

      // Verifica se o status do IP mudou de inativo para ativo e atualiza a base de dados
      if (TreeView.Items[i].ImageIndex = 2) then DBUpdateIPStatus(IP, 1);

      // Muda o ícone para ativo
      TreeView.Items[i].ImageIndex:=1;

      // Altera o Objeto do StringList para o ImageIndex = 2, para que no final, este item não seja desativado.
      IPList.Objects[i]:=TObject(2);
    end
  else
    begin
      // O IP ainda não está na lista
      Nods:= treeview.items.Addchild(Node,ip);
      Nods.ImageIndex:=1;

      // Adiciona no StringList com status inativo, para não desativar no final.
      IPList.AddObject(IP, TObject(2));
    end;
...


No final, quando todas as interfaces tiverem respondido, você inativa os IPs que estavam com status ativo e não responderam:

var
  i : Integer;
...
  for i:=0 to Pred(IPList.Count) do
    if (Integer[IPList.Objects[i]) = 1) then
      begin
        TreeView.Items[i].ImageIndex:=2;
        DBUpdateIPStatus(IPList[i], 2);
      end;
  IPList.Free;


Arthur a funçao DBUpdateIPStatus(IP, Status) ela é propria do Componente UDPServer, ou preciso declarar ela? Nao Aparece ela para mim e essa linha aqui da erro
 if (Integer[IPList.Objects[i]) = 1) then
GOSTEI 0
Arthur Heinrich

Arthur Heinrich

05/08/2023

A função DBUpdateIPStatus(IP, Status) não existe. Estou abstraindo ela do código.

Sua função é atualizar a base de dados. Mas, como isso depende do banco utilizado e do modelo, não escrevi nenhum código.

É necessário lembrar que o IP pode não existir na base, caso em que devemos executar um insert. Se existir, precisa ser um update.

Como o insert ocorre apenas uma vez, eu utilizaria o seguinte método:

update <tabela de status de IP> set status = <status> where IP = <IP>
if <número de linhas atualizadas> = 0 then
  insert into <tabela de status de IP> values (<IP>, <status>)
commit


Ou coisa parecida.
GOSTEI 0
Alan

Alan

05/08/2023

A função DBUpdateIPStatus(IP, Status) não existe. Estou abstraindo ela do código.

Sua função é atualizar a base de dados. Mas, como isso depende do banco utilizado e do modelo, não escrevi nenhum código.

É necessário lembrar que o IP pode não existir na base, caso em que devemos executar um insert. Se existir, precisa ser um update.

Como o insert ocorre apenas uma vez, eu utilizaria o seguinte método:

update <tabela de status de IP> set status = <status> where IP = <IP>
if <número de linhas atualizadas> = 0 then
  insert into <tabela de status de IP> values (<IP>, <status>)
commit


Ou coisa parecida.


Certo, na verdade eu tenho uma tabela,onde cadastro todas as controladoras que eu irei usar com os campos:
"Id_controladora"	"Numero"                  "Descrica             "Desativada"		      "  Ip"	                  "ip_servidor"	      "Criacao"
"1"	                            "1"		 "CATRACA 01"                	"0"	                "192.168.40.1"       "192.168.40.100"    " 2023-07-24 14:14:25"
"2"	                            "2"		"CATRACA 02"	                "0"		        "192.168.40.2"	"192.168.40.100"	     "2023-07-24 14:16:30"
"3"	                            "3"		"CATRACA 03"	                "0"		        "192.168.40.3"	"192.168.40.100"       "2023-07-24 14:35:47"
"4"	                            "4"		"CATRACA 04"	                "0"		        "192.168.40.4"	"192.168.40.100"       "2023-07-24 15:18:38"
"5"	                            "5"		"CATRACA 05"	                "0"		         "192.168.40.5"	"192.168.40.100"	      "2023-07-24 15:19:47"
"7"	                           "6"		"CATRACA 06"	                "0"		         "192.168.40.6"	"192.168.40.100"	      "2023-07-24 18:38:08"
"8"	                           "7"		"CATRACA 07"	                "0"		          "192.168.40.7"	"192.168.40.100"       "2023-07-24 18:40:31"
"9"	                     "8"		         CATRACA 08"	                "0"		          "192.116.84.8"	"192.168.40.100"	      "2023-07-24 18:40:49"
"10"	                     "9"		        "CATRACA 09"               	"0"		          "192.168.40.9 "	"192.168.40.100"	      "2023-08-09 15:05:57"
"11"	                    "98"		        "CATRACA 98"	                "0"		         "192.168.40.98"	"192.168.40.100"	      "2023-08-09 15:06:55"
 

todos os ips que eu irei usar,estara nesse banco de dados , o Status eu poderia como exemplo usar o campo Desativada que é do tipo TINYINT onde Desativada é 0 e ativada é 1.No caso terei só que fazer o update mais ou menos assim :
Update Controladoras SET desativada = "1" Where ip = // Aqui passo o parametro

No caso como ja tenho todos os ips cadastrado nao precisaria de fazer o insert ne,ou estou errado?
ficaria assim mais ou menos
Begin
  IP := ABinding.PeerIP;
  // Verificar se o IP já existe no TreeView
  i:=IPList.IndexOf(IP);
  if (i>=0) then
    begin
      // IP já existe e a posição i é a posição do item no TreeView
 
      // Verifica se o status do IP mudou de inativo para ativo e atualiza a base de dados
      if (TreeView.Items[i].ImageIndex = 2) then// DBUpdateIPStatus(IP, 1);
begin
      DM.FDcontroladoras.Close;
      dm.FDcontroladoras.sql.Clear;
      dm.FDcontroladoras.sql.Add('Update Controladoras SET desativada = "1" Where ip = :pIp');
      dm.FDcontroladoras.ParamByName('Ip').Value := ip;
      dm.FDcontroladoras.ExecSQL;
 
      // Muda o ícone para ativo
      TreeView.Items[i].ImageIndex:=1;
 
      // Altera o Objeto do StringList para o ImageIndex = 2, para que no final, este item não seja desativado.
      IPList.Objects[i]:=TObject(2);
    end
  else
    begin
      // O IP ainda não está na lista
      Nods:= treeview.items.Addchild(Node,ip);
      Nods.ImageIndex:=1;
 
      // Adiciona no StringList com status inativo, para não desativar no final.
      IPList.AddObject(IP, TObject(2));
    end;

é mais Ou menos isso , Ou estou Pensando errado?
GOSTEI 0
POSTAR