﻿<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xml" href="/cjs/screen.xsl" media="screen"?>
<lecture>

<meta>
  <maintitle>Sítě</maintitle>
  <author>Jiří Znamenáček</author>
  <title>Co všechno se musí (a může) stát, aby prohlížeč zobrazil vyžádanou stránku</title>
  <date>2010-12-02</date>
  <link><!--a href="http://vyuka.ookami.cz" rel="external">http://vyuka.ookami.cz</a--></link>
</meta>
<!--
  „“–
-->


<slide title="Úvod">

  <p>
    Když prohlížeč zobrazuje webové stránky příslušející např. doméně <code>http://www.python.org</code>, z hlediska uživatele se toho zdánlivě moc nestane – prostě napíšeme do adresního řádku adresu (většinou i bez identifikace protokolu <code>http://</code>) a na obrazovce se nám „magicky“ objeví požadovaná stránka.
  </p>
  <p>
    Z hlediska prohlížeče se toho ale musí (či může) stát mnohem více, než by člověk nejen na první pohled čekal. Podívejme se tomu na zoubek trošku podrobněji.
  </p>

</slide>
<slide title="Vyrovnávací pamět („cache“)">

  <p>
    Předně – pro někoho asi trochu překvapivě – se vůbec nemusíme dívat na skutečně aktuální podobu příslušné stránky. Někde cestou od nás k cílovému zdroji totiž může být uložena starší kopie, které dosud nevypršela doba platnosti. Konkrétně:
  </p>
  <ol>
    <li>
      Prohlížeč může požadovaný zdroj nalézt s dosud nevypršenou dobou platnosti ve své vlastní vyrovnávací paměti.
    </li>
    <li>
      Nebo se kopie zdroje může nacházet kdesi cestou v některé ze síťových vyrovnávacích pamětí (typicky proxy-server vašeho poskytovatele připojení).
    </li>
  </ol>
  <p>
    Teprve pokud nic z výše uvedeného nenastane, stáhne se požadovaný zdroj z původního umístění.
  </p>
  
  <handout>
    Podle ceho browser pozna, ze ma v cachi prave pozsadovany zdroj? To nedela zadne dotazy "ven"?
    Kdyz se clovek podiva treba na Firefox, tak je tam zaznamena cela adresa, tak se snad rozhoduje podle ni...
  </handout>

