|
[Grafika]
[WebTip]
[Fotografování]
[Galerie]
[MujMac]
[Printing]
![]() |
|||||||||
![]() |
![]() |
|||||||||
![]() ![]() ![]() |
||||||||||
![]() |
![]() |
|||||||||
|
![]() |
![]() |
||||||||
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
|
![]() |
![]() |
![]() |
Dnes si ukážeme, jak vytvořit jednoduchý TCP server. Pod pojmem server mám na mysli program, který bude schopen přijímat požadavky na spojení od klientů. Překlad slova server je sluha. Server obsluhuje požadavky klientů. V předminulém díle jsem vysvětlil pojem soket. Použil jsem přirovnání soketu ke konci potrubí (hrdlo trubky). Na straně serveru vytvoříme hrdlo trubky (funkce socket). Nyní ale na rozdíl od klienta musíme nejprve přiřadit (funkce bind) soketu jméno (instance struktury sockaddr_in). Poté musíme vytvořit frontu, ve které budou uloženy požadavky na spojení (funkce listen). Překlad slova "listen" je poslouchat. Vytvořením fronty jsme vlastně vydali povel k tomu, aby operační systém na daném portu poslouchal, jestli nepřišel požadavek na spojení. Požadavky na spojení můžeme z fronty požadavků (kterou jsme vytvořili pomocí listen) postupně vybírat (funkce accept). Není-li ve frontě žádný požadavek a my se pomocí accept snažíme nějaký vybrat, program počká, dokud nějaký nedojde. Běh programu se "zablokuje". (Stále hovoříme o tak zvaném blokovacím módu.) Funkce accept nám vrátí nový soket, pomocí kterého budeme komunikovat s klientem. Starý soket bude dále sloužit pouze k navazování spojení. Zní to možná zvláštně, ale je to vlastně logické. Jeden soket slouží k navazování spojení a pro každého klienta, který se připojí, máme k dispozici nový soket. Tak může server obsluhovat více klientů najednou a navíc ještě při jejich obsluze přijímat spojení od klientů nových. Mám-li použít přirovnání k potrubí jako v předminulém díle, tak lze říci, že na straně serveru vytvoříme objímku potrubí. Do této objímky budou zasouvat potrubí klienti, kteří se budou chtít připojit. Nejprve ale musíme rozhodnout, na kterém portu budeme spojení očekávat a do kterých síťových karet je možné potrubí (hadici) zasunout. Poté vytvoříme frontu, do které budeme vkládat požadavky na spojení. Zde trochu selhává parafráze s potrubím. Představme si to tak, že klienti vlastně vkládají potrubí do fronty. Z fronty budeme vybírat potrubí vložené klienty a pro každé potrubí vytvoříme novou objímku (soket). Chceme-li spojení s klientem ukončit, zahodíme konec potrubí, který jsme pro komunikaci s daným klientem získali. Chceme-li přestat nabízet možnost připojit se, uzavřeme "hlavní" soket, který jsme pojmenovali. Na straně klienta používáme tak zvané anonymní sokety (nepojmenované sokety). Na straně serveru používáme sokety pojmenované. Pomocí pojmenovaného soketu čekáme na vytvoření spojení. Pro každé spojení poté vytvoříme anonymní soket. Podívejme se na funkce podrobněji. FunkceSe strukturou sockaddr_in jsme se již setkali. Také jsme se již setkali s funkcí socket, která vytváří soket. Pro nás nové funkce jsou: Pojmenováni soketu
Dále s klientem komunikujeme pomocí stejných funkcí, které používáme při komunikaci klienta se serverem. Těmito funkcemi jsme se již zabývali. Příklad velice jednoduchého serveru:
Program má jako svůj parametr číslo portu, na kterém bude očekávat spojení. Pomocí klientů z minulého dílu se můžete připojovat k tomuto serveru. Server obslouží 3 klienty a ukončí se. Nejste-li připojeni k síti, můžete přesto spustit tento program. Na stejném počítači poté spusťte klienta a jako adresu serveru předejte řetězec "localhost". Máte-li možnost, můžete si také vyzkoušet se k tomu programu připojit pomocí klienta z MS Windows®. Klienta pro MS Windows jsem vytvořil v minulém díle. Spustit server čekající na portu nižším než 1023 může pouze uživatel root. Jedná se o bezpečnostní opatření. Na nižších portech běží standardní služby a nikdo jiný než správce (root) by neměl mít možnost je spouštět. Nejste-li root, nedávejte tedy programu jako parametr nižší číslo než 1023. Jen pro zajímavost si můžeme říci, že toto číslo je o 1 nižší než hodnota makra PROT_SOCK deklarovaném v hlavičkovém souboru /usr/src/linux/include/net/sock.h jádra operačního systému. Jestliže změníme hodnotu makra PROT_SOCK a překompilujeme jádro operačního systému, budeme mít jinou hodnotu maximálního portu, na kterém můžou poslouchat pouze programy spuštěné rootem. PODOBNÉ EXPERIMENTY VÁM ALE V ŽÁDNÉM PŘÍPADĚ NEDOPORUČUJI. OmluvaVyzkoušíte-li tento server a připojíte se k němu pomocí Linuxového klienta, bude se možná trochu divit. Linuxový klient se totiž nezastaví. Je v něm chyba. K odeslání a přijetí dat dojde, ale v momentě, kdy server uzavře spojeni, klient zamrzne v nekonečné smyčce. Při psaní ukázkového příkladu jsem zapomněl na fakt, že při ukončení spojení druhou stranou vrací recv 0 a neblokuje program. V ukázkovém programu je potřeba upravit cyklus while při přijímání dat. Na chybu jsem přišel až při psaní tohoto článku, když jsem napsal server. Při psaní článku o klientovi jsem neměl ještě server a na ničem jsem ukázkový příklad netestoval. Příště již nebudu ukázkové příklady takto podceňovat a za svou chybu se všem omlouvám. Nerad měním již vydané články, proto tam tuto drobnou chybu ponechám. V příkladech ke stažení je opravená verze klienta. Všimněte si na tomto programu jedné zvláštnosti, nebo spíše nedokonalosti. Program přijme jedno spojení a poté ho obsluhuje. V momentě, kdy obsluhuje klienta, nepřijímá žádné další požadavky na spojení. Navíc je schopen komunikovat v jednom okamžiku pouze s jedním klientem. Jedná se o jednovláknový server. Tohle si můžeme dovolit pouze v našem banální příkladě, ve kterém dojde k přijetí spojení a odeslání krátkých textů. Nedostatek lze tolerovat zvláště v případě, kdy server nebude příliš zatížen. Jinak by ale každý server měl být schopen obsluhovat více klientů najednou. Jak toto řešit si povíme v budoucnu. V příštím díle vytvoříme TCP klienta pro MS Windows®. |
![]() |
![]() |
![]() |