Internetové programování s WinSock (1)
Pod pojmem internetová aplikace se rozumí více odlišných věcí. Typicky se jedná o serverovou aplikaci, nejčastěji psanou ve skriptovacím jazyku typu PHP nebo ASP, která jako své uživatelské rozhraní generuje WWW stránky. Jindy se internetovou aplikací rozumí applety umístěné na webových stránkách a prováděné klientským počítačem. Nicméně tou skupinou, která si označení internetové aplikace zaslouží asi nejvíce, jsou klientské a serverové programy komunikující přes Internet pomocí protokolů typu TCP/IP. Právě programováním takových aplikací v prostředí operačního systému Windows se budeme v tomto seriálu zabývat.
Mezi známé reprezentanty této kategorie patří například webové prohlížeče, e-mailové programy, klienti FTP, programy pro stahování souborů, offline browsery, chatovací programy, klienti diskuzních skupin, přehrávače internetových rádií a jiných multimediálních přenosů, programy pro sdílení souborů, nástroje pro vzdálenou správu počítačů a sítí a mnoho dalších. Většina aplikací má i svou serverovou stranu, takže potřebujeme servery HTTP, FTP, mailservery, servery pro internetové vysílání atd.
Aplikace nad TCP/IP tedy implementují nejrůznější druhy služeb Internetu, zatímco prve zmíněné webové aplikace pracují na vyšší úrovni, pouze v rámci služby WWW.
Naším cílem bude seznámit se s principy práce internetového klienta i serveru a způsoby jejich implementace pomocí knihovny WinSock.
Co je to WinSock?
Windows Sockets, zkráceně WinSock, je jednou ze součástí programátorského rozhraní Win32 API, která nabízí základní prostředky pro síťovou komunikaci. Je nutno hned dodat, že tato knihovna není zrovna jednoduchá a může začínajícímu programátorovi občas připravit nemilá překvapení (tedy přesněji může začínajícího programátora učinit končícím programátorem). Proto se musíme na programování nad WinSock pořádně připravit.
WinSock vychází z Berkeley Sockets, což je internetové rozhraní původem z unixového operačního systému BSD. Rozhraní Sockets se rozšířilo i na ostatní unixové i neunixové platformy a WinSock je jeho realizací pro systémy Windows. WinSock není úplně kompatibilní se Sockets na jiných platformách, má svá rozšíření a své odlišnosti (a své chyby v implementaci). Nicméně programy běžící na odlišných systémech s odlišnými knihovnami spolu mohou bez problémů komunikovat a spolupracovat.
Centrální myšlenkou knihoven Sockets je abstrakce tzv. socketu (v překladu zásuvka nebo objímka, ale raději budu používat termín socket). Socket je jakýsi přípojný bod, přes který může aplikace posílat data na Internet nebo je naopak přijímat. Spojení mezi dvěma aplikacemi běžícími na různých počítačích v síti si tedy můžeme názorně představit jako fiktivní propojovací kabel, který vede z jedné zásuvky do druhé a proudí jím data.
Shrňme si nejdříve, jakým způsobem probíhá komunikace počítačů na Internetu a co to znamená pro programátora.
Jak funguje Internet
Úkolem každé aplikace, ať už je to WWW prohlížeč nebo třeba klient pro zjištění přesného času, je poslat určitá data jiné aplikaci na libovolném počítači v síti a eventuálně přijmout jiná data jako odpověď. Někdy se komunikace odbude jediným dotazem a jedinou odpovědí, jindy jde o delší konverzaci. Třeba FTP klient se na delší dobu připojí k serveru a posílá mu příkazy.
Podle tzv. modelu OSI (Open Systems Interconnect) je odpovědnost za provoz Internetu rozdělena do sedmi vrstev, do nichž spadají jednotlivé hardwarové a softwarové komponenty. Každá vrstva ke své práci využívá služeb vrstev nižších, a to při odesílání dat i při jejich příjmu. Zdánlivě spolu vždy komunikují prvky odpovídající vrstvy na obou stranách, skutečná komunikace ale probíhá na vrstvě nejnižší - fyzické.
Nejvyšší vrstvou je vrstva aplikační. Tu reprezentují známé služby Internetu, jakými jsou WWW, FTP a e-mail, tedy všechny aplikace, ze kterých má užitek normální člověk. Komunikace na této úrovni probíhá ve formě tzv. zpráv. Zprávy mohou být textové (třeba příkazy FTP) nebo binární (např. zprávy v síti Gnutella). Protokoly aplikační vrstvy definují, jaké zprávy musí klient a server podporovat a jak na ně reagovat. Uživatel je od zpráv aplikační vrstvy obvykle odstíněn grafickým uživatelským rozhraním.
Prezentační vrstva se stará o zajištění jednotné reprezentace dat. Aplikační vrstva sice definuje syntaxi a význam jednotlivých zpráv, ale to ještě k domluvě mezi různými počítači nemusí stačit. Je nutné definovat např. způsob kódování textu (ASCII, EBCDIC, UTF-8 apod.), reprezentaci konce řádku (znaky CR-LF nebo jen LF, příp. jen CR), pořadí bytů ve vícebytovém čísle, formát kódování různých základních typů dat. Dokonce ani počet bitů v bytu nemusí být samozřejmostí. Na počítači s odlišnými konvencemi je nutné zajistit správnou konverzi dat. Na úrovni prezentační vrstvy je možno také provádět transparetní kompresi nebo šifrování přenášených dat.
Relační vrstva zajišťuje navázání a správu dialogu mezi aplikacemi. Klient a server si o sobě vymění důležité informace, a potom teprve mohou začít komunikovat pomocí regulérních zpráv aplikační vrstvy. Do relační vrstvy spadá např. autorizace klienta FTP nebo e-mailového klienta při připojení k serveru. Dalším příkladem je navázání komunikace klienta se serverem pomocí technologie šifrovaného spojení Secure Sockets Layer (SSL).
Transportní vrstva, pro programátora aplikací ta nejdůležitější, provádí samotný přenos dat po síti. Nejdůležitějšími protokoly transportní vrstvy jsou TCP a UDP. Protokoly této úrovně podporují adresování pomocí portů. Zatímco adresa IP (viz níže) slouží k identifikaci jednotlivých počítačů a jiných zařízení v síti, porty umožňují rozlišení různých služeb na jednom počítači. Oběma protokoly se budeme zabývat podrobněji za chvíli.
Síťová vrstva je tvořena především protokolem IP. Ten se stará o adresování počítačů pomocí logických adres - adres IP. Logická adresa je nezávislá na konkrétní síťové infrastruktuře, může být přiřazena zařízení připojenému přes síť Ethernet stejně jako přes modem. Protokol IP dále zajišťuje směrování datových paketů (tzv. datagramů IP) po síti směrem k cílové adrese. Protokolu IP se budeme také ještě věnovat. Síťovou vrstvu doplňují ještě další pomocné protokoly jako ICMP a IGMP, starající se o provoz směrovačů, testování apod.
Síťový hardware a jeho ovladače spadají do nejnižších dvou vrstev modelu - vrstvy spojové a fyzické. Na této úrovni jsou data přenášena ve formě paketů většinou pevné velikosti, tzv. rámců (frames). K adresování se používají fyzické adresy (MAC - Media Access Control), které jsou pevně přiřazeny síťovému hardwaru.
Podívejme se teď na vrstvy modelu OSI z našeho programátorského pohledu:
· Vrstva aplikační, prezentační a relační jsou tím, co máme v úmyslu sami implementovat.
· Funkce vrstvy transportní a síťové jsou implementovány v operačním systému a budeme je využívat prostřednictvím knihovny WinSock.
· Vrstva spojová a fyzická jsou našemu pohledu prakticky úplně skryty.
Protokoly síťové a transportní vrstvy v prostředí Internetu se obvykle označují jako protokoly TCP/IP. Řekneme-li TCP/IP, nemáme na mysli pouze protokol TCP a protokol IP, ale všechny související protokoly včetně UDP, ICMP atd.
Protokol IP
IP (Internet Protocol) by bylo možné nazvat základním stavebním kamenem Internetu. Tento protokol umožňuje propojení zařízení a sítí různých standardů do sítě jediné a umožňuje přenos dat mezi nimi.
Jednotlivé počítače mají přiřazeny logické adresy IP, které je jednoznačně identifikují. Adresa může být přiřazena trvale nebo dynamicky (při každém připojení může být jiná, což je případ modemů). Adresa IP je 32bitová, z toho některé hodnoty mají zvláštní význam. Pro čitelný zápis adresy se používá dekadická tečková notace, čtyři čísla od 0 do 255 oddělená tečkami, např. 192.91.16.1. Při skutečném použití v protokolu IP je adresa interně reprezentována 32bitovým číslem.
Přenášená data jsou balena do datagramů IP. Datagram se skládá z hlavičky IP následované užitečnými daty. Hlavička má minimálně 20 bytů a obsahuje kromě zdrojové a cílové IP adresy mnoho systémových informací nutných pro doručení. Při použití protokolu TCP nebo UDP následuje jeho hlavička za hlavičkou IP.
Datagramy cestují přes směrovače, které čtou cílovou adresu a podle svých směrovacích tabulek je přeposílají dále směrem k cíli. Datagram může být podle potřeby po cestě rozdělen - fragmentován. Každý fragment dostane svou vlastní hlavičku IP, nesoucí i informace nutné k pozdějšímu poskládání původního datagramu. Jednotlivé datagramy nebo i fragmenty jednoho datagramu mohou cestovat sítí po odlišných trasách.
Protokol IP nezaručuje doručení datagramů ve stejném pořadí, jako byly odeslány. Dále některé datagramy mohou být po cestě ztraceny a jiné mohou dorazit vícekrát. Jestliže se ztratí jediná část fragmentovaného datagramu, je celý datagram zahozen. Navíc správnost dat kromě hlavičky není kontrolována, obsah datagramů může být poškozen. Pro tyto vlastnosti je přenos dat pomocí IP označován jako nespolehlivý. O zajištění spolehlivosti se musí postarat protokoly vyšších vrstev např. kontrolou a opakovaným vysíláním ztracených a poškozených datagramů.
Pro úplnost se zmíním o verzích protokolu IP. Dnes se používá verze 4 (IPv4), nová verze má číslo 6 (IPv6). V nové verzi bude adresa IP 128bitová, což zajistí prakticky nevyčerpatelný počet dostupných unikátních adres. Hlavička IPv6 bude mít délku 40 bytů místo současných 20. Přechod na verzi 6 je zatím velmi pomalý, napřed bude nutná podpora většiny softwaru.
Protokol TCP
Protokol TCP (Transmission Control Protocol) zajišťuje spolehlivý přenos dat mezi aplikacemi. K přenosu se sice využívá protokol IP, narozdíl od něho je ale zajištěno, že všechna zaslaná data budou doručena. Přijímající strana musí potvrzovat příchozí pakety. Jestliže se některý paket po cestě ztratí nebo poškodí a potvrzení o jeho příjmu nepřijde, je vyslán opakovaně. Protokol se dále stará o odstranění případných duplikovaných paketů a o sestavení všech přijímaných dat v pořadí, ve kterém byla odeslána.
TCP je tzv. spojovaný protokol. Před začátkem komunikace je nutno ustavit TCP spojení a po skončení jej zase korektním způsobem zrušit. Navázáním spojení se vytvoří komunikační kanál, který je plně duplexní, tj. umožňuje zasílání a příjem dat oběma stranami nezávisle na sobě.
Typickou vlastností protokolu TCP je přenos dat ve formě proudu. Data jsou sice vysílána v podobě datagramů IP, nicméně hranice těchto datagramů jsou komunikujícím aplikacím skryty. Jestliže tedy jedna strana vyšle stokrát čtyřbytové číslo nebo jednou 400bytový blok, nemůže počítat s tím, že protějšek obdrží data ve stejných kouscích. Data mohou být podle potřeby libovolně spojována do větších bloků nebo naopak dělena, a to jak implementací TCP na odesílajícím počítači, tak i na straně příjemce. Aplikace tedy musí chápat přenášená data jako souvislý proud. K rozpoznávání začátků a konců zpráv v datovém proudu se používají buď zvláštní oddělovací znaky (třeba konce řádků), nebo každá zpráva obsahuje informace o své délce v bytech, případně je délka zprávy jinak odvoditelná z jejího obsahu.
Blok dat, který je zabalen do jednoho datagramu IP a odeslán na síť, se nazývá segmentem TCP. Segment TCP má svou vlastní hlavičku o minimální velikosti 20 bytů, spolu s hlavičkou IP činí tedy režie protokolů 40 bytů na jeden datagram. Hlavička TCP obsahuje především čísla portů odesílající i cílové aplikace. Dále je tu uvedena pozice prvního bytu užitečných dat segmentu v rámci přenášeného proudu. Tak je možné zajistit rekonstrukci proudu na straně příjemce ve správném pořadí. K dalším polím hlavičky TCP se vrátíme, až se budeme více věnovat praktickému použití protokolu.
Knihovna WinSock nabízí pro přenos dat pomocí TCP tzv. proudové sockety (stream sockets).
Protokol UDP
Protokol UDP (User Datagram Protocol) je alternativou protokolu TCP pro přenos dat s téměř diametrálně odlišnými vlastnostmi.
Stejně jako v přpadě protokolu IP je přenos dat nespolehlivý. Jediným vylepšením proti IP je kontrola správnosti obsahu celého datagramu. Jestliže jsou data poškozena, je datagram zahozen a není předán cílové aplikaci. Aplikace musí počítat se ztracenými a duplikovanými datagramy a s nepředvídatelným pořadím jejich příjmu.
Na druhé straně UDP narozdíl od TCP zaručuje zachování hranic datagramů a jejich předání aplikaci ve stejné podobě, jako byly odeslány. Nedochází tedy ke skládání datagramů do proudu.
UDP je tzv. nespojovaný protokol. Datagram UDP je možné okamžitě poslat na libovolnou adresu, aniž by bylo nutné navazovat s touto adresou spojení. Navíc UDP podporuje tzv. broadcasting, což je hromadné odeslání datagramu na všechny adresy v dané síti. Většinou je toto možné jen v rámci uzavřené lokální sítě, směrovače na Internetu pokus o broadcasting do cizí sítě nedovolí.
Každý datagram UDP je balen do jednoho datagramu IP. Datagram UDP má 8bytovou hlavičku UDP, obsahující jen zdrojový a cílový port, velikost datagramu a kontrolní součet. Po zabalení do paketu IP tedy tvoří data obou hlaviček jen 28 bytů na každý datagram.
V knihovně WinSock jsou k dispozici tzv. datagramové sockety implementující protokol UDP.
TCP nebo UDP?
To je otázka, na kterou si musíme odpovědět, než se dáme do vývoje. Oba protokoly mají své výhody pro konkrétní druhy aplikací.
Výhody TCP jsou následující:
· Přenos dat je spolehlivý, o všechny kontroly a opravy se stará samotný protokol, aplikace se může věnovat svým problémům.
· Protokol sám optimalizuje využití komunikačního kanálu a dosahuje lepšího využití kapacity přenosové linky.
Protokol UDP má tyto přednosti:
· Protokol je jednodušší, jeho datagramy obsahují méně pomocných dat.
· Není nutno navazovat spojení, současná komunikace s velkým počtem počítačů je proto efektivnější. Je podporován broadcasting.
· Implementace klienta i serveru je jednodušší.
· Protokol doručuje samostatné datagramy, aplikace se proto nemusí starat o rozeznávání jednotlivých zpráv v proudu.
V případě, že programujeme klienta nebo server některého zavedeného protokolu, musíme se držet transportního protokolu, který je předepsán. Většina protokolů přenášejících souvislé bloky dat je založena na TCP. Patří mezi ně HTTP, FTP, SMTP (přenos e-mailu), POP3 (stahování e-mailu), IRC (chat). UDP používají nejčastěji jednodušší služby, pracující způsobem dotaz-odpověď, např. zjištění přesného času nebo překlad doménového jména na adresu IP (DNS). Protokoly využívající UDP někdy volitelně podporují i TCP jako alternativní transportní protokol.
Jestliže budeme vyvíjet vlastní službu, rozhodneme se pro protokol TCP, jestliže aplikace bude přenášet větší objemy dat mezi dvěma počítači. UDP zvolíme v případě, že objem přenesených dat mezi každými dvěma počítači je malý, přitom spolu může komunikovat i větší počet účastníků najednou. Kandidátem na využití UDP jsou různé informační a vyhledávací služby.
Přenos dat ve formě datagramů může lákat programátora k použití UDP v každé aplikaci komunikující pomocí různých krátkých zpráv a odpovědí. To ale není správná cesta v případě, že přenesených zpráv je velké množství a každá zpráva putuje ve vlastním datagramu. Protokol TCP by v takovém případě spojoval více zpráv do jednoho segmentu a přenos by byl mnohem efektivnější.
Závěr
To byla tedy úvodní průprava do problematiky aplikací nad TCP/IP. Některé další technologické podrobnosti si přiblížíme, až se budeme věnovat konkrétním problémům a jejich implementaci. V příštím dílu tohoto cyklu se začneme učit používat knihovnu WinSock a někt eré její základní funkce v praxi.