</slide>
<slide title="HTTP">

  <p>
    Dotaz k získání požadovaného zdroje je vyslán protokolem <code>HTTP</code>. Můžeme si ho názorně nasimulovat pomocí protokolu <code>telnet</code>. Přitom je třeba vědět, že (není-li uvedeno jinak) protokol HTTP je na cílovém počítači obsluhován službou (programem) naslouchajícím na portu 80. Proto (komentáře po znaku # nejsou součástí dotazu ani odpovědi!):
  </p>

  <example lang="http">
pirat@hotaru:~$ telnet www.python.org 80
Trying 2001:888:2000:d::a2...
Connected to www.python.org.
Escape character is '^]'.
GET / HTTP/1.1         # příkaz protokolu HTTP (získání zdroje z umístění „/“ pomocí protokolu HTTP verze 1.1)
Host: www.python.org   # dodatečná hlavička dotazu (minimálně tato jedna je při verzi protokolu 1.1 povinná)
↵                      # prázdná řádka (ukončuje dotaz)
# nyní už následuje odpověď – nejdříve její hlavička...
HTTP/1.1 200 OK
Date: Wed, 01 Dec 2010 16:17:20 GMT
Server: Apache/2.2.9 (Debian) DAV/2 SVN/1.5.1 mod_ssl/2.2.9 OpenSSL/0.9.8g mod_wsgi/2.5 Python/2.5.2
Last-Modified: Wed, 01 Dec 2010 11:59:27 GMT
ETag: "105800d-49e3-49658097825c0"
Accept-Ranges: bytes
Content-Length: 18915
Connection: close
Content-Type: text/html

# ...a tady po další prázdné řádce samotná data
&lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">


&lt;html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">

&lt;head>
  &lt;meta http-equiv="content-type" content="text/html; charset=utf-8" />
  &lt;title>Python Programming Language – Official Website&lt;/title>
  ...   # zbytek dat byl vynechán

# když se na otevřeném spojení jistou dobu nic neděje, je automaticky ukončeno
Connection closed by foreign host.
  </example>
  <!--note>
    Nadbytečné řádky jsou zde pouze kvůli formátování komentářů, ve skutečném HTTP-dotazu nejsou (a nesmí být!) přítomny.
  </note-->

  <p>
    Odpověď na dotaz obsahuje nejdříve návratovou HTTP-hlavičku (s kódem odpovědi 200, tedy že požadovaný zdroj byl skutečně nalezen a bude vrácen) a po <code>\r\n</code> (tedy <em>carriage return</em> + <em>line feed</em>) vlastní data (o délce 18 915 bajtů, jak je též oboje uvedeno v hlavičce).
  </p>

</slide>
<slide title="DNS – překlad jmen na adresy">

  <p>
    K zaslání dotazu jsme museli vědět, že HTTP-dotazy jsou na cílovém stroji obsluhovány na portu 80. Cílový stroj jsme přitom zadali pomocí jeho „lidského“ názvu. To ale není identifikace, kterou by použil počítač – ten si musel zjistit IP-adresu (ať už IPv4 nebo IPv6):
  </p>
  <example lang="http">
pirat@hotaru:~$ host www.python.org
www.python.org has address 82.94.164.162
www.python.org has IPv6 address 2001:888:2000:d::a2
  </example>

  <p>
    Pomocí jiného programu můžeme přijít i na to, od koho jsme danou odpověď získali:
  </p>
  <example lang="http">
pirat@hotaru:~$ nslookup www.python.org
Server:   	 172.20.20.23
Address:    172.20.20.23#53

Non-authoritative answer:
Name:    www.python.org
Address: 82.94.164.162
;; Received 124 bytes from 194.109.9.100#53(ns2.xs4all.nl) in 17 ms
  </example>

</slide>
<slide title="DNS-zóny, SOA-záznamy">

  <p>
    Jak ale počítač vůbec zjistí, koho a jak se ptát?
  </p>
  
  <p class="enumerate">
    V internetové prehistorii sloužil k překladu soubor <code>hosts</code>, který musel správce každého počítače připojeného do sítě pravidelně obnovovat z centrálního úložiště. Ještě dnes je tento soubor k dispozici, ale slouží už poněkud jinému účelu (pokud je vůbec nějak využit). Ale je jasné, že s přibývajícím počtem připojených počítačů to bylo neudržitelné.
  </p>
  <note>
    Konkrétně na Linuxu hledejte <code>/etc/hosts</code>, na Windows pak při klasické instalaci <code>C:\Windows\System32\drivers\etc\hosts</code>.
  </note>
  
  <p class="enumerate">
    Proto byl vynalezen protokol <strong>DNS</strong> (z <em>Domain Name System</em>). Podívejme se, jak vypadá dotaz na zjištění IP-adresy uvedené domény: 
  </p>
  <example lang="http">
pirat@hotaru:~$ dig python.org any +multiline

; &lt;&lt;>> DiG 9.7.0-P1 &lt;&lt;>> python.org any +multiline
;; global options: +cmd
;; Got answer:
;; ->>HEADER&lt;&lt;- opcode: QUERY, status: NOERROR, id: 5241
;; flags: qr rd ra; QUERY: 1, ANSWER: 6, AUTHORITY: 2, ADDITIONAL: 1

;; QUESTION SECTION:
;python.org.   	 IN ANY

;; ANSWER SECTION:
python.org.   	 18000 IN AAAA 2001:888:2000:d::a2
python.org.   	 18000 IN A 82.94.164.162
python.org.   	 18000 IN SOA ns.xs4all.nl. hostmaster.xs4all.nl. (
   			 2010112900 ; serial
   			 21600  	; refresh (6 hours)
   			 7200   	; retry (2 hours)
   			 604800 	; expire (1 week)
   			 86400  	; minimum (1 day)
   			 )
python.org.   	 18000 IN MX 50 mail.python.org.
python.org.   	 18000 IN NS ns.xs4all.nl.
python.org.   	 18000 IN NS ns2.xs4all.nl.

;; AUTHORITY SECTION:
python.org.   	 18000 IN NS ns2.xs4all.nl.
python.org.   	 18000 IN NS ns.xs4all.nl.

;; ADDITIONAL SECTION:
ns2.xs4all.nl.   	 15715 IN A 194.109.9.100

;; Query time: 18 msec
;; SERVER: 172.20.20.23#53(172.20.20.23)
;; WHEN: Wed Dec  1 17:52:58 2010
;; MSG SIZE  rcvd: 228
  </example>
  <p>
    Vysvětlivky:
  </p>
  <ul>
    <li>
        Příznak <code>any</code> vrátí odpověď na všechny možné dotazy, které je možno položit.
    </li>
    <li>
        Příznak <code>+multiline</code> slouží (pouze) k úpravě výpisu SOA-záznamu do čitelnější podoby (kde SOA = <em>Start Of Authority</em>, tedy autoritativní údaje o příslušné DNS-zóně).
    </li>
    <li>
        <code>AAAA</code> je IPv6-adresa.
    </li>
    <li>
        <code>A</code> je IPv4-adresa.
    </li>
    <li>
        <code>MX</code> je odkaz na emailový server pro danou doménu.
    </li>
    <li>
        A konečně <code>NS</code> je <em>Name Server</em>, tedy počítač starající se o správu DNS-záznamů příslušné domény (nebo obecněji <em>zóny</em>).
    </li>
  </ul>

</slide>
<slide title="Hierarchie DNS-serverů I">

    <p class="enumerate">
        Správa jmen na internetu je rozdělena podle logické úrovně – jiné stroje mají na starosti doménu nejvyšší úrovně (TLD = <em>Top Level Domain</em>) <code>org</code>, jiné zase doménu druhé úrovně <code>python</code> (pod doménou <code>org</code>) a případné jiné stroje další poddomény.
    </p>
    <note>
        Co běžný uživatel nevidí, je kořenová doména „<code>.</code>“, která se nachází na konci doménového jména (tj. např. <code>docs.python.org.</code>), ale pro většinu praktických účelů se nepoužívá (v řídících záznamech DNS je ovšem životně důležitá, protože jinak by jména byla vyhodnocována jako relativní).
    </note>
    <p>
        Přitom stroje spravující doménu jisté úrovně „ví“, kam (na jaké další DNS-stroje) mají přesměrovat dotazy na nižší podúrovně. Každá část této veliké a značně distribuované databáze se tak „stará“ pouze o svoji příslušnou podčást všech doménových jmen.
    </p>
    
    <p class="enumerate">
        Kdyby každý překlad doménového jména na IP-adresu šel celou touto cestou od kořene až po poslední DNS-server, bylo by to strašlivá zátěž na všechny stroje po cestě a především na stroje starající se o kořenovou zónu. Ve skutečnosti se získané odpovědi ukládají do mezipamětí (vyrovnávacích pamětí, <em>cache</em>) spolu s údajem, do kdy jsou platné. Dotaz na překlad pak „probublá“ výše pouze tehdy, není-li příslušné jméno k dispozici v nějakém bližším DNS-serveru.
    </p>

</slide>
<slide title="Hierarchie DNS-serverů II">

  <p>
    Jak tedy vypadá celý stromeček DNS-serverů zodpovědných za překlad uvedeného jména na IP-adresu?
  </p>
  <example lang="http">
pirat@hotaru:~$ dig www.python.org +trace

; &lt;&lt;>> DiG 9.7.0-P1 &lt;&lt;>> www.python.org +trace
;; global options: +cmd
.   		 2239    IN    NS    i.root-servers.net.
.   		 2239    IN    NS    b.root-servers.net.
.   		 2239    IN    NS    g.root-servers.net.
.   		 2239    IN    NS    e.root-servers.net.
.   		 2239    IN    NS    c.root-servers.net.
.   		 2239    IN    NS    j.root-servers.net.
.   		 2239    IN    NS    k.root-servers.net.
.   		 2239    IN    NS    m.root-servers.net.
.   		 2239    IN    NS    f.root-servers.net.
.   		 2239    IN    NS    d.root-servers.net.
.   		 2239    IN    NS    h.root-servers.net.
.   		 2239    IN    NS    a.root-servers.net.
.   		 2239    IN    NS    l.root-servers.net.
;; Received 228 bytes from 172.20.20.23#53(172.20.20.23) in 0 ms

org.   		 172800    IN    NS    b0.org.afilias-nst.org.
org.   		 172800    IN    NS    b2.org.afilias-nst.org.
org.   		 172800    IN    NS    c0.org.afilias-nst.info.
org.   		 172800    IN    NS    d0.org.afilias-nst.org.
org.   		 172800    IN    NS    a2.org.afilias-nst.info.
org.   		 172800    IN    NS    a0.org.afilias-nst.info.
;; Received 434 bytes from 192.203.230.10#53(e.root-servers.net) in 190 ms

python.org.   	 86400    IN    NS    ns.xs4all.nl.
python.org.   	 86400    IN    NS    ns2.xs4all.nl.
;; Received 76 bytes from 2001:500:e::1#53(a0.org.afilias-nst.info) in 296 ms

www.python.org.   	 86400    IN    A    82.94.164.162
python.org.   	 86400    IN    NS    ns2.xs4all.nl.
python.org.   	 86400    IN    NS    ns.xs4all.nl.
  </example>
  <p>
    Vidíme, že:
  </p>
  <ul>
    <li>
        O kořenovou zónu, tj. „tečku“, se stará 13 rozdílných logických strojů (které jsou rozeseté po celém světě a navíc samozřejmě každý z nich představuje celou armádu počítačů se stejnou adresou, které odpovídají na <em>anycastové</em>-dotazy podle nejvýhodnější aktuální dostupnosti).
    </li>
    <li>
        Tyto nás přepošlou na 6 logických strojů, které mají na starosti doménu nejvyšší úrovně <code>org</code>.
    </li>
    <li>
        Odtud už se dostaneme na <em>name-servery</em>, které obhospodařují doménu druhé úrovně <code>python</code> (jako subdoménu domény <code>org</code>). A vidíme, že se o to nestará organizace <em>Python Software Foundation</em> (která má jinak doménu <u>python.org</u> na starosti, jak bychom zjistili dotazem <code>whois python.org</code>), ale poskytovatel jejího internetového připojení <em>XS4ALL</em>. Není tudíž divu, že..
    </li>
    <li>
        ..adresování uvnitř domény <code>python.org</code> (tedy rozlišení mezi doménami třetí úrovně jako jsou např. <code>www.python.org</code> nebo <code>docs.python.org</code>) má na starosti také on.
    </li>
  </ul>

</slide>
<slide title="Intermezzo">

  <p>
    Nyní už známe většinu částí „vysokoúrovňové“ komunikace na úrovni protokolu HTTP: Pro získání vstupní HTML-stránky na adrese <code>http://www.python.org</code> potřebujeme zaslat HTTP-dotaz (nezapomínejme na povinnou ukončovací prázdnou řádku)..
  </p>
  <example lang="text">
GET / HTTP/1.1
Host: www.python.org
↵
  </example>
  <note>
    To jest: Získej (<code>GET</code>) kořenový dokument (<code>/</code>) pomocí protokolu <code>HTTP 1.1</code>, zaslaná dodatečná hlavička <code>Host: www.python.org</code>.
  </note>
  <p>
    ..na port <code>80</code> (základní port HTTP-protokolu) stroje identifikovaného IP-adresou <code>82.94.164.162</code> (kterou získáme z DNS překladem jména <code>www.python.org</code>).
  </p>

</slide>
<slide title="Cesta dat po síti">

  <p>
    Uvedený text HTTP-dotazu na port 80 je ovšem teprve začátek – daný dotaz se totiž musí dostat z našeho počítače (který má také svoji IP-adresu) na počítač cílový, kde bude vyhodnocen, a příslušná odpověď (zde vstupní HTML-stránka) bude vrácena na náš počítač, kde bude zobrazena. A tohle všechno dohromady není vůbec jednoduché:
  </p>
  <ul>
    <li>
      Už na první pohled je zřejmé, že výsledkem dotazu může být enormní množství dat (např. video z YouTube.com) – zřejmě uvedená data nebudou přenášena všechna najednou jako jeden „balík“.
    </li>
    <li>
      Za druhé data musí „téct“ po nějakém přenosovém médiu (což mohou být klasické nebo optické kabely, ale stejně tak dobře třeba vzduch).
    </li>
    <li>
      A za třetí mezi naším a cílovým počítačem téměř určitě (pokud to zrovna není kupříkladu náš přístupový bod do internetu) není přímá linka, data tudíž „tečou“ přes mnoho dalších síťových zařízení či počítačů. Zde je graficky (za pomoci programu <a href="http://www.secdev.org/projects/scapy/" class="external">Scapy</a>) zobrazena jedna z možných cest:
      <img src="_files/www.python.org.svg" />
    </li>
  </ul>

</slide>
<slide title="Hierarchie protokolů">

    <p>
        Data na internetu si postupně předávají jednotlivé služby, které se starají o jejich přeposílání mezi zainteresovanými koncovými uzly:
    </p>
    <ol>
        <li>
            Za „logické“ adresování (tj. od nás ke zdroji a zpět) je zodpovědný protokol <strong>IP</strong> (<em>Internet Protocol</em>).
        </li>
        <li>
            Za rozložení dat na menší kousky (a pak zase jejich zpětné složení) plus jejich směřování na konkrétní službu je zodpovědný protokol <strong>TCP</strong> (<em>Transmission Control Protocol</em>).
        </li>
        <li>
            Vlastní přeposílání těchto kousků mezi jednotlivými fyzickými zařízeními na cestě pak má na starosti protokol příslušné fyzické, spojovací vrstvy – pro případ „obyčejného“ síťového kabelu je to nejčastěji <strong>Ethernet</strong>.
        </li>
    </ol>

  <handout>
    Zminit HTTP-kompresi?
  </handout>

</slide>
<slide title="TCP/IP aneb „Život datového packetu“">

  <p>
    Podívejme se na (zjednodušený) souhrnný diagram „cesty“ jednoho konkrétního HTTP-dotazu:
  </p>
  <img src="_files/network-stack.png" />
  <note>
    Zdroj: <a href="http://www.newartisans.com/2007/10/life-and-times-of-a-tcp-packet.html" class="external">Life and times of a TCP packet</a>
  </note>
  
  <p>
    Od protokolu nejvyšší úrovně (HTTP) až po vlastní přenos signálu (fyzická vrstva) se odehraje následující:
  </p>
  <ol reversed="reversed">
    <li>
      Na nejvyšší vrstvě (<strong>aplikační vrstva</strong>) prohlížeč pomocí protokolu <code>HTTP</code> vyšle dotaz, resp. přijme odpověď, v podobě konkrétně formátovaného řetězce (výše uvedený kód s GET jako dotaz, HTTP-hlavička a HTML-podoba stránky plus obrázky atp. jako odpověď).
    </li>
    <li>
      Na TCP-úrovni (<strong>transportní vrstva</strong>) jsou přenášená data „rozsekána“ na menší kousky, které jsou „zabaleny“ do „krabice“ (tzv. paket, z anglického <em>packet</em>) s označením pořadového čísla (zjednodušeně řečeno; ale obecně si protokol <code>TCP</code> hlídá, zda a v jakém stavu dorazily všechny odeslané pakety a případný ztracený paket si vyžádá znovu) a mimo jiné portu cílové služby (což je 80 pro protokol <code>HTTP</code>, není-li určeno jinak).
    </li>
    <li>
      Na IP-úrovni (<strong>síťová vrstva</strong>) je TCP-paket z předchozí vrstvy zabalen do IP-paketu, který se stará o logické adresování v rámci internetu (tj. z jaké a na jakou IP-adresu byla vyslána příslušná data), ale též o to, aby se pakety po netu netoulaly nekonečně dlouho (pomocí pole <code>TTL</code> = <em>Time To Live</em>; viz další bod).
    </li>
    <li>
      Na předposlední vrstvě nad vlastními kabely (nebo jiným médiem; jde o tzv. <strong>vrstvu síťového rozhraní</strong>) se odehrává fyzické adresování – přeposílání IP-paketů mezi jednotlivými fyzickými zařízeními na cestě mezi oběma komunikujícími počítači. Každý další počítač v cestě rozbalí ethernetový paket určený jemu (paket si nese hardwarovou adresu, tzv. MAC-adresu, následujícího počítače v řetězci síťových zařízení; k jejich nalezení v rámci místní sítě slouží pro IPv4 protokol <a href="/materialy/net/arp+ndp.xml?slajd=2">ARP</a> a pro IPv6 protokol <code>NDP</code>) a podívá se dovnitř na zabalený IP-paket:
      <ul>
        <li>
          Je-li určený jemu (odpovídá cílová IP-adresa), rozbalí IP-paket a předá uvnitř se schovávající TCP-paket na příslušnou službu (port).
        </li>
        <li>
          Není-li určený jemu (cílová IP-adresa není jeho vlastní), zmenší pole TTL o jedničku a zabalí takto upravený IP-paket do nového ethernetového rámce (v němž je startovní MAC-adresou jeho vlastní a cílovou pro něj následující síťový stroj).
        </li>
      </ul>
      IP-paket je tímto „přebalováním“ předáván dál a dál v řadě síťových strojů a to tak dlouho, dokud buď nedojde svého cíle nebo nevyprší jeho TTL.
    </li>
    <li>
      Tyto poslední pakety – v našem případě ethernetové – jsou pak fyzicky přenášeny po nejrůznějších kabelech a skrz nejrůznější propojovací koncovky a další zařízení. Každé konkrétní „zasíťování“ má vlastní protokoly a způsoby přenosu, které nás už nemusí příliš trápit.
    </li>
  </ol>

</slide>
<slide title="Doplněk 1 – „3-way handshake“">

  <p>
    Výše popsaný princip zachycuje cestu jednoho konkrétního paketu, ale vlastní TCP-komunikace je podstatně složitější. V principu se dá rozložit na tři stupně:
  </p>
  <ol>
    <li>
      navázání spojení; probíhá také třífázově – klient požádá o spojení (tzv. <em>SYN</em>-paket), server vrátí potvrzení požadavku (paket <em>SYN-ACK</em>), klient potvrdí jeho přijetí (<em>ACK</em>-paket)
    </li>
    <li>
      vlastní přenos dat
    </li>
    <li>
      ukončení spojení
    </li>
  </ol>
  <note>
    Tedy pro příklad – než prohlížeč vůbec začne od serveru dostávat nějaká data ke zobrazení, dojde mezi klientským počítačem a cílovým servrem k výměně tří paketů pro navázání spojení, tj. výše popsaná cesta paketů se odehraje třikrát (dvakrát k serveru, jednou ke klientovi). Teprve poté se začnou přenášet samotná data zobrazované stránky.
  </note>

</slide>
<slide title="Doplněk 2 – UDP">

    <p>
        Kromě výše uvedených protokolů můžete také někdy zaslechnout zkratku <strong>UDP</strong> (<em>User Datagram Protocol</em>):
    </p>
    <p>
        V podstatě jde o protokol srovnatelný s <code>TCP</code>, ale narozdíl od něj zaručuje pouze integritu paketů (pomocí kontrolního součtu), nikoli už jejich doručení.
    </p>
    <note>
        Protokol <code>TCP</code> tedy zaručuje, že pakety dorazí v pořádku a všechny, protokol <code>UDP</code> pak pouze to, že pokud vůbec dorazí, tak budou v pořádku.
    </note>

</slide>

<!--
  Zminit i preklady adres, deleni na vnejsi a vnitrni site apod.? Mozna casem na jinem slajdu.
-->



</lecture>
