Algorítimo para listar todos os IPs da rede

prezado rmendes08,

Se fosse uma aplicação que apenas lista os todos Ips da Rede, já teria sua utilidade… :wink:

mas sei que talvez explicando melhor o que pretendo com esta lista, eu ajudo vcs me ajudem … :slight_smile:
Não tenho como descrever o que minha aplicação irá fazer detalhadamente, mas vou te explicar em um contexto geral.
Minha aplicação precisa listar todos Ips ativos da rede para, a partir da lista verificar qual é impressora, desta forma consigo toda as impressoras da rede.

Talvez, é claro vcs tenham uma ideia bem melhor para isso…
Já pensei no AD, mas estou preocupado com redes que não tenha o mesmo configurado. Meu sistema pode rodar em linux e windows.

voltando a lista de Ips, o meio como vou conseguir a mesma no momento não faz diferença, desde que eu não tenha que deixar uma aplicação em cada maquina.

E por um acaso você já sabe como fazer para identificar se é uma impressora o dispositivo que está respondendo em determinado IP ? Como você fará isso ?

Talves eu esteja errado mais o comando net view lista todas as maquinas na rede e o arp - ??????XXX lista o nome e o ipp de todas maquinas na rede mais tem que verificar se procede.

Bom, para identificar se é uma impressora pretendo utilizar o protocolo SNMP.

Mas para isso dependo dos endereços IP… :cry:

Eu ia tentar montar um algoritmo para listar todos os ips de uma rede, mas não tá dando tempo… sei o princípio da coisa, mas teria que dar uma desenferrujada nas operações com bits hehe

No entanto, tem uma coisa que simplificaria MUITO o processo: há como garantir que a máscara de rede será sempre de bytes cheios (ou seja, só 255 e zeros) ? Nesse caso a solução fica bastante trivial

Pior que não…

digamos que a aplicação será distribuída e não sei ao certo em que plataforma, nem e que ambiente de rede irá rodar.
Claro que há alguns requisitos de configuração de sistema e rede, mas coisas triviais, e não posso impor que seja em redes com mascará de bits cheios

Olá,

Demorou mas consegui
Segue minha implementação para listagem de IPs de uma rede lógica.

Não sei a quantas anda com este problema, se já tiver conseguido melhor ainda!

import java.util.ArrayList;
import java.util.BitSet;
import java.util.List;


class ListaIPs {

    public static void main(String[] args) {
        String ipStr = "192.168.1.208";
        String maskStr = "255.255.252.0";

        IPAddress ipAddress = new IPAddress(ipStr);
        Netmask netmask = new Netmask(maskStr);

        System.out.println("IP fornecido : " + ipAddress.toString() + "/" + netmask.toString());
        System.out.println("IP da Rede   : " + NetworkUtils.getBaseNetworkIP(ipAddress, netmask));
        System.out.println("IP Broadcast : " + NetworkUtils.getBroadcastIP(ipAddress, netmask));
        
        System.out.println("Listando todos os IPs validos da rede: ");
        for (IPAddress ipp : NetworkUtils.listAvailableIPAddresses(ipAddress, netmask)) {
            System.out.println("- " + ipp);
        }
    }
}

/**
 * Representacao de um endereco IP, baseado em um conjunto de octetos.
 * 
 * @author Rodrigo
 */
class IPAddress {
    private OctetSet octets;

    IPAddress(OctetSet octetSet) {
        this.octets = octetSet;
    }
    IPAddress(String ipString) {
        this.octets = OctetSet.parse(ipString);
    }
    OctetSet getOctets() {
        return new OctetSet(octets);
    }
    @Override
    public String toString() {
        return octets.format();
    }
}

/**
 * Representacao de um mascara de rede, baseada em um conjunto de octetos.
 * @author Rodrigo
 *
 */
class Netmask {
    private OctetSet octets;

    Netmask(String maskString) {
        this.octets = OctetSet.parse(maskString);
    }
    OctetSet getOctets() {
    	return new OctetSet(octets);
    }
    @Override
    public String toString() {
    	return octets.format();
    }
}

/**
 * Armazena um conjunto de 4 bytes (octetos), apropriado para operações com endereços IP.
 * 
 * @author Rodrigo
 */
class OctetSet {

    private BitSet[] octets;

    /**
     * Constroi instancia a partir do valor numérico dos bytes.
     * @param octet1
     * @param octet2
     * @param octet3
     * @param octet4
     */
    OctetSet(short octet1, short octet2, short octet3, short octet4) {
        octets = new BitSet[] {
            toBits(octet1),
            toBits(octet2),
            toBits(octet3),
            toBits(octet4),
        };
    }
    
    /**
     * Clona uma outra instância.
     * @param octetSetToClone
     */
    OctetSet(OctetSet octetSetToClone) {
        this.octets = new BitSet[4];
        for (int i = 0; i < 4; i++) {
        	this.octets[i] = (BitSet) octetSetToClone.octets[i].clone();
        }
    }

    /**
     * Obtem instancia a partir de valores formatados no estilo endereço IP, 
     * por exemplo "111.111.111.111",
	 *
     * @param formattedOctetset
     * @return
     */
    static OctetSet parse(String formattedOctetset) {
    	String[] octetsStr = formattedOctetset.split("\\.");

        if (octetsStr.length != 4) {
            throw new IllegalArgumentException("Octetset deve conter 4 octetos");
        }

        OctetSet octetSet = new OctetSet(
            Short.parseShort(octetsStr[0]),
            Short.parseShort(octetsStr[1]),
            Short.parseShort(octetsStr[2]),
            Short.parseShort(octetsStr[3]));
        
        return octetSet;
    }
    
    /**
     * Formata octetset no estilo endereço IP.
     * @return
     */
    String format() {
        String result = fromBits(octets[0])
            + "." + fromBits(octets[1])
            + "." + fromBits(octets[2])
            + "." + fromBits(octets[3]);
        return result;
    }

    /**
     * Aplica operação lógica OR bit a bit.
     * A operação modifica o valor contido nesse objeto.
     * @param operand
     */
    void or(OctetSet operand) {
    	for (int i = 0; i < 4; i++) {
        	this.octets[i].or(operand.octets[i]);
        }
    }
    
    /**
     * Aplica operação lógica AND bit a bit.
     * A operação modifica o valor contido nesse objeto.
     * @param operand
     */
    void and(OctetSet operand) {
    	for (int i = 0; i < 4; i++) {
        	this.octets[i].and(operand.octets[i]);
        }
    }
    
    /**
     * Inverte o valor de cada bit contido nesse objeto.
     * @param operand
     */
    void flipAll() {
    	for (int i = 0; i < 4; i++) {
        	this.octets[i].flip(0, 8);
        }
    }
    
    /**
     * Adiciona "1" ao valor contido nesse objeto.
     * Exemplo:
     * 000.000.000.000 + 1  = 000.000.000.001
     * 000.000.000.254 + 1  = 000.000.000.255
     * 000.000.000.255 + 1  = 000.000.001.000
     * 029.255.255.255 + 1  = 030.000.000.000
     */
    void addOne() {
        final BitSet allOnes = new BitSet(8);
        allOnes.set(0, 8);

        if (octets[0].equals(allOnes)
        		&& octets[1].equals(allOnes)
        		&& octets[2].equals(allOnes)
        		&& octets[3].equals(allOnes)) {
        	// Todos estao no valor maximo (11111111), nada a fazer
        	return;
        }
        
        // Sera incrementado o ultimo octeto que ainda nao estiver com valor 11111111
        BitSet octetToIncrement = null;
        for (int i = 3; i >= 0; i--) {
            if (!octets[i].equals(allOnes)) {
            	// Este é o que sera incrementado
                octetToIncrement = octets[i];
                break;
            } else {
            	// Caso contrario, zera todas as posicoes para incremento do 
            	// proximo octeto mais significativo.
            	octets[i].clear();
            }
        }

        // Soma 1 ao byte selecionado
        for(int i = 7; i >= 0; i--) {
            if(!octetToIncrement.get(i)) {
                octetToIncrement.set(i);
                octetToIncrement.clear(i + 1, 8);
                break;
            }
        }
    }

    /**
    * Converte para binário o valor fornecido. Este bitset conterá exatamente 1 byte (8 bits),
    * com os bytes menos significativos à direita (indice 7).
    *
    * @param val Valor a ser convertido. Deve estar dentro do range
    * permitido para 1 byte (0-255)
    * @return
    */
    private BitSet toBits(short val) {
        if (val < 0 || val > 255) {
            throw new IllegalArgumentException("Numero invalido");
        }

        BitSet bytte = new BitSet(8);
        bytte.clear();

        final short[] pots = {128,64,32,16,8,4,2,1};

        /*
        * Utilizando algoritmo simplificado de sucessivas subtraçoes pelas potencias de 2
        */
        for (short i = 0; i < 8; i++) {
            if (val >= pots[i]) {
                bytte.set(i);
                val = (short) (val - pots[i]);
            }
        }

        return bytte;
    }

    /**
     * Converte de BitSet (binario) para valor numérico.
     * @param val
     * @return
     */
    private short fromBits(BitSet val) {
        final short[] pots = {128,64,32,16,8,4,2,1};
        short result = 0;
        for (short i = 7; i >= 0; i--) {
            if (val.get(i)) {
                result += pots[i];
            }
        }
        return result;
    }
    
    @Override
    public boolean equals(Object obj) {
    	if (obj == null) return false;
    	if (obj.getClass() != this.getClass()) return false;
    	
    	OctetSet other = (OctetSet) obj;
    	for (int i = 0; i < 4; i++) {
        	if(!this.octets[i].equals(other.octets[i])) return false;
        }
    	
    	return true;
    }
}

/**
 * Utilitários para cálculos envolvendo endereços de rede.
 * 
 * @author Rodrigo
 */
class NetworkUtils {

    /**
    * Retorna o IP da rede.
    * @param ipAddress
    * @param netmask
    * @return
    */
    static IPAddress getBaseNetworkIP(IPAddress ipAddress, Netmask netmask) {
        OctetSet ipRedeOctets = ipAddress.getOctets();
        ipRedeOctets.and(netmask.getOctets());        
        return new IPAddress(ipRedeOctets);
    }

    /**
    * Retorna o IP de broadcast para a rede
    * @param ipAddress
    * @param netmask
    * @return
    */
    static IPAddress getBroadcastIP(IPAddress ipAddress, Netmask netmask) {
        OctetSet ipBroadcastOctets = ipAddress.getOctets();
        
        OctetSet flippedMask = netmask.getOctets();
        flippedMask.flipAll();
        
        ipBroadcastOctets.or(flippedMask);
        
        return new IPAddress(ipBroadcastOctets);
    }

    /**
    * Lista os enderecos IP validos na mesma rede do endereco informado
    * @param ipAddress
    * @param netmask
    * @return
    */
    static List<IPAddress> listAvailableIPAddresses(IPAddress ipAddress, Netmask netmask) {
        // Range vai do IP da rede até o IP de broadcast
        OctetSet ip = getBaseNetworkIP(ipAddress, netmask).getOctets();
        OctetSet limit = getBroadcastIP(ipAddress, netmask).getOctets();

        List<IPAddress> ips = new ArrayList<IPAddress>();
        while (true) {
            ip.addOne();
            if (ip.equals(limit)) {
                break;
            }
            ips.add(new IPAddress(new OctetSet(ip)));
        }

        return ips;
    }

}
1 curtida

Opa gomesrod, blz?

Ainda estou na luta com isso.
vlw pela atenção! vou testar o código e posto o resultado… ou alguma duvida sobre ele…kkk

krak velho!!!

agora que copiei o código pro eclipse, reparei que é um código gigantesco… deve ter dado um trabalhão…vlw mesmo gomesrod!!! :smiley:

gomesrod, Funcionou!!!

mais uma vez obrigado kra tava com este problema fazia um tempão.

vlw galera!!!

Baseado neste codigo pode criar tambem uma definicção baseando no primeiro numero a qual classe de rede pertence e quantas possibilidades de redes pode ser feito.

ex: _ClassePrimeiros bitsNúm. de redes_Número de hosts __Máscara padrão
*======A =====0 =================126 ============16.777.214 ==========255.0.0.0
*======B =====10 ================16.382==========65.534 ==============255.255.0.0
*======C =====110================2.097.150=======254==================255.255.255.0
*======D=====1110==========Utilizado para tráfego Multicast
*======E=====1111==========Reservado para uso futuro

labavel, vou confessar q não entendi…

E so uma analogia do que se pode expandir neste codigo pense assim

Os endereços IP estão repartidos por classes, de acordo com o número de bytes que representam a rede.

E a divisão dos endereços IP em três classes A, B e C, é facilitar a investigação de um computador na rede.

Com efeito, esta notação é possível procurar inicialmente a rede que se deseja atingir e seguidamente procurar um computador . Assim, a atribuição dos endereços IP faz-se de acordo com a dimensão da rede.

Para quem trabalha com rede não e tão simples apenas informar um numero de IP e uma mascara deve ser dimencionado, quantas maquinas deverão utilizar a rede e quais ips elas devem usar conforme lista no servidor.

Opa gomesrod, acabei de ver o seguinte:

quando eu coloco a mascara 255.255.0.0, e o ip 128.0.0.1, o código já começa listando a partir do host 128.0.237.36, está correto??

estou tentando entender melhor a lógica utilizada…

Ahhh, entendi!!

vlw… vou dar uma aprofundada no assunto!!

[quote=softlesk]Opa gomesrod, acabei de ver o seguinte:

quando eu coloco a mascara 255.255.0.0, e o ip 128.0.0.1, o código já começa listando a partir do host 128.0.237.36, está correto??

estou tentando entender melhor a lógica utilizada…[/quote]
Não tá certo não, o primeiro IP da rede seria justamente esse 128.0.0.1, até o 128.0.255.254

Mas veja se não foi o console que cortou os resultados porque a lista ficou grande.

rsrsrsrrs…

to me sentindo ridículo, por não ter pensado nisso… :lol:

Realmente o console cortou…eita trem rápido, listou tudo em questão de dois segundos…

vlw (de novo)… :lol:

Listar é rápido, o demorado vai ser mandar requisição para cada um e esperar resposta!

Olha ali na tabelinha do labavel, para uma rede dessa (classe B) é possível ter 65.534 IPs.
Em um dia tem 86400 segundos.

Ou seja, se demorar um pouco mais de um segundo cada resposta (ou esperar dar timeout, que demora mais ainda!) o processo passa facilmente de um dia.

gomesrod

Qual o procedimento para obter o resultado do primeiro octeto 3 primeiros numeros.

System.out.println("Classe : " + ClasseIP.toString(); System.out.println("Núm. de redes : " + NunRedes.toString(); System.out.println("Número de hosts : " + NunHosts.toString();

Em outras palavras com o resultado do primeiro bit irei classificar em qual classe ele pretence e o Núm. de redes e os Número de hosts disponiveis para ele.

Hehe olha o projeto crescendo! :smiley:

Faz assim:
Nos octetos da máscara, vai contando (da esquerda para a direita) todos os que estão com valor true.

Se estiver entre 8 e 15 bits ligados, é classe A
Entre 16 e 23, é classe B
A partir de 24, é classe C

Assim:
255.255.255.0 = 11111111.11111111.11111111.00000000 = 24 bits ligados = classe C
255.255.192.0 = 11111111.11111111.11000000.00000000 = 18 bits ligados = classe B *
E assim por diante.

  • A classe B “pura” seria 255.255.0.0 (16 bits), nesse exemplo ela foi dividida em sub-redes.

Vc pode ir testando os bits dos Bitsets em loop, é só entender como ele funciona que fica simples.

Para saber a quantidade de redes possíveis para aquela máscara, é só fazer (2) elevado a (quantidade de bits ligados na mascara)
E a quantidade de hosts é (2) elevado a (quantidade de bits desligados na mascara) menos 2.

Esse menos 2 é porque numa rede sempre se “perde” o primeiro e o último IPs, que são os endereços da rede e de broadcast, respectivamente.