Kalkulator IP
Zadanie 300: Kalkulator IP
Wstęp
Adresacja IP to jeden z fundamentów działania sieci komputerowych. Zrozumienie, jak komputer przetwarza adres IP oraz maskę podsieci, jest kluczowe dla każdego, kto zajmuje się administracją sieci czy programowaniem aplikacji sieciowych. W tym zadaniu zajmiemy się stworzeniem własnego kalkulatora IP w języku JavaScript.
Podstawowe elementy kalkulatora IP
Kalkulator IP służy do wyznaczania kluczowych parametrów podsieci na podstawie podanego adresu IP i maski podsieci. Do głównych elementów, które musimy obliczyć, należą:
- Adres sieci (Network Address): Pierwszy adres w podsieci, reprezentujący samą sieć. Nie może być przypisany do żadnego urządzenia (hosta).
- Adres rozgłoszeniowy (Broadcast Address): Ostatni adres w podsieci, używany do wysyłania pakietów do wszystkich urządzeń w danej sieci naraz.
- Minimalny adres hosta (Min IP / First Host): Pierwszy użyteczny adres IP wewnątrz sieci, który możemy przypisać urządzeniu (Adres sieci + 1).
- Maksymalny adres hosta (Max IP / Last Host): Ostatni użyteczny adres IP wewnątrz sieci, który możemy przypisać urządzeniu (Adres rozgłoszeniowy - 1).
- Liczba komputerów w sieci (Number of Hosts): Całkowita liczba użytecznych adresów IP w danej podsieci. Obliczana jest za pomocą wzoru
2^(32 - maska) - 2. Dwa wykluczone adresy to zawsze adres sieci i powiązany z nią adres rozgłoszeniowy.
Parsowanie adresu IP i maski w JavaScript
Maszyny dokonują obliczeń sieciowych binarnie na 32-bitowych ciągach znaków. Aby ułatwić nam logikę, najpierw musimy przetworzyć (sparsować) ciąg znaków (np. "192.168.1.10") na jedną matematyczną postać liczbową, użyteczną do operacji bitowych.
1. Parsowanie adresu IP
Adres IP w wersji 4 (IPv4) składa się z 4 oktetów zapisanych dziesiętnie, oddzielonych kropkami. Najłatwiej przekształcić go na jedną 32-bitową liczbę całkowitą (integer). Użyjemy do tego wbudowanej metody split(".") w celu rozdzielenia wyrazu na cztery osobne blok-oktety. Następnie posłużymy się przesunięciem bitowym w lewo (<<) i w rezultacie połączmy za pomocą operatora bitowego OR (|) w jedną wielką liczbę.
// Przykładowa funkcja parsująca tekstowy adres IP do liczby 32-bitowej
function ipToNum(ip) {
let octets = ip.split('.'); // tworzymy tablicę np. ["192", "168", "1", "10"]
return (parseInt(octets[0]) << 24) |
(parseInt(octets[1]) << 16) |
(parseInt(octets[2]) << 8) |
parseInt(octets[3]) >>> 0;
// `>>> 0` wymusza na końcu potraktowanie liczby jako bez znaku (unsigned)
}
2. Parsowanie maski podsieci
Maska w praktycznych ćwiczeniach często podawana jest w krótkim formacie CIDR (np. /24), oznaczającym ile początkowych bitów (od strony lewej) to jedynki, decydując o zasięgu sieci. Możemy z niej wygenerować 32-bitową liczbę:
// Zamiana maski CIDR (np. liczba 24) na liczbę 32-bitową do operacji
function cidrToMaskNum(cidr) {
// Generowanie maski: (-1 to binarnie same jedynki)
// Przesuwamy w lewo o "wolne miejsca", następnie ucinamy operatorami do wartości bez znaku.
return (-1 << (32 - cidr)) >>> 0;
}
Obliczanie poszczególnych elementów
Po przekonwertowaniu adresu IP oraz maski podsieci do wspomnianych liczb układających się bitowo, otrzymujemy pełną dowolność, aby dokonać niezbędnych obliczeń logicznych dla naszego kalkulatora:
1. Adres sieci (Network)
Adres sieci znajduje się "wycinając" tylko wspólne mianowniki z adresacji bazowej przy użyciu logicznego AND (&) między wygenerowaną liczbą z IP a z Maski.
// Mając ipNum oraz maskNum
let networkNum = (ipNum & maskNum) >>> 0;
2. Adres rozgłoszeniowy (Broadcast)
Za wyliczenie broadcastu odpowiada dodanie przeciwnej (odwróconej) formy maski. Używamy logicznego OR (|) z odwróconą za pomocą bitowego NOT (~) maską podsieci.
let invertedMaskNum = ~maskNum;
let broadcastNum = (networkNum | invertedMaskNum) >>> 0;
3. Pierwszy oraz Ostatni host (Min IP / Max IP)
Minimalny IP i Maksymalny IP to jedynie zwykłe operatory obok skrajnych części wykluczonych na zewnątrz.
let minIpNum = networkNum + 1;
let maxIpNum = broadcastNum - 1;
4. Liczba adresów użytecznych w sieci
Jest to matematyczne spotęgowanie wolnych bitów przestrzeni minus dwa zarezerwowane adresy brzeżne.
let numHosts = Math.pow(2, 32 - cidr) - 2;
// W normalnych podsieciach odejmujemy od potęgi cyfrę 2. (Gdy maska jest większa od 30 to zasady potrafią się zmienić).
Jak przywrócić format znaków po obliczeniach?
Mając już gotowe w wariantach liczbowych dane o np. Twoim networkNum, możemy zamaskować je od nowa dzieląc układ i wydobywając operacjami AND (& 255) reszty bajtowe spajając kropką za pomocą wbudowanego na końcu join().
function numToIp(num) {
return [
(num >>> 24) & 255,
(num >>> 16) & 255,
(num >>> 8) & 255,
num & 255
].join('.');
}
// Przykład
// console.log(numToIp(networkNum)); // Zwróci np. "192.168.1.0"
Zadania dodatkowe (obowiązkowe)
Poniżej znajdziesz 5 dodatkowych wytycznych do wykonania w swoim kodzie. Traktujemy je jako podstawę tego zadania - są to instrukcje obowiązkowe do wykonania, a nie tylko ukłon dla chętnych. Rozwiąż je, dopracowując swój skrypt krok po kroku.
- Walidacja danych wejściowych (RegEx/If-y): Zabezpiecz kalkulator mechanizmem, który przed jakimkolwiek bitowym obliczeniem zweryfikuje, czy podany ciąg jako adres IP ma odpowiednią formę (cztery liczby w zakresie 0-255 przedzielone wyłącznie kropeczkami) oraz czy maska podsieci w notacji CIDR mieści się matematycznie w twardym spektrum od /0 do /32. Jeżeli wynik z wejścia da fałsz, program powinien przerwać pracę i wygenerować wyjątek logu np. za pomocą
console.error(). - Zwracanie danych w postaci gotowego Obiektu (JSON): Twój kalkulator jako instrukcja globalna funkcji (np. pod klamrą
kalkulatorIp()) po zakończeniu całego procesu ma agregować dane, by zamiast wylewać je prosto z czeluści terminala, finalnie zwrócił za pośrednictwemreturnjeden kompletny obiekt (JavaScript Object). Powinien on posiadać wyraźne klucze dla właściwości:network,broadcast,first_host,last_hostorazhosts_count(oczywiście wehikuł zwrócony stringami przez wspomnianą funkcjęnumToIp(...)). - Obsługa masek w formie dziesiętnej (kropkowej): Zmodyfikuj początki swojego kodu parsującego tak, aby program opcjonalnie mógł zaakceptować na wejściu maskę jako pełen adres kropkowy obok IP (np.
255.255.255.0zamiast liczby/24). Skrypt po wykryciu kropek wykona procedurę "wypluwania" notacji (zwracając, że255.255.255.0posiada zapalonych domyślnie "24" bitów jedynek od lewej). Wykorzystaj to, by wrócić z procesem do logiki klasycznej dla liczby CIDR. - Rozpoznawanie historycznej klasy IP oraz puli prywatnej: W obiekcie JSON z punktu drugiego mają znaleźć się dwa kolejne, nowe klucze. Oznacz dla zbadanego zakresu na zasadzie klasyki domyślną Klasę Sieci (klucz np.
network_class) oddającABCDewentulnieE; po czym dorzuć wartość informującątrue/false, która zdradzi odpowiednio napisanymi po sobie poleceniami warunkowymi, czy jest to popularny "Prywatny Adres IP" (adres zza maskarady domowej puli 192.168.x.x, 10.x.x.x, 172.16-31.x.x). - Budowa interfejsu przeglądarkowego HTML/CSS/DOM: Wyłuskaj esencję stworzonej logiki z terminala umieszczając skrypt w złączeniu pliku
index.html. Zbuduj formularz posiadający proste kafelki dlaAdresu IPorazMaski. Dopracuj go kodem JS wprowadzając funkcję cyklicznie nasłuchującą (addEventListener), dzięki której podanie/zmiana liter na wejściu błyskawicznie – w czasie rzeczywistym zaktualizuje osadzoną statycznie tabelkę na dole okna uderzając bezpośrednio przez polecenieinnerHTML. Postaraj się również ostylować graficznie swój kalkulator w skromnym stopniu używając reguł CSS.