package uebung2;
public final class IpConverter {
//Author: Paul W******
private static final String SPLIT_EXP = "\\."; //Diese Konstante wird später benötigt, um den String zu splitten.
public static final long BITMASK = 255; //Die Bitmaske wird später zum Verknüpfen gebraucht.
/****************************************************************************************************
* ipStrAsLong: Methode um eine IP-Adresse von einem String in einen long zu packen. *
* Die vier durch Punkte getrennten Werte der IP (die vier Bytes) werden durch parsing *
* ermittelt und dann mit Hilfe des binären left-Shift Operators an die richtige Position *
* eines longs geschoben *
* Die vier letzten Bytes des long enthalten so den dazugehörenden Wert der IP. *
* Ist z.B. die eingegebene IP 255.255.254.0, sieht die Aufteilung im long so aus: *
* Byte 1 bis 4: Nicht benutzt und deswegen mit 0en belegt *
* Byte 5: 255 *
* Byte 6: 255 *
* Byte 7: 254 *
* Byte 8: 0 *
* Ein long (wie jeder andere Zahlentyp bei Java auch) kann sowohl dezimal als auch binär *
* interpretiert werden, je nachdem, was benötigt wird. Eine Umrechnung ist nicht erforderlich *
* Es wird ein long statt eines int verwendet, weil eine IP-Adresse vorzeichenlos ist. *
* In einem int wird das erste bit aber als Vorzeichen interpretiert (Stichwort: Zweier-Komplement). *
* Dies kann bei Berechnungen und dem Sortieren von Werten zu merkwürdigen Effekten führen. *
****************************************************************************************************/
public static long ipStrAsLong (final String ipStr) {
long result = 0;
final String[] strArray = ipStr.split(SPLIT_EXP); //String-Array erzeugen, String bei den Punkten splitten und ins Array schreiben
for(int i = 0; i < strArray.length; i++) { //Array durchgehen
int temp = Integer.parseInt(strArray[i]);
result = result|temp; //long result bitweise mit int temp verknuepfen
if(i != (strArray.length -1)) { //wenn nicht am Ende des Arrays angelangt, letzten Wert 8 Bits nach links shiften.
result = result << 8;
}
}
return result;
}
/*************************************************************************************************************
*longAsIpStr: Umgekehrte Methode von IpStrAsLong. Aus dem vorher gepackten long (der IP), werden zunächst *
* die Zahlenwerte ausgelesen und in das Array intArray gepackt. Der long wird von hinten nach vorne *
* durchgearbeitet, daher auch das Array von hinten gefüllt. Dies geschieht, indem zunächst alles bis auf das *
* letzte Byte des longs 0 gesetzt wird. So bleibt die gesuchte Zahl übrig und wird ins Array geschrieben. *
* Dann wird ein Byte nach rechts geshiftet, und das vorletzte Byte wird an die vorletzte Stelle des Arrays *
* geschrieben. Der Shift- und Schreibvorgang geschieht dann noch zweimal, bis alle vier Zahlenwerte der IP *
* im Array stehen. *
* In weiterer Folge wird das Array von vorne nach hinten durchgegangen und die Werte in den Ausgabestring *
* geschrieben, wobei Dezimalpunkte hinzugefügt werden, damit wieder eine IP entsteht. *
*************************************************************************************************************/
public static String longAsIpStr (long value) {
int[] intArray = new int[4]; //Array zum Speichern der Werte.
String resultStr= ""; //String, in dem das Ergebnis gespeichert wird.
for(int i = intArray.length -1; i >= 0; i--) {
intArray[i] = (int) (value&BITMASK); // alle Werte bis auf das letzte Byte in value 0 setzen und von hinten die Positionen des Arrays füllen (downcast nach int)
value = value >> 8; //8 bits nach rechts shiften
}
for(int i = 0; i < intArray.length; i++) { //Aus den ints im Array den String zusammenbauen.
if(i == (intArray.length -1)) {
resultStr = (resultStr + intArray[i]);
}else {
resultStr = (resultStr + intArray[i] + ".");
}
}
return resultStr;
}
/****************************************************************************************************
* outputSubnetValue: Methode, um die kleinste und größte IP-Adresse aus einer eingegebenen IP *
* + Subnetzmaske zu ermitteln. Zunächst werden die beiden Strings mithilfe von ipStrAsLong() in *
* longs gepackt. Dann wird die IP mit der Netzmaske binär verknüpft, womit der Netzwerkteil der IP *
* bestimmt wird. Dieser ist zugleich auch die Subnetznummer, die niedrigste IP ergibt sich aus *
* Subnetznummer + 1. *
* Daraufhin wird die Anzahl der möglichen IPs ausgerechnet, indem die Subnetzmaske als int *
* gedowncastet wird. Die Anzahl der möglichen IPs + die niedrigste IP ergibt dann die höchste IP +1*
* , weil die Broadcast-Adresse nicht mitgerechnet werden darf. Die niedrigste und höchste IP werden*
* schlussendlich in einen String geschrieben und als Rückgabewert zurückgegeben. *
***************************************************************************************************/
public static String outputSubnetValue(String ip, String netmask) {
String resultStr = "";
long ipLong = ipStrAsLong(ip);
long netmaskLong = ipStrAsLong(netmask);
long netpart = ipLong&netmaskLong; //IP mit Netzmaske verknüpfen, hiermit wird der Netzwerkteil der IP bestimmt
int netmaskInt = (int) netmaskLong; //durch den downcast der netmask zu int wird die negative Anzahl der Möglichkeiten gefunden (Zweierkomplement)
netmaskInt = Math.abs(netmaskInt); //Anzahl positiv machen
long highest = netpart + netmaskInt; //höchsten Wert der IP bestimmen, indem die Anzahl der möglichen IPs zur niedrigsten Adresse addiert wird
resultStr=(longAsIpStr(netpart +1 ) + " bis " + longAsIpStr(highest -2)); // die longs werden in Strings umgewandelt -> niedrigste + 1, weil .0 nicht vergeben werden darf
return resultStr; //(Fortsetzung) höchste -2, weil Broadcast nicht vergeben werden darf
}
}