Protokol IP, adresa a maska, směrování, IP multicast

Následující článek vám vysvětlí, co je to vlastně ta IP adresa a proč, když si chcete zahrát csko po LANce, tak musíte vyplnit nějaké 255.255.255.0. Ale pěkně popořadě.

IP adresa

Jedná se jednoznačný identifikátor počítače v síti (ale té počítačové), pokud je používán protokol IP, což bude platit prakticky pro každého čtenáře tohoto článku. IP adresa se skládá ze čtyř částí, které oddělují tečky. Každé této čtvrtině se říká oktet, IP adresa je tedy složena ze čtyř oktetů. Každý oktet může obsahovat číslo v rozmezí  0 až 255. Proč zrovna 255? Protože na uložení čísla máme jen 8 bitů, tedy jeden bajt a pokud tento bajt vyplníme samými jedničkami, tak větší číslo než 255 nedostaneme (111111112 => 25510). Takový běžný domácí počítač mívá IP adresu ve stylu 192.168.1.X nebo 10.0.0.X, kde X je typicky malé číslo (např. 1, 2 nebo 3) .

Proč já mám 192.168.1.1, kamarád taky a internet nespadne?

Protože kamarád bydlí jinde, a má u sebe jinou počítačovou síť, než je u vás doma. Koukněte znovu na první řádek předcházejícího odstavce, IP adresa musí být jedinečná v rámci sítě, kterých je ale na světě nepočítaně (Blaník, Jára Cimrman). Kamarád má síť, vy máte síť. Ale zkuste se oba sejít např. u vás doma (v rámci jedné počítačové sítě) a oba dva si nastavte stejnou IP adresu, to se teprve budou dít divy :-).

Protokol IP

Toto téma jsme už načali, troufale jsem tvrdil, že protokol IP používá prakticky každý. Umí totiž velice důležitou věc, propojit více sítí dohromady. Tohoto cíle dosahuje směrováním paketů. Až si budete na Facebooku psát se svým kamarádem, bude to právě protokol IP, který zaslanou zprávu přes různé počítačové sítě doručí na servery Facebooku a odtud až do počítače vašeho známého. Zmíněný paket se skládá jak se samotné zaslané zprávy na Facebooku (např. jj, příjdu), tak metadat, s jejíchž pomocí bude protokol IP vědět, kam paket doručit.

Zajímavé je, že protokol IP nezaručuje, že paket skutečně doručí, jen se o to pokusí. Což může být docela problém, že? Co kdybychom posílali přes datovou schránku daňové přiznání a ono nedorazilo? Proto se IP kombinuje s dalším protokolem TCP. Výsledné kombinaci se říká TCP/IP a zmíněné TCP v této dvojici zaručuje spolehlivé doručení zprávy ve správném pořadí. Ne vždy je to ale výhodné. Až bude Česko sledovat na internetu mistrovství světa v hokeji, počítačové sítě by měly co dělat, pokud by musely garantovat dodání každého pixelu v obraze, přičemž výpadek jednoho čtverečku běžně člověk ani není schopný zaregistrovat. Naštěstí zde máme protokol UDP, opět kombinovaný s IP do podoby UDP/IP. UDP na spolehlivost příliš nehledí, raději se zaměřuje na rychlost. Servery České televize pak nemusí přeposílat ztracený (a v tu dobu již starý) pixel, protože hokejové utkání již pokročilo o nějakou vteřinu a raději odešlou aktuální data.

Maska

Teď se můžeme vrátit k IP adrese a vysvětlit si pojem maska. Správně totiž nemá moc smysl uvádět jen samotnou IP adresu, protože maska s ní umí dělat úplné divy a tak je více než žádoucí ji znát. Každá IP adresa je rozdělena na 2 části. První část udává síť, druhá již identifikuje konkrétní zařízení v síti. Podívejme se například na populární kombinaci 192.168.1.1 a masku 255.255.255.0. Masku si musíme převést do binární podoby a počet jedniček zleva nám říká, kde se IP adresa dělí na zmíněné dvě poloviny.

  • Maska 255.255.255.0 je binárně 11111111.11111111.11111111.0, máme zde tedy 24 jedniček.
  • IP adresa 192.168.1.1 je binárně 11000000.10101000.00000001.00000001, zleva si odpočítáme 24 pozic, protože naše maska má 24 jedniček.

Po rozdělení máme 11000000.10101000.00000001.00000001. Červená část udává síť, modrá prostor, který můžeme použít k identifikaci zařízení (např. počítačů) uvnitř této sítě.

V adresním prostoru automaticky vznikají dvě speciální adresy:

  • 11000000.10101000.00000001.00000000 = 192.168.1.0 — tedy samé nuly v druhé části adresy. Takové IP adrese se říká adresa sítě.
  • 11000000.10101000.00000001.11111111 = 192.168.1.255 — tedy samé jedničky v druhé části adresy. Takové IP adrese se říká adresa broadcastu. Tuto adresu použijeme, pokud chceme zprávu poslat všem uzlům v síti.

K čemu je tedy ta maska? Stručně řečeno, s její pomocí lze měnit rozsah jednotlivých sítí a vytvářet podsítě. U sebe doma si tak např. můžete vyrobit 2 sítě, které se vzájemně neuvidí a k jejich propojení použijete router. K příkladu z úvodu článku — masku při vytváření LAN uvádíme proto, aby počítače byly na stejné síti a vzájemně se viděly.

Směrování

Router neboli směrovač je krabička, která přeposílá pakety. Umí adresovat (směrovat) mezi sousedními sítěmi. Switch dělá něco podobného ale pouze na úrovni lokální sítě. Krásně je to napsáno na Wikipedii:

Rozdílné funkce routerů a switchů si lze představit jako switche coby silnice spojující všechna města ve státě a routery coby hraniční přechody spojující různé země.

Ta krabička co máte pod stolem tedy automaticky není vždy router, i když jí tak možná říkáte. Také může jít o switch. Je jednoduchá metoda, jak poznat, co vám to tam vlastně bliká. Switch ke svému běhu nepotřebuje IP adresu. Koupíte jej v obchodě, donesete domů, strčíte do něj kabel a to je vše. Router je ve své podstatě počítač, který ale nedělá nic jiného, než že neustále přeposílá (směruje) pakety. Ke svému běhu musí mít nastavenou IP adresu, vlastně ideálně dvě, aby mohl mezi těmito dvěma sítěmi směrovat.

IP multicast

Někdy potřebujeme odeslat paket na více cílových stanic zároveň. Představme si například internetové rádio, pro které je zbytečné duplikovat provoz a odesílat ta samá data k mnoha počítačům separátně. Na místo toho je lepší vytvořit tzv. IP multicast. Cílové stanice v tomto případě sdružíme do skupin a paket odešleme právě do této skupiny. Zmíněnou funkcionalitu přináší protokol IGMP.

Funkce a triggery v PostgreSQL

postgresql-triggerNásledující článek se bude hodit každému, kdo již má určité zkušenosti s SQL a rád by si vyzkoušel napsat vlastní funkci nebo trigger. Začneme velmi zvolna, nejprve si představíme, jak napsat jednoduchou funkci a následně se vrhneme na triggery.

Vlastní funkce v PostgreSQL

Funkce dělá přesně to, co její matematický protějšek. Pro vstupní hodnotu vrátí určitý údaj. My si nyní vytvoříme funkci, co nebude vyžadovat argument a vždy vrátí číslo jedna — to jen pro zahřátí, taková funkce samozřejmě není moc užitečná, ale alespoň se podíváme, jak vlastně vypadá její syntaxe.


CREATE FUNCTION test() RETURNS integer AS $$

SELECT 1 AS result;

$$ LANGUAGE SQL;

SELECT test(); --vypíše 1

Nejprve s pomocí CREATE FUNCTION vymezíme, že začínáme psát funkci. Poté uvedeme její název (zde test) a prázdnou závorku, protože nepřebíráme žádné argumenty. Databázový server zajímá, jaký datový typ bude naše funkce vracet, proto jej uvedeme (integer). Za klíčovým slovem AS začíná vymezení samotného těla funkce, které z obou strany obklopuje symbol dvou dolarů ($$). Závěrem uvedeme použitý jazyk (LANGUAGE SQL) a nezapomeneme na středník, podobně jako v těle funkce, ve kterém jednoduše s pomocí příkazu SELECT získáme číselnou hodnotu 1.

Pojďme zkusit něco užitečnějšího, naučíme se používat argumenty:


CREATE FUNCTION plus(integer, integer) RETURNS integer AS $$
 SELECT $1 + $2 AS result;
$$ LANGUAGE SQL;

SELECT plus(10, 5); --vypíše 15

SELECT plus(5, 'a'); --Error in query: ERROR: invalid input syntax for integer: "a"

Tato funkce umí sečíst dvě čísla. U argumentů uvádíme jen datový typ a na hodnotu se odkazujeme s pomocí dolaru a indexu (první argument je dostupný s pomocí $1).

Než se vhrneme na náš první trigger, smažeme z databáze vytvořené funkce. Udělá se to následovně:


DROP FUNCTION test();

DROP FUNCTION plus(integer, integer);

Jednoduchý trigger v PostgreSQL

Na úvod si představme, že máme tabulku human  obsahující údaje o lidech. Uchováváme jedinečné ID, jméno, příjmení a oslovení. Napíšeme si trigger, který nám bude zmíněné oslovení generovat automaticky. Nejprve vytvoříme samotnou funkci, kterou server následně automaticky zavolá. Daná funkce nebude dělat nic jiného, než že vezme jméno i příjmení a spojí oba údaje mezerou.

tabulka_human


CREATE FUNCTION concatenate() returns trigger AS $$
BEGIN
UPDATE human SET salutation = (NEW.name || ' ' || NEW.surname) WHERE id = NEW.id;
RETURN NULL;
END;
$$ LANGUAGE plpgsql;

Oproti zápisu funkce je zde několik rozdílů. Trigger nikdy nemá argumenty a jako návratový typ uvádíme slovo trigger. Do těla se nám dostala část BEGIN a END; (pozor na středník). Uvnitř těla smíme používat proměnnou NEW, která odkazuje na nově vytvořený/upravený řádek. Příkazem RETURN vracíme výsledek funkce (zde je NULL, protože nic vracet nechceme). Klauzule LANGUAGE obsahuje plpgsql, protože píšeme trigger pro PostgreSQL.

Pojďme nyní naší tabulku donutit, ať trigger volá automaticky při každém vložení hodnoty:


CREATE TRIGGER human_trigger AFTER INSERT ON human
FOR EACH ROW EXECUTE PROCEDURE concatenate();

Zápis je hodně upovídaný a osobně se mi špatně pamatuje. Zase se naopak dobře čte :-). Uvádíme pojmenování našeho triggeru (human_trigger), název tabulky (human) a samotnou funkci, co bude volána (concatenate());

A nyní pozor, stačí nám spustit následující příkaz a v tabulce objevíme automaticky vygenerované oslovení:


INSERT INTO human(name, surname, salutation) VALUES ('Jan', 'Novák', '?');

Sloupec salutation nedovoluje hodnoty NULL, proto musíme nějakou uvést, i když bude následně přepsána triggerem. To je nepříjmené, pojďme si náš trigger vylepšit! Funkci nebudeme volat po zápisu řádku, ale před zápisem (a v tuto chvíli si vygenerujeme oslovení).


CREATE FUNCTION concatenate() returns trigger AS $$
BEGIN
NEW.salutation := NEW.name || ' ' || NEW.surname;
return new;
END;
$$ LANGUAGE plpgsql;

S pomocí proměnné NEW přiřadíme oslovení. Hotovu funkci poté budeme volat před provedením INSERT nebo v případě UPDATE:


CREATE TRIGGER human_trigger BEFORE INSERT OR UPDATE ON human
 FOR EACH ROW EXECUTE PROCEDURE concatenate();

Vlastnosti typových systémů

vlastnosti-typovych-systemuK čemu v programování slouží typový systém? Jde o nástroj k porovnávání datových typů jednotlivých proměnných, které se provádí před operací v libovolném výrazu. Díky typovému systému zajistíme, že nedojde k chybě spočívající v kombinaci špatných datových typů (například když se pokusíme sečíst číslo a textový řetězec).

Silně a slabě typované jazyky

Typový systém může na problematiku nahlížet dvěma způsoby. Silně typované programovací jazyky striktně vyžadují pouze předem vymezené datové typy. Každá operace v takovém jazyce má proto určené jaké datové typy argumentů akceptuje. Do této kategorie patří např. Java nebo C.

Naopak tomu slabě typovaný jazyk se snaží operaci provést za každou cenu a proto přistupuje k přetypování. Vraťme se k příkladu z úvodu. Součet čísla a textového řetězce zdá se nedává smysl, ovšem co když v textu máme uložené opět číslo? Pak jazyku nic nebrání v tom, aby provedl přetypování textu na číslo a vypočítal výsledný součet. Ač se popsané chování může jevit jako jednoznačná výhoda, záleží na úhlu pohledu, někdy mohou díky této slabé kontrole datových typů vznikat hůře odhalitelné chyby. Popsaným způsobem se chová např. PHP nebo JavaScript.

Staticky a dynamicky typované jazyky

Programovací jazyk, který datové typy proměnných zjišťuje staticky, provádí vstupní analýzu kódu, během které je schopný odhalit datový typ každé proměnné. Napomáhá tomu mimo jiné to, že datový typ je zpravidla nutno deklarovat. Díky tomu pak překladač může lépe optimalizovat vytvářený kód (přesně totiž ví, s čím přichází do styku). Uvedené informace se vztahují k většině dnešních programovacích jazyků.

Existuje ovšem i jiný přístup. Co kdybychom datový typ zjistili až za běhu programu? Pak může jedna proměnná obsahovat několik naprosto rozdílných hodnot. Nemluvíme zde proto o typu proměnné (to platí pro staticky typované jazyky) ale o typu hodnoty. S uvedeným přístupem přichází např. jazyk Perl.

Bezpečně a nebezpečně typované jazyky

U bezpečně typovaných jazyků máme zajištěno, že pokud je operace proveditelná (tedy je splněna náležitost v podobě správných argumentů), tak vždy bude operace úspěšně dokončena. Nestane se zkrátka, že kvůli prováděné operaci aplikace spadne.

Naopak tomu jako už název prozrazuje nebezpečně typované jazyky dávají programátorovi šanci dostat výpočetní proces do nekonzistentního stavu. Díky existenci pointeru je poměrně jednoduché tohoto cíle dosáhnout v jazyce C nebo C++. Můžeme totiž různě přesouvat obsahy proměnných i obměňovat místa, kam v paměti ukazujeme.

void main()
{
    int *x = 0; //nulový ukazatel (NULL pointer)
    *x = 42; //chyba, na toto nulové místo se snažíme uložit hodnotu
}