PDA

View Full Version : [java] generare range di ip: capitano ip tronchi


karplus
11-11-2006, 00:00
Ciao, sto facendo un programmino per generare tutti gli ip possibili entro certi range che decido direttamente all'interno del programma; tali ip vengno poi riversati in file di testo.

Nella fattispecie il suddetto programma dovrebbe generare tutti gli ip compresi fra 90.117.23.0 e 90.117.29.255.
Se faccio stampare a video i vari ip, l'ultimo ip é effettivamente 90.117.29.255.
Se invece faccio stampare gli in un file di testo, l'ultimo ip risulta essere 90.117.27.18, e quello precedente 90.117.27.188.

Non riesco proprio a capire perchè verso la fine manchino gli ultimi ip. Allargando il range non cambia niente, stesso problema ma con numeri diversi.

Questo é il programma:



import java.io.*;

class Range {
public static void main(String args[]) throws IOException {

BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
PrintWriter pwr = new PrintWriter(new FileWriter("ip.txt"));

int blc,r1=23,r2=29, arr[]=new int [256];

arr[0]=90;
arr[1]=117;

for (int j=0; j<=r2-r1; j++) {
for (int i=1; i<=255; i++) {
pwr.println(arr[0]+"."+arr[1]+"."+(r1+j)+"."+i);
}
}
}
}




Avete idea di come potrei effettivamente risolvere?
Non voglio aggirare il problema tipo allungare di 1 il range, fosse solo x quello mi farei la stampa degli ip con excel. Voglio proprio capire dove sta il problema in un programmino così semplice.

Grazie :)

PGI-Bis
11-11-2006, 02:36
flusha il flusho.

L'ultimo ip che leggi, 90.117.27.18, è un 90.117.27.189 ma la JVM è morta prima che il flusso avesse il tempo di svuotare il suo buffer. E c'erano anche gli altri, in coda.

Quando scrivi su un PrintWriter scrivi su un pezzo di RAM che, eventualmente e per mero accidente, viene riversato, in tutto o in parte, sul disco.

Così una volta che hai finito di scrivere, se vuoi che il contenuto sul file abbia tutti i byte che hai inviato attraverso il PrintWriter, devi "svuotare il PrintWriter" con:

printWriter.flush().

import java.io.*;

class Range {
public static void main(String args[]) throws IOException {
PrintWriter pwr = null;
try {
pwr = new PrintWriter(new FileWriter("ip.txt"));

int blc,r1=23,r2=29, arr[]=new int [256];

arr[0]=90;
arr[1]=117;

for (int j=0; j<=r2-r1; j++) {
for (int i=1; i<=255; i++) {
pwr.println(arr[0]+"."+arr[1]+"."+(r1+j)+"."+i);
}
}
pwr.flush();
} finally {
if(pwr != null) {
pwr.close();
}
}
}
}

Il finally con il close significa "me possino ammazza', pwr sarà chiuso prima che il metodo main restituisca il controllo". Si chiude lo stesso quando la JVM tira il calzino ma è un evento che, dal punto di vista delle librerie IO che usi, rientra tra i dettagli di uno solo dei molti ambiente JRE con cui il tuo codice è compatibile.

Taccio sulla strada intrapresa per raggiungere lo scopo :D.

andbin
11-11-2006, 12:06
Per generare un range di indirizzi si può anche realizzare una soluzione un pochino più articolata ma più generica.

Ho scritto questa classe:
public class InetAddressRangeGenerator
{
private byte[] from;
private byte[] to;
private int length;
private boolean finished;

public InetAddressRangeGenerator (InetAddress addrFrom, InetAddress addrTo)
{
byte[] fromTmp = addrFrom.getAddress ();
byte[] toTmp = addrTo.getAddress ();

if (fromTmp.length != toTmp.length)
throw new IllegalArgumentException ("Bad addresses");

from = fromTmp;
to = toTmp;
length = from.length;
finished = false;
}

public InetAddress nextAddress ()
{
InetAddress addr = null;

if (!finished)
{
int comp = 0;

for (int i = 0; i < length && comp == 0; i++)
{
comp = (from[i] & 0xFF) < (to[i] & 0xFF) ? -1 :
(from[i] & 0xFF) > (to[i] & 0xFF) ? +1 : 0;
}

if (comp <= 0)
{
try {
addr = InetAddress.getByAddress (from);
} catch (UnknownHostException e) { } // Non dovrebbe accadere

if (comp < 0)
{
int v, carry = 1;

for (int i = length-1; i >= 0; i--)
{
v = (from[i] & 0xFF) + carry;
from[i] = (byte) v;
carry = v > 255 ? 1 : 0;
}
}
}

if (comp >= 0)
finished = true;
}

return addr;
}
}Poi la si usa con:
try
{
InetAddress addrFrom = InetAddress.getByName ("90.117.23.0");
InetAddress addrTo = InetAddress.getByName ("90.117.29.255");

InetAddressRangeGenerator rangeGen = new InetAddressRangeGenerator (addrFrom, addrTo);

InetAddress ad;

while ((ad = rangeGen.nextAddress ()) != null)
System.out.println (ad.getHostAddress ());
}
catch (Exception e)
{
System.out.println (e);
}
In teoria dovrebbe funzionare anche con indirizzi IPv6, io comunque l'ho testata solo con indirizzi IPv4.

Che ne dite???

PGI-Bis
11-11-2006, 12:13
Che ne dite???

Ne dico tutto il bene possibile :).

karplus
11-11-2006, 16:14
flusha il flusho.

L'ultimo ip che leggi, 90.117.27.18, è un 90.117.27.189 ma la JVM è morta prima che il flusso avesse il tempo di svuotare il suo buffer. E c'erano anche gli altri, in coda.

Quando scrivi su un PrintWriter scrivi su un pezzo di RAM che, eventualmente e per mero accidente, viene riversato, in tutto o in parte, sul disco.

Così una volta che hai finito di scrivere, se vuoi che il contenuto sul file abbia tutti i byte che hai inviato attraverso il PrintWriter, devi "svuotare il PrintWriter" con:

printWriter.flush().


Taccio sulla strada intrapresa per raggiungere lo scopo :D.

Avevo dimenticato il .flush() e il close(), lol :muro:

Ti ringrazio dell'esauriente spiegazione tecnica, ma ora voglio sapere che strada hai intrapreso. :O



Che ne dite???

Dico che la tua é sicuramente più figa, ma io sono per il codice più stringato possibile. :D

Però toglimi una curiosità, sta parte proprio non la capisco, me la spiegheresti? :confused:



for (int i = 0; i < length && comp == 0; i++)
{
comp = (from[i] & 0xFF) < (to[i] & 0xFF) ? -1 :
(from[i] & 0xFF) > (to[i] & 0xFF) ? +1 : 0;
}

PGI-Bis
11-11-2006, 16:25
... ma ora voglio sapere che strada hai intrapreso. :O

Taccio nel senso che non dico nulla sul codice perchè ne comprendo la natura sperimentale: è per provare e non mi pare il caso di lanciarsi in disquisizioni stilistiche.

C'è qualche tocco "bizzarre" :D.

Il tuo arr è un array di 256 interi ma di quei 256 ne usi solo due (il primo e il secondo).

Melius abundare quam deficere? :D

andbin
11-11-2006, 16:34
Però toglimi una curiosità, sta parte proprio non la capisco, me la spiegheresti? :confused:
for (int i = 0; i < length && comp == 0; i++)
{
comp = (from[i] & 0xFF) < (to[i] & 0xFF) ? -1 :
(from[i] & 0xFF) > (to[i] & 0xFF) ? +1 : 0;
}Certo, lo spiego subito.

Quel codice effettua una comparazione tra l'indirizzo contenuto nei bytes in 'from' e quelli in 'to'. La comparazione serve per stabilire se ho raggiunto o meno l'indirizzo 'to'.
L'indirizzo è memorizzato nell'array in "network byte order", ossia il byte più significativo è il primo nell'array. Quindi parto dal primo byte e vado in avanti.
Ho utilizzato l'operatore condizionale ternario, per compattare un po' il codice.

Avrei potuto scrivere la stessa cosa con degli if:
if ((from[i] & 0xFF) < (to[i] & 0xFF))
comp = -1;
else if ((from[i] & 0xFF) > (to[i] & 0xFF))
comp = +1;
else
comp = 0;Più chiaro così??

Appena ottengo un comp diverso da zero, posso uscire dal ciclo, altrimenti continuo il ciclo per verificare i byte man mano meno significativi.

Alla fine posso avere comp = -1, 0 o +1 che mi dice se 'from' è minore, uguale o maggiore di 'to'.

Notare (e questo è importante) la AND con 0xFF. Il byte, in Java, è un tipo di dato con segno. Questo vuol dire che 0xFF è minore di 0x01. Facendo una operazione di AND, non solo porto il byte temporaneamente a 'int' ma lo tronco per evitare l'estensione di segno, avendo così un valore 0...255.

karplus
11-11-2006, 18:13
Taccio nel senso che non dico nulla sul codice perchè ne comprendo la natura sperimentale: è per provare e non mi pare il caso di lanciarsi in disquisizioni stilistiche.

C'è qualche tocco "bizzarre" :D.

Il tuo arr è un array di 256 interi ma di quei 256 ne usi solo due (il primo e il secondo).

Melius abundare quam deficere? :D

Esatto, nella versione di prova é meglio stare larghi con la dimensione degli array :D

Teoricamente dovrebbe servire a incamerare i 4 blocchi dell'ip, perchè abbia scelto 256 resta un mistero cmq :asd:



Thx ad andbin per la spiegazione, me la devo leggere ben bene perchè 0xFF manco sapeva che si poteva usare :D