View Full Version : [java] generare range di ip: capitano ip tronchi
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 :)
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.
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???
Che ne dite???
Ne dico tutto il bene possibile :).
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;
}
... 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
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.
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
vBulletin® v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.