VYSOKÁ ŠKOLA POLYTECHNICKÁ JIHLAVA Katedra elektrotechniky a informatiky
S í ť o v á a s y n c h ro n n í a p l i k a c e P i š k v o r k y bakalářská práce
Autor: Josef Kvasnica Vedoucí práce: PaedDr. František Smrčka, Ph.D. Jihlava 2012
Vysoká škola polytechnická Jihlava Tolstého 16, 586 01 Jihlava
ZADÁNÍ BAKALÁŘSKÉ PRÁCE
Autor práce:
Josef Kvasnica
Studijní program:
Elektrotechnika a informatika
Obor:
Aplikovaná informatika
Název práce:
Síťová asynchronní aplikace Piškvorky
Cíl práce:
Práce se bude v teoretické části zabývat popisem známé hry Piškvorky, přehledem použitých technologií (C#/.NET), rozborem asynchronní komunikace, a převážně popisu síťové komunikace (socketový mechanismus). V praktické části je navržena samotná aplikace, která demonstruje síťovou komunikaci. Samotná aplikace bude pracovat na bázi klientserver a bude implementačně rozdělena do dvou logických částí třída server a třída klient. Server, který bude sdílet veřejnou IP adresu, bude naslouchat na určitém portu. Klient se poté připojí pomocí IP adresy serveru a portu, na kterém server naslouchá. Desktopová síťová aplikace/hra bude přehledně graficky zpracovaná.
Jméno vedoucího BP
Jméno vedoucího katedry
vedoucí bakalářské práce
vedoucí katedry Katedra elektrotechniky a informatiky
Anotace Tato bakalářská práce je zaměřena na síťovou asynchronní desktopovou hru piškvorky. Program je vytvořen ve vývojovém prostředí Microsoft Visual C# 2010 Express edition. První část práce se věnuje základnímu objasnění problematiky socketové komunikace, která je uspořádána do dalších podkategorií. Druhá část práce se zabývá podrobným vývojem aplikace. Tato část je obecně rozdělena do tří etap, které popisují analýzu, návrh a implementaci.
Klíčová slova Piškvorky, .NET, C#, soket, desktopová aplikace, asynchronní komunikace
Abstract This thesis is focused on asynchronous desktop network game Gomoku (Five in row). The program is created in development environment Microsoft Visual C# 2010 Express edition. The first part is devoted to clarifying the basic issues of socket communication, which is organized into subcategories. The second part deals with a detailed development of application. This section is generally divided into three stages that describe the analysis, design and implementation
Key words Five in row, .NET, C#, socket, desktop application, asynchronous communication
Prohlašuji, že předložená bakalářská práce je původní a zpracoval jsem ji samostatně. Prohlašuji, že citace použitých pramenů je úplná, že jsem v práci neporušil autorská práva (ve smyslu zákona č. 121/2000 Sb., o právu autorském, o právech souvisejících s právem autorským a o změně některých zákonů, v platném znění, dále též „AZ“). Souhlasím s umístěním bakalářské práce v knihovně VŠPJ a s jejím užitím k výuce nebo k vlastní vnitřní potřebě VŠPJ. Byl jsem seznámen s tím, že na mou bakalářskou práci se plně vztahuje AZ, zejména § 60 (školní dílo). Beru na vědomí, že VŠPJ má právo na uzavření licenční smlouvy o užití mé bakalářské práce a prohlašuji, že s o u h l a s í m s případným užitím mé bakalářské práce (prodej, zapůjčení apod.). Jsem si vědom toho, že užít své bakalářské práce či poskytnout licenci k jejímu využití mohu jen se souhlasem VŠPJ, která má právo ode mne požadovat přiměřený příspěvek na úhradu nákladů, vynaložených vysokou školou na vytvoření díla (až do jejich skutečné výše), z výdělku dosaženého v souvislosti s užitím díla či poskytnutí licence. V Jihlavě dne 30. května 2012
............................................... Podpis
Poděkování Na tomto místě bych rád poděkoval svému vedoucímu práce PaedDr. Františku Smrčkovi, Ph.D. za poskytnutí tématu a možnost vytvářet ho pod jeho vedením. V neposlední řadě bych chtěl poděkovat své rodině, přítelkyni a přátelům za podporu během studia.
Obsah 1
Úvod ......................................................................................................................... 8
2
Hra Piškvorky ....................................................................................................... 10
3
4
2.1
Historie ............................................................................................................. 10
2.2
Pravidla a informace o hře ............................................................................... 10
2.3
Modifikace piškvorek....................................................................................... 11
Socketový mechanismus v C# .............................................................................. 12 3.1
Nejdůležitější třída pro práci se sockety .......................................................... 13
3.2
Nespojově orientované sockety........................................................................ 14
3.3
Spojově orientované sockety............................................................................ 14
3.4
Synchronní sockety a operace .......................................................................... 15
3.5
Asynchronní sockety a operace ........................................................................ 15
Vývoj aplikace ....................................................................................................... 18 4.1
Analýza a specifikace požadavků .................................................................... 19
4.1.1
Diagram případů užití ............................................................................... 20
4.1.2
Doménová analýza .................................................................................... 21
4.2
Návrh aplikace ................................................................................................. 22
4.2.1
Vývojové prostředí a popis základních komponent .................................. 22
4.2.2
Použité technologie ................................................................................... 24
4.2.3
Microsoft .NET Framework ..................................................................... 24
4.2.4
Architektura klient-server ......................................................................... 26
4.2.5
Co provádí klient v aplikaci? .................................................................... 26
4.2.6
Co provádí server v aplikaci? ................................................................... 27
4.2.7
Návrhový diagram tříd .............................................................................. 29
4.2.8
Synchronní diagram komunikace ............................................................. 30
4.3
Implementace ................................................................................................... 30
4.4
Integrace a testování ......................................................................................... 32
4.4.1
Funkčnost .................................................................................................. 33
4.4.2
Použitelnost ............................................................................................... 33
4.4.3
Spolehlivost .............................................................................................. 33
4.4.4
Výkon........................................................................................................ 34
5
Srovnání s existujícími aplikacemi ...................................................................... 34
6
Uživatelská příručka............................................................................................. 35 6.1
Serverová část .................................................................................................. 35
6.2
Klientská část ................................................................................................... 37
6.3
Komunikace ..................................................................................................... 39
7
Závěr ...................................................................................................................... 41 7.1
Zhodnocení ....................................................................................................... 41
7.2
Možnosti dalšího rozšíření aplikace ................................................................. 41
Seznam použité literatury ............................................................................................ 43 Seznam obrázků ............................................................................................................ 46 Seznam použitých zkratek ........................................................................................... 47 Seznam příloh ................................................................................................................ 48 A
Obsah přiloženého CD.......................................................................................... 48
B
Zdrojové kódy ....................................................................................................... 49
1 Úvod Tvorba webových aplikací a webových stránek se s postupem času stala abnormálně oblíbenou disciplínou, do které pronikají zejména programátoři, kteří se snaží rychle zdokonalovat v oboru. Skoro každý počítačový nadšenec se během života setká s programovacím jazykem PHP a s tvorbou webových stránek, poněvadž počítá s tím, že je tato disciplína jednoduchá, a že jí proto může využívat mnoho lidí po celém světě. Ovšem, opak je pravdou. Každá firma na trhu, která se zabývá vývojem aplikací, se snaží být výjimečná a perspektivní. Především chtějí vytvářet a nabízet něco, co se na trhu doposud neobjevilo. I když firmy sahají stále po vzdělanějších lidech v oboru, od programátorů až po IT specialisty, mají značné problémy s myšlenkou, co nového vymyslet. I když se objeví přelomová myšlenka či nápad, tak nemáme až tak vyhráno. Rozsáhlá konkurence po celém světě nám může ihned přelomový nápad přebrat. Webové stránky obsahují plno interaktivních modulů, které jsou již několik let naimplementovány. Mezi interaktivní moduly patří návštěvní knihy, ankety, počítadla, atd. Pak tu jsou dokonalé systémy, které existují též několik let. Do této skupiny patří redakční a šablonovací systémy, e-shopy, fóra, atd. Jsem zastáncem toho, že by se měly softwarové produkty vyvíjet více, než webové. Vývoj softwaru by měla být určitě oblíbenější disciplína. A to je jeden z mých důvodů, proč jsem si tvorbu webu jako téma své bakalářské práce nevybral. Tvorbou webu se zabývám již delší čas a chtěl bych si rozšířit obzory v tomto směru. Téma mé bakalářské práce je desktopová síťová aplikace piškvorky. Nejhorší chvíle na počátku mé práce nastaly při výběru programovacího jazyka. Programování jako takové není nic jiného, než logický pytel se seznamem příkazů. Definice nám říká, že je naprosto jedno, který programovací jazyk se naučíme, ale je potřeba se seznámit se syntaxí a sémantikou příkazů. Pokud se naučíme používat jeden komplexní jazyk, můžeme si být jistí, že nám ostatní programovací jazyky nebudou činit problémy.
8
Obecně jsem se s vývojem softwaru setkal na střední škole a to s programovacím jazykem Pascal ve vývojovém prostředí Turbo Pascal 5.5. Na Pascal rád vzpomínám, naučil mě základy a já mohl pokračovat a přejít na další možnosti. Pascal mohu doporučit všem začátečníkům, kteří se chtějí ponořit do světa programování. O Pascalu se často hovoří také jako o výukovém programovacím jazyce. Pascal samozřejmě stárnul a já se snažil přejít na modernější vývoj softwaru. Z doslechu a rad od kolegů v IT jsem přešel na C/C++ a tyto programovací jazyky a návyky mi zůstaly dodnes. Výrazné problémy pro některé programátory dělá přechod ze strukturovaného programování na programování objektové. Celý stávající problém se v objektovém světě řeší dělením na více podproblémů a my se musíme naučit vnímat svět v objektech. Výhodou objektového modelu oproti klasickému je ta skutečnost, že objekty sdružují a udržují funkcionalitu s datovou složkou. Programovací jazyk C++ je jenom rozšíření programovacího jazyka C a není plně objektový. Na programování aplikace jsem si vybral programovací jazyk C#, protože v něm mám dlouholeté zkušenosti a je příbuzný právě s C++. Zvolil jsem GUI pro grafické rozhraní, respektive WinForms rozhraní, které není pro vývoj z hlediska designu populární. Již delší čas jsem přemýšlel o situaci, jestli mám napsat hru, nebo síťovou aplikaci. Až jednoho dne mě přepadla myšlenka o zkombinování. Z tohoto důvodu byly volbou síťové piškvorky, které řeší kombinaci jednoduché grafické deskové hry a síťové aplikace.
9
2 Hra Piškvorky 2.1 Historie Historie hry Piškvorky (Gomoku) sahá přibližně někam do období 2000 let před Kristem. Ano, je tomu opravdu tak, piškvorky jsou více jak 4000 let staré. První zmínky pocházejí od řeky Hwang Ho, která je v Číně. Nejenom v Číně, ale také v antickém Řecku a v (předkolumbovské) Americe byly objeveny určité údaje a specifikace o této hře. [1] První podobná hra se datuje do 7. století, kde se tato hra objevuje v Japonsku, pochází z Číny a je nazvaná jednoduchým japonským slovem Go (Go znamená v japonštině číslo pět a Moku je průsečík). Na základě této hry možná vznikly i naše známé piškvorky. O tomto faktu svědčí i hra s bílými a černými kameny o velikosti desky 19x19. Plno odborníků se i domnívá, že piškvorky vychází právě z japonského slova Go.
2.2 Pravidla a informace o hře Piškvorky se hrají na základním plátně o rozměrech 15x15. Na začátku hry se spravedlivě určí, kdo bude začínat. Ten, kdo začíná, má z matematického hlediska samozřejmě výhodu. Každý z hráčů dostane na začátku specifický symbol a to buď kolečko, nebo křížek. Kolečko se obarvuje červenou barvou a křížek modrou barvou. Cílem hry je dostat 5 stejných symbolů vedle sebe v libovolném směru – vertikálně, horizontálně či diagonálně. Hráč, který tuto herní kombinaci splní jako první – vyhrává. Pokud ani jeden z hráčů tuto kombinaci nesplní a všechna volná místa jsou na hracím poli obsazena, nastává remíza a hra končí. Výzkum doktora L. Victora Allise prokázal, že při perfektní hře na ploše 15x15 vždy vyhraje začínající hráč a při jinak velké omezené ploše, či v neomezené variantě hry, začínající hráč nikdy neprohraje. Jinak řečeno je dokázáno, že druhý hráč nemůže při perfektní hře začínajícího vyhrát. [3]
10
2.3 Modifikace piškvorek Základní verze piškvorek byla natolik oblíbenou hrou, že se během několika let vytvořily zajímavé modifikace. Renžu U klasických piškvorek má výhodu začínající hráč. To neplatí u této modifikace, která vyrovnává výhodu začínajícího hráče. Najdeme tu striktní pravidla pro začínajícího hráče. Ten nesmí během hry porušit několik pravidel. Nesmí vytvořit dvojitou trojku, dvojitou čtyřku a přesah (6 nebo více kamenů v jedné řadě). Šestvorky U této modifikace, jak už plyne z názvu této hry, se hraje na šest vítězných symbolů vedle sebe. Každý hráč, který je na tahu, umisťuje dva symboly. Též se i u této modifikace eliminuje výhoda začínajícího, který musí na začátku hry dát pouze jeden symbol. 3D Piškvorky Tato modifikace hry piškvorek je výjimečná a značně moderní. Sahá do 21. století. Hráč se snaží udělat linii svých stejných symbolů na plátně 4x4x4, nebo 8x8x8. Pentago Zajímavá hra na desce 6x6, která se dále rozděluje na čtvrtiny (pod-desky) 3x3. Hráč vždy po svém tahu otáčí pod-desky po směru, nebo proti směru hodinových ručiček. Vyhrává ten hráč, který jako u klasických piškvorek, umístí pět svých symbolů v řadě. Kvantové Piškvorky Tento druh piškvorek je pro mnohé hráče nejzábavnější. Z hlediska času je tato modifikace nejrychlejší logickou hrou. Nabízí hned dva druhy plátna. Hraje se na plátně 3x3, nebo 9x9. Vyhrává ten hráč, který dříve udělá 3 své symboly. Ve spojení s fyzikou byla tato hra vymyšlena kvůli znázornění některých specifických jevů v kvantové fyzice.
11
3 Socketový mechanismus v C# Jedná se o starší komunikační mechanismus, stále používán v různorodé praxi a při síťovém programování. Socketový mechanismus, respektive první socketové rozhraní (Berkeley Socket API) vzniklo na univerzitě v Berkeley v roce 1983 pro unixové systémy BSD. [7] Později se však ukázalo, že toto rozhraní není zcela optimální a má mnoho nevýhod. Toto rozhraní nepodporovalo objektový model a operace byly naimplementovány blokově. Z tohoto prostého důvodu vznikaly další implementace, které tyto nevýhody eliminovaly. Rozhraní WinSock API je implementačně založené na Berkeley Socket API a pro práci se systémem Windows. Na socket můžeme nahlížet jako na abstraktní meziprocesní komunikační prostředek, který je definovaný jako koncový kanál. Socket tedy obecně definuje kombinaci IP adresy (identifikace počítače) a portu (identifikace procesu). Od jiných komunikačních prostředků se liší především tím, že komunikující procesy nemusí být na stejném počítači. [6] Socket si lze také představit i jako určitou datovou strukturu nebo objekt, který nese informace o stavu síťové komunikace s druhou stranou. Při vytvoření socketu v programu se jako parametry do instance předávají AddressFamily, SocketType a ProtocolType. Vždy se musí uvážit správná kombinace adresy, typu socketové komunikace a protokolu. Socketový mechanismus se nejvíce používá a upřednostňuje pro typ komunikace pracující na bázi klient-server.
Obrázek 1: Základní princip socketů na bázi klient-server. 12
3.1 Nejdůležitější třída pro práci se sockety Pro síťovou komunikaci se obecně využije jmenný prostor System.Net. Pro práci se sockety lze najít nejdůležitější třídy ve jmenném prostoru System.Net.Socket. Zmíněný jmenný prostor nabízí práci s třídami asynchronně i synchronně. Odlehčené třídy, které najdeme v tomto jmenném prostoru:
TcpClient, TcpListener,
UdpClient,
IrdaClient, IrdaListener.
Nevýhoda těchto tříd spočívá v synchronním režimu (blokujícím režimu), výhodou použití těchto tříd je ulehčení práce při programování. Nejzákladnější a nejdůležitější třídou pro práci se socketem je třída Socket. Vytvoření instance socketu: Socket OurSocket = new Socket( AddressFamily addressFamily, SocketType socketType, ProtocolType protokolType);
AddressFamily – určuje základní adresovací schéma, se kterým budou sockety pracovat. InterNetwork, InterNetworkV6, IrDa SocketType – určuje typ a způsob socketu, jakým se budou data v socketové komunikaci přenášet.
Stream – odeslán je klasický proud dat při obousměrně navazovaném spojení využívajícím TCP protokol (spojová služba).
Dgram – odeslán je klasický datagram (balík dat), posílají se krátké zprávy využívající UDP protokol, není navázáno spojení (nespojová služba).
Raw – zřídka nazývaný jako syrový socket využívající protokoly ICMP a IGMP.
ProtocolType – protokol, se kterým budeme v rámci socketové komunikace pracovat a přenášet data. IP, IPv6, TCP, UDP
13
3.2 Nespojově orientované sockety Při programování síťových aplikací se obecně setkáme s termínem nespojovaná služba. Nespojovanou službu využívá v praxi protokol UDP. Tento protokol je druhou alternativou k protokolu TCP. Protokol UDP je založen na odesílání nezávislých zpráv. Data pošleme a v daný okamžik ztrácíme jakoukoliv kontrolu; nedozvíme se, jestli druhá strana data dostala. Důležitým poznatkem je, že mezi dvěma koncovými body nenavazuje spojení. Pokud máme spojení, které ve skutečnosti nenavazuje; vzniká překážka. Protokol nepotvrzuje přijaté pakety a není tedy možné kontrolovat, zda se nějaký datagram během cesty neztratil. V případě potřeby se o nápravu možné ztráty dat postará vyšší vrstva (aplikační vrstva). Další nevýhodnou vlastností je pořadí, v jakém přijaté data dorazí. Při odeslání několik zpráv najednou jednomu příjemci nelze jednoznačně předpovídat, v jakém pořadí budou zprávy doručeny. Tento protokol se využívá především při přenosech multimediálních dat. Důvod je jednoznačný, přenáší se objemná data, potvrzování by bylo v rámci sítě náročné.
3.3 Spojově orientované sockety S opakem nespojované služby se v počítačových sítích setkáme pod pojmem spojová služba. Spojovanou službu představuje protokol TCP. Při komunikaci pomocí TCP je nezbytné navázat spojení. Spojení navazuje klient, který se připojuje k serveru. Po navázání spojení mezi aplikacemi se vytvoří virtuální dočasný okruh. Poté, co bylo spojení navázáno, může probíhat samotný přenos dat. Na konci komunikace je nutné spojení ukončit. Protokol TCP je spolehlivý, zaručuje doručení všech paketů a to ve správném pořadí. Pakety, které nedorazí, se posílají znovu. [20]
14
3.4 Synchronní sockety a operace Než si popíšeme synchronní způsob socketové komunikace, uděláme si terminologii v základních pojmech, které do tohoto odvětví jednoznačně zapadají. Blokující operace Z názvu je již patrné, že po zavolání metody, která je blokující, se další příkazy nemohou vykonávat do té doby, dokud tato operace není dokončena. Dokončení operace provádí většinou druhá strana, nebo událost. Zjednodušeně lze konstatovat, že se zablokuje hlavní vlákno. V případě že tento problém budeme chtít eliminovat, vytvoříme pracovní vlákno a spustíme operaci v něm. Reálným příkladem může být odeslání zprávy klientem na server. Operace odeslání není pro klienta ukončena do té doby, dokud server zprávu nepřijme a nepošle odpověď. Tato situace platí i pro opačný způsob. Seznam blokujících metod:
Accept,
Connect,
Receive,
ReceiveFrom,
Send,
SendTo.
Neblokující operace Opakem blokujících operací jsou operace neblokující, u kterých se po zavolání nečeká na dokončení. V takovém případě může program pokračovat následujícím příkazem a vlákno není blokováno. Seznam neblokujících metod:
Bind,
Listen.
Synchronní způsob komunikace můžeme přirovnat k blokujícím operacím. Často se tyto termíny sjednocují. Synchronní operace jsou obslouženy především jedním vláknem. Asynchronní způsob komunikace spočívá v odděleném vlákně. Metoda, která se zavolá, tak skončí ještě předtím, než je znám výsledek celé operace. V okamžiku, kdy je operace dokončena, je volána callback metoda. [22] 15
3.5 Asynchronní sockety a operace Opakem synchronní socketové komunikace je asynchronní socketová komunikace. U synchronní již víme, že pokud klient pošle serveru zprávu a server nepošle odpověď, nemůže klient vykonávat další operace a čeká v hlavním vlákně. Tato skutečnost nám znepříjemňuje situaci a jediné východisko pro tuto situaci je použití dalších vláken. Existuje samozřejmě i další alternativa, která se snaží tuto problematiku hravě a snadně vyřešit. Jedná se o asynchronní metody. Myšlenka obecně spočívá v tom, že pokud klient zašle serveru zprávu, tak tím klient ukončil operaci a může pokračovat dalšími operacemi. Pokud chceme zjistit, jak tato operace dopadla, musíme to jednoznačně zajistit. O dokončení operace a získání výsledku nás informuje zvláštní metoda zvaná callback. Asynchronní metody nemají daleko od vláken, jelikož asynchronní metody také používají vlákna. Každá asynchronní metoda má svůj začínající a končící ekvivalent. Pro příklad si můžeme uvést metodu pro připojení BeginConnect a EndConnect. Metoda BeginConnect je asynchronní a při jejím zavolání ihned skončí a přejde na další operace. Tato metoda má ve svém parametru asynchronního delegáta, který odkazuje na metodu callback, která běží v odděleném vlákně a čeká na return metody BeginConnect, tedy na stav od serveru. V případě, že metoda BeginConnect vrátí výsledek (stav), vrátí se nám callback, který definitivně zpracuje výsledek. O úplné ukončení asynchronní operace se postará synchronní metoda EndConnect.
Obrázek 2: Základní princip asynchronní metody připojení k serveru.
16
Veškerý postup je demonstrován na obrázku 3 a je implementačně v této bakalářské práci ke zhlédnutí v přílohové části.
17
4 Vývoj aplikace V předchozích částech bakalářské práce jsme se zabývali čistou teorií, která je založena na mé aplikaci. Nezbývá nic jiného, než nahlédnout na mou aplikaci z hlediska vývoje. Jakým přístupem vyvinout kvalitní software není v dnešní době jednoduchá otázka. Pokud se chceme zabývat tím, jakým způsobem budeme software vyvíjet, nabízí se nám dvě základní metodiky. Tradiční metodika vývoje softwaru Požadavky zákazníka jsou na začátku vývoje důkladně promyšleny a zpracovány, ovšem jsou neměnné. Proměnné jsou zdroje a čas. Seznam nejběžnějších tradičních metodik:
Vodopádový model,
Spirálový model,
RUP,
UP (volná alternativa RUP).
Agilní metodika vývoje software Zákazník nemá přesnou představu o tom, co požaduje. Za neměnné se považují zdroje a čas, nejdůležitější proměnná je funkcionalita projektu. Při agilním přístupu se provádí tzv. krátký inkrementovaný vývoj a nejdůležitějším pilířem je zpětná vazba se zákazníkem. Ten se občas jeví jako součást v týmu. V případě změn funkcionality, kterou přehodnotí klient, se provádí rigorózní testování. Seznam nejběžnějších agilních metodik:
Extrémní programování,
SCRUM Development Process,
Lean Development.
Obrázek 3: Rozdíl mezi tradiční a agilní metodou. 18
Z výše uvedených možností pro tvorbu softwaru jsem si vybral sekvenční vodopádový model, který nabízí tyto sekvence:
Obrázek 4: Sekvenční vodopádový model. Jedná se o jeden z nejstarších modelů životního cyklu softwaru. V tomto modelu jsou jednotlivé etapy seřazeny sekvenčně za sebou a opravdu mezi sebou protékají jako vodopád. Důležitou podmínkou je, že následující etapa začíná až po skončení etapy předcházející. Vodopádový model má v dnešní době mnoho nedostatků a je využíván především při výuce. Problém nastává v okamžiku, kdy si chce zákazník měnit své požadavky a nenachází se v etapě požadavky. V případě, že skončí poslední etapa a my předáme výsledný software zákazníkovi, který chce ovšem něco přehodnotit, musíme začít od první etapy, tedy od úplného začátku. Naopak, výhodou tohoto sekvenčního modelu je jednoduchost pro pochopení, každá etapa je jednoznačná.
4.1 Analýza a specifikace požadavků Veškeré analýzy provádí ve vývojovém týmu IT analytici. Hlavní náplní analytika je analýza požadavků a potřeb zákazníka. Navrhuje diagramy, sepisuje srozumitelně specifickou dokumentaci požadavků a dělá dalších mnoho dílčích aktivit.
19
Jeden z důležitých pilířů, které by měla firma splňovat, aby správně fungovala, je bezprostředně vzájemné porozumění všech stran ve firmě. Analytik se proto snaží ve firmě porozumět všem stranám, na starost má hned několik pracovních pozic, na které musí bezesporu dohlížet. Jedná se především o pozice obchodníka, testera, vývojáře a také samotného zákazníka. Každý člověk z těchto pozic má jiné zájmy, jiné úhly pohledu a analytik hraje často roli v pozici prostředníka. Požadavky mého softwaru jsou především cíle této bakalářské práce. Požaduje se následující:
Herní aplikace pracující na bázi klient-server, kde samotný server představuje entitu a to samé platí i pro klienta.
Asynchronní socketová komunikace.
Serverová i klientská grafická část aplikace nabízí herní pole, kam se vkládají herní symboly.
Server začne naslouchat pomocí tlačítka Začít naslouchat. O stavu připojení informuje server labelová komponenta.
Klient se pomocí tlačítka Připojit k serveru připojí k serveru. O stavu připojení informuje klienta labelová komponenta.
Zobrazení úvodní obrazovky při spuštění aplikace, která je nasazená do klienta i serveru.
Není možné k jednomu serveru připojit více klientů.
4.1.1 Diagram případů užití Diagram užití (use case) zobrazuje vnější pohled na náš systém, resp. na naší aplikaci a pomáhá tak odhadnout hranice systému. Tvorba těchto diagramů se provádí pomocí UML, což je modelovací a zároveň grafický jazyk pro tvorbu vizualizací, specifikací, dokumentací a návrhu systému. Hlavní postavou je zde aktér (tvar postavičky), zpravidla uživatel systému v určité roli. Maximální počet aktérů není omezen, ale při použití mnoha aktérů dochází ke značné nepřehlednosti. Aktér může obsahovat vazby, stejně jako naše případy užití (tvar oválný). Při použití některých z vazeb (generalizace) můžeme nepřehlednost zredukovat. Při myšlenkové analýze jsem do modelu zobrazil dva aktéry (klient, server)
20
a několik případů užití. Na tomto diagramu (obrázek 6), se zakládá specifický princip analýzy mé aplikace.
Obrázek 5: Diagram případů užití stavějící na bakalářské aplikaci piškvorky.
4.1.2 Doménová analýza Nyní, když má analytik k dispozici seznam všech požadavků a diagram pro případ užití, sestavuje na základě důležitých slov třídy, které budou pro samotný návrh klíčové. Analytik nehledá pouze podstatná jména, věnuje se i slovesům, které mu pomáhají najít třídní metody. Výstupem doménové analýzy je nový seznam tříd, který je testován a předán do návrhové sekce. V požadavcích mám sděleno, že komunikace na bázi klient-server má probíhat pomocí socketů. Analyzoval jsem projekt a zkoušel pojmout klíčové slovo socket z jiných úhlů.
21
Tímto algoritmem jsem našel třídu Socket, která představuje naše hlavní klíčové slovo. Další nalezenou třídou je SocketKlient a SocketServer.
4.2 Návrh aplikace Základní rozdíl mezi analýzou a návrhem je ten, že analýza se spíše zabývá otázkou co je potřeba udělat, zatímco návrh řeší spíše otázku jak to udělat. [12] Na návrhu aplikace pracuje především architekt, který navrhuje možná řešení. Obecně platí, že výstup návrhové etapy je předán pro programátory, kteří se snaží návrhový výstup implementovat. I v tomto případě je pro úspěšnou implementaci důležitá týmová komunikace.
4.2.1 Vývojové prostředí a popis základních komponent Základní vývojové prostředí, ve kterém je naprogramována aplikace poskytuje světoznámá a velkolepá firma Microsoft. Jedná se o Microsoft Visual C# 2010 Express Edition. Toto vývojové prostředí je zcela pro veřejnost zdarma. Omezení je licence, která přesně říká, že naprogramovaný program nesmí být dále použit ke komerčním účelům. Znamená to skutečnost, že se nesmí program prodávat (obchodovat s ním) apod. Výsledný program a zdrojová aplikace se musí použít pouze pro osobní účely. Největší předností je vizualizace funkcionality aplikace, která vede ke grafickému rozhraní. Grafické rozhraní je organizováno na platformě velmi užitečných ovládacích prvků (Controls – textové pole, tlačítka, seznamy, …). Ovládací prvky pracují na bázi Drag and Drop. V překladu tento termín znamená - táhni a pusť. Jedná se o moderní, kvalitní a vizualizační postup. Tento postup je ulehčením při programování pro rádoby-programátory, kteří nejsou znalí v oboru programování. Dalšími vlastnostmi, kterými prostředí disponuje je bezprostředně dynamická podpora. Dynamickou podporu si lze představit jako on-line nápovědu. Odborně se tomuto termínu říká IntelliSense. Pokud se ve zdrojovém kódu napíše některý z ovládacích prvků (pro příklad tlačítko) a poté se napíše operátor přístupu (tečka), nebo operátor šipky, zobrazí se k objektu tlačítko sada vlastností, metod, atributů, událostí, čímž tento ovládací prvek disponuje. Už z toho důvodu je malá pravděpodobnost překlepu. Nelze 22
do programu napsat něco, co vyvolaný prvek neumí. Vývojové prostředí pro vývoj nabízí základní okenní části:
ToolBox, který nabízí sadu všech ovládacích prvků.
Solution Explorer popisuje celkové složení naší aplikace.
Database Explorer je určen pro správu databázových aplikací.
Properties Window slouží pro nastavení vlastností a událostí k daným ovládacím prvkům.
Error List zobrazuje chyby (syntaktické, logické) při překladu.
Main Window je okno, kam se zdrojový kód píše.
Každé vývojové prostředí, které disponuje grafickým rozhraním, nabízí sadu ovládacích prvků. Nejběžněji používané ovládací prvky:
Tlačítko (Button) – klasické vizualizační tlačítko, které po stisknutí vyvolá událost onClick.
Zaškrtávací políčko (CheckBox) – komponenta pro určení pravdy nebo nepravdy; mnohonásobný výběr.
Přepínač (RadioButton) – komponenta pro přepínání voleb, často použití pro případ výběru muže nebo ženy.
Popisek (Label) – textová komponenta, která popisuje ovládací prvek, nebo nahrazuje klasické psaní.
Textové pole (TextBox) – hojně využívané vstupní pole pro psaní jednoho řádku textu, který má být dále zpracován.
Seznam (ListBox) – pole pro psaní více řádků, které pracuje s kterýmkoliv datovým typem v rámci generiky.
Posuvný jezdec (TrackBar) – posuvná komponenta, která slouží ke změně hodnoty jezdcem.
Ukazatel průběhu (ProgressBar) – komponenta často použita ve smyslu úspěšného dokončení.
23
4.2.2 Použité technologie Programovací jazyk C# je populární objektově orientovaný programovací jazyk, který vytvořila počítačová firma Microsoft zároveň s platformou .NET. Zmiňovaný programovací jazyk je zjednodušená, vylepšená a čistě objektová verze programovacího jazyka C++. Často se říká, že kdo chce být kvalitním a zkušeným programátorem, měl by se učit C++. Kdo chce být naopak rádoby-programátor, tak přesedlá k programovacímu jazyku C#. C# se využívá především k tvorbě:
databázových programů,
síťových programů,
webových aplikací,
webových služeb,
formulářových aplikací ve Windows.
4.2.3 Microsoft .NET Framework Nezbytnou podmínkou pro programování v jazyce C# je .NET Framework. Toto prostředí je nezbytnou součástí pro programování a skládá se z několika částí. První částí je společné běhové prostředí Common Language Runtime (CLR). Tento modul zajišťuje běh programů přeložených z různých programovacích jazyků do mezijazyka Microsoft Intermediate Language (MSIL). CLR umožňuje jejich vzájemnou spolupráci, takže různé součásti programu mohou být napsány v různých programovacích jazycích (VB, C++, Jscript). Dále tu je specifická knihovna tříd nazývaná Basic Class Library (BCL). Nad touto knihovnou jsou k nalezení knihovny pro tvorbu grafického uživatelského rozhraní programů a knihovny pro webové služby. Nejvyšší vrstvu tvoří překladače různých programovacích jazyků. S postupným vývojem architektury vznikaly i určité verze .NET Frameworku. Každá verze se specifikuje určitými doplňky. Primárně si popíšeme změny v programovacím jazyce C# ve vydaných verzích 1.0, 1.2, 2.0, 3.0 a 4.0. Nesmíme zaměňovat verze architektury .NET od samotného programovacího jazyka C#.
24
Verze 1.0 Přichází první verze objektově orientovaného programovacího jazyka C# s .NET Frameworkem verze 1.0. Vznikají jednoduché programy a neexistují skoro žádné výhody pro jednoduchost kódu. Verze 2.0 S touto verzí přichází i nové doplňky jazyka jako jsou částečné a statické třídy, generika, iterátory a anonymní metody pro pohodlnější užívání delegátů (odkazů na metody). Verze 3.0 Tato verze C# byla značně vylepšena. Jazyk C# byl v tuto dobu obohacen skvělými užitečnými doplňky. Můžeme zde najít novinky jako je dotazovací jazyk (LINQ), nové lambda výrazy, jednoduché použití vlastností (properties), klíčové slovo var a rozšiřující metody (extension methods). Verze 4.0 Jedná se o nejnovější (aktuálně) vydanou verzi, která je stále ve vývoji. Tato verze podporuje dynamicky typované objekty, kovarianci a kontravarianci. Na obzoru je již verze 5.0. Tato verze má v budoucnu podporovat Windows runtime a plnou podporu pro jednoduché použití asynchronních služeb, klíčová slova wait a async.
Obrázek 6: Koncepce platformy .NET.
25
4.2.4 Architektura klient-server Klient-server je síťová architektura, která odděluje klienta (často aplikaci s grafickým uživatelským rozhraním) a server. Klient-server aplikace fungují na bázi spolupráce mezi tazatelem (klientem) a tím, kdo na dotaz odpovídá (server). Klient typicky pošle požadavek pomocí určitého protokolu, kterému obě strany rozumí a pokud server takovému požadavku dokáže a smí vyhovět, provede jej a vrátí klientovi odpověď. Filozofie klient-server aplikací je klíčovou v rámci síťové komunikace. [13] Výhody architektury:
Klient se nemusí zajímat o výpočetně náročné algoritmy a operace, snaží se zpracovat spíše vrácená data.
Při změně náročného algoritmu by se tato změna musela distribuovat do všech klientů, což není zdaleka vždy reálné, v případě klient-server by mohlo stačit modifikovat pouze serverovou část.
4.2.5 Co provádí klient v aplikaci? Při samotném návrhu aplikace bychom měli zvážit, jaké úkoly bude náš aplikační klient provádět. [14] 1. Vytvoření socketu klienta. Vytvoření hlavního socketu, do toho socketu se data nezapisují. 2. Přiřazení názvu, číslo portu a IP adresy serveru. K vytvořenému socketu přiřadíme číslo portu a IP adresu serveru, ke kterému se chceme připojit. 3. Připojení na server. Po stisknutí tlačítka Připojit k serveru se posílá požadavek o připojení na server. 4. Průběh vlastní komunikace. V případě, že je spojení navázáno, může probíhat vlastní přenos dat.
26
Odeslání dat Klient klikne na tlačítko ve svém hracím poli, které je neobsazené. Po stisknutí tlačítka posílá klient souřadnice serveru, který čeká na příjem dat. Zároveň se klientovi na hracím poli vybarví stisknuté tlačítko červeným kolečkem. Příjem dat Klient obdržel na socketu zprávu, musí tak rozpoznat, jaký typ zprávy od serveru přijal. Klient dostává od serveru pouze dva druhy zpráv. Buď klient dostal zprávu o konci hry, kterou musí dál parsovat, aby zjistil, kdo vyhrál. V druhém případě přijal souřadnice serveru. 5. Konec komunikace a odpojení od serveru. 6. Zavření socketu klienta. Pro uvolnění dat a systémových prostředků je nezbytné socket uzavřít.
4.2.6 Co provádí server v aplikaci? Úloha socketového serveru je mírně složitější. Server navíc provádí výpočet, který ve svém algoritmu hledá pět stejných symbolů v libovolném směru. 1. Vytvoření socketu serveru. Vytvoření hlavního socketu, do kterého se data nezapisují. 2. Přiřazení názvu socketu k danému portu a IP adrese. Klienti potřebují přistupovat k tomuto socketu. Dojde k asociaci socketu s koncovým bodem, tj. naší IP adresou a portem. 3. Vytvoření fronty pro příchozí požadavky. Voláním funkce listen se vytvoří fronta pro příchozí požadavky od klientů. Server si požadavky ukládá do fronty. 4. Čekání na připojení klientů. Pokud server ve své frontě nemá žádný požadavek, čeká do té doby, dokud si do své fronty neuloží nový požadavek (klienta). Pokud je fronta plná, jsou další příchozí požadavky ignorovány.
27
5. Vytvoření socketu pro klienty a průběh vlastní komunikace. Vytvoří se socket pro novou komunikaci s klientem (socketu přísluší adresa klienta, který se připojil). Do tohoto socketu lze zapisovat, jako do souboru. Odeslání dat Server klikne na tlačítko ve svém hracím poli, které je neobsazené. Po stisknutí tlačítka server kontroluje, jestli nevytvořil výherní pětku. Pokud ji vytvořil, zašle klientovi zprávu o konci hry, jinak zašle své souřadnice. Zároveň se serveru na hracím poli vybarví stisknuté tlačítko modrým křížkem. Příjem dat Server příjem zpracuje, uloží si klientovy souřadnice na svou hrací plochu a zkontroluje, jestli klient nesestavil výherní pětku. V případě, že tomu tak je, zasílá server klientovi odpověď o konci hry. 6. Ukončení spojení s klientem a uzavření příslušeného socketu. 7. Zavření socketu serveru.
28
4.2.7 Návrhový diagram tříd
Obrázek 7: Diagram tříd navržený pro aplikaci.
29
4.2.8 Synchronní diagram komunikace
Obrázek 8: Podrobné schéma socketové komunikace klient – server. Převzato od [14].
4.3 Implementace Implementace softwaru je transformace návrhu jednotlivých modulů a jejich vzájemných vazeb do programové realizace. [15] Socketový klient i server jsou implementačně z hlediska přenosu dat na podobné úrovni. Server navíc implementuje algoritmus pro vyhodnocení vítěze. Způsob zpracování přijatých dat V případě, že metoda BeginReceive vrátí výsledek (naskytne událost), zavolá se callback metoda OnDataReceive. V této metodě si vyzvedneme data. Nyní si popíšeme způsob zpracování dat. Nejprve je potřeba si přetypovat náš socket, abychom zjistili více informací ze socketu. Dalším příkazem si uložíme počet bajtů na socketu. Abychom byli schopni si přijaté bajty uložit jako znaky, vytvoříme si pole znaků o velikosti počtu přijatých bajtů. Proto si vytvoříme dekodér, který převede bloky bajtů na bloky znaků dle UTF-8. Pro převedení bajtů na znaky slouží metoda GetChars, kde 30
parametrově předáváme náš buffer, který představuje pole bajtů, kde máme přijaté data a znaky, které představují pole znaků. V posledním kroku převedeme pole znaků na jednoduchý řetězec (string). public void OnDataReceived(IAsyncResult asyn) { Socket sock = (Socket)asyn.AsyncState; int prijateBajty = sock.EndReceive(asyn); char[] znaky = new char[prijateBajty]; Decoder dekoder = Encoding.UTF8.GetDecoder(); dekoder.GetChars(buffer, 0, prijateBajty, znaky, 0); String prijatyRetezec = new String(znaky); if (prijateBajty > 0) { // Práce s přijatým řetězcem... } }
Algoritmus pro hledání pěti stejných symbolů Funkce najitPetku, která hledá pět stejných symbolů v libovolném směru má jako vstupní parametry souřadnice int x, y a char symbol, který specifikuje, jestli se má kontrolovat kolečko, či křížek. Návratovou hodnotou funkce je booleovský hodnotový typ true nebo false, který signalizuje úspěšnost nalezení pětky. V samotné implementaci funkce se nachází globální pole pole_test typu char, které si ukládá na určené pozice symboly. Dále jsem si vytvořil funkci jeVPoli, která kontroluje, jestli se symbol nachází ve správném rozmezí. Bez použití této funkce by v některých případech překladač oznamoval chybu: Array index is out of range. Pro ukázku uvedu zdrojový úryvek pro hledání pěti stejných symbolů ve vodorovném směru. Ostatní dva směry (svislý a šikmý) pracují na stejné bázi. Na začátku funkce se provádí inicializace proměnných pocet, x a y. Vytvoření identických proměnných je ve funkci z důvodu, že během provádění algoritmu se provádí určité modifikace se souřadnicemi x, y, přitom výchozí argumentové souřadnice xn, yn musí být zachovány. První while cyklus testuje počet stejných symbolů směrem doleva od aktuálně vloženého. V případě, že proměnná pocet nabude číselné hodnoty 5, vrací se true a funkce skončí. V druhém případě se obsah proměnné pocet přenáší do druhého while cyklu. Na konci prvního while cyklu musíme celočíselnou proměnnou y posunout o jednu souřadnici směrem doprava, protože aktuální souřadnici jsme již testovali. Na konci obou while cyklů se provede inicializace hodnot jako na začátku funkce, poté se může začít se zbylými směry.
31
Funkce pro kontrolu rozmezí bool jeVPoli(int x, int y) { return ((x >= 0 && x < X_SOURAD+4) && (y >= 0 && y < Y_SOURAD+4)); }
Funkce pro hledání pěti symbolů ve vodorovném směru public bool najitPetku(int xn, int yn, char symbol) { int pocet = 0; int x = xn; int y = yn; // Testujeme počet správných tahů vodorovně, směr doleva while (jeVPoli(x, y) && pole_test[x, y] == symbol) { pocet++; y--; if (pocet == 5) return true; } y = yn + 1; // Testujeme počet správných tahů vodorovně, směr doprava while (jeVPoli(x, y) && pole_test[x, y] == symbol) { pocet++; y++; if (pocet == 5) return true; } pocet = 0; x = xn; y = yn; // Testujeme další směry... return false; }
4.4 Integrace a testování Testování se provádí z pohledu tří základních dimenzí reprezentovaných kvalitou, funkcionalitou a výkonností systému. [16] V průběhu vývoje své aplikace proběhlo testování aplikace ze dvou stran, tedy z pohledu programátora (Developer’s Unit testing) a proběhlo také testování ze strany mých přátel (Feature testing). Aplikace se nejvíce testovala na lokální adrese 127.0.0.1 a portu 8221. Problém nastal, když se aplikace začala testovat v internetové síti. Jelikož vlastním veřejnou IP adresu, založil jsem server a na druhém počítači spustil kolega klientskou část aplikace.
32
Kolega však nebyl schopen se připojit na můj stroj, který vlastní veřejnou IP adresu. V tu chvíli jsem si uvědomil, že něco není v pořádku. Socketová komunikace je komunikačním prostředkem mezi aplikacemi, které běží na určitém portu. Zjistil jsem,
že
mám
otevřené
porty
za
routerem,
proto
jsem
musel
provést
tzv. port forwarding (nasměrování portů), které spojení povolí. Černá a bílá skříňka Při testování černé skřínky testujeme vstupy a výstupy softwaru bez znalosti zdrojového kódu (do černé skříňky nelze nahlížet) aplikace. Pří testování bílé skříňky se testují vstupy a výstupy softwaru s nahlížením do zdrojového kódu (do bílé skříňky lze nahlížet) aplikace.
4.4.1 Funkčnost Veškeré funkční požadavky, tedy cíle mé bakalářské práce, které jsou naprogramovány v herní aplikaci, jsou funkční. Nesetkal jsem se v programu s metodou, která neplní svou funkci. Algoritmicky nejsložitější je funkce pro hledání pěti stejných symbolů v libovolném směru. Tato výpočetní metoda, kterou vykonává server, se testovala nejvíce. Ostatní vstupní moduly jsou zabezpečeny.
4.4.2 Použitelnost Ovládání aplikace je jednoduché. Aplikace je uživatelsky přívětivá, nenabízí mnoho možností a je přehledná. Na klientské části je jedno tlačítko pro připojení a to samé platí pro server, který má jedno tlačítko pro naslouchání. Obě herní části obsahují herní pole a vstupní komponenty.
4.4.3 Spolehlivost Robustní aplikace musí reagovat na náhlé změny, na které se v daný okamžik nečeká. Může dojít k výpadku sítě, nebo k různým druhům přetížení. Při těchto problémech se musí aplikace vzpamatovat, detekovat tento stav a nahlásit ho. Snažil jsem se vyřešit spolehlivost pomocí programových výjimek. Programové výjimky umí rozpoznat náhlý stav a upozornit na něj.
33
4.4.4 Výkon Výkon aplikace je testován a optimalizován implementačně. Na začátku jsou vytvořeny prostředky pro komunikaci, které jsou po skončení aplikace řádně uvolněny. Operační paměť je řádně spravována. Další optimalizací je přijmutí pouze jednoho uživatele. Více požadavků na komunikaci aplikace řádně ignoruje a nepovoluje.
5 Srovnání s existujícími aplikacemi Na českém internetu jsem našel pouze pár podobných aplikací, které se podobají aplikaci této bakalářské práce, tj. desktopovým síťovým piškvorkám. Mnohem více síťových piškvorek se na českém internetu nachází v nedesktopové formě, tedy přímo na webové platformě. Druhým typem hry, kde hraje počítač proti uživatelovi, jsem našel nespočetně mnoho. 1. Síť. piškvorky, dostupné: [http://www.slunecnice.cz/sw/sitove-piskvorky/stahnout/] Tyto piškvorky jsou naprogramovány v programovacím jazyce C++. Nabízí mnohem lepší grafické možnosti a na konci hry se výherní kombinace proškrtne kvůli čitelnosti. To má aplikace neumí, přemýšlím o realizaci tohoto modulu v budoucnosti. 2. Síť. piškvorky, dostupné: [http://lhdelphi.wz.cz/showarticle.php?ID=40] Neměl jsem přímou zkušenost vyzkoušet tyto síťové piškvorky, protože se při spuštění vyhodnotila virová hrozba. Přesto jsem alespoň chvíli viděl, co aplikace nabízí. Tyto piškvorky jsou asi nejlepší alternativou, kterou jsem našel. Ke spuštění je potřeba jedna část aplikace, která po spuštění nabízí volbu klient - server - špion. O rozšíření špiona do aplikace samozřejmě přemýšlím a v budoucnu bych tuto volbu rád realizoval.
34
6 Uživatelská příručka Celkový projekt je z hlediska přehlednosti rozdělen na klientskou a serverovou část.
6.1 Serverová část 1. Spuštění souboru SocketServer.exe Při spuštění tohoto souboru se zobrazí úvodní okno, které během načítání inicializuje základní doplňky aplikace. Po načtení úvodního okna se zobrazí hlavní herní okno aplikace, kde můžeme v popiskách zpozorovat informace o stavu serveru, stavu klienta a který hráč je na tahu. Na pravé straně se nachází herní pole pro samotnou hru.
Obrázek 9: Úvodní okno serveru při spuštění aplikace.
Obrázek 10: Hlavní herní okno serverové části.
35
2. Založení, naslouchání serveru Založení serveru je nezbytná činnost pro hraní piškvorek. Pro založení serveru se v oblasti nastavení uvádí pouze číslo portu, na kterém bude server naslouchat. Zmáčkneme na tlačítko Začít naslouchat a poté se v popisku Stav serveru zobrazí text Naslouchá. V tento okamžik čeká server na klienta. IP adresa je automaticky nastavena na lokální IP v rámci rozsahu LAN a také na klasickou IP adresu v rámci celé internetové sítě. Nutnou podmínkou je vlastnit veřejnou IP adresu.
Obrázek 11: Server naslouchá na příchozí spojení.
36
6.2 Klientská část 1. Spuštění souboru SocketKlient.exe Při spuštění tohoto spustitelného souboru se podobně jako u serverové části zobrazí úvodní okno a poté hlavní herní okno aplikace.
Obrázek 12: Úvodní okno klienta při spuštění aplikace.
Obrázek 13: Hlavní herní okno klientské části.
37
2. Připojení k serveru Na hlavním okně se v oblasti nastavení připojení vyskytuje IP adresa serveru a Port. Tyto údaje pečlivě vyplníme a zmáčkneme na tlačítko Připojit k serveru. V případě úspěchu se do popisku zobrazí text Připojeno k vzdálenému serveru, jinak se zobrazí Neúspěšný pokus o připojení k serveru.
Obrázek 14: Neúspěšný pokus o připojení k serveru.
Obrázek 15: Úspěšný pokus o připojení k serveru.
38
6.3 Komunikace 1. Zobrazení průběhu hry Obě strany jsou síťově navázané, hra může začít. Začíná server, který má znak modrého křížku.
Obrázek 16: Průběh hry z pohledu klienta.
Obrázek 17: Průběh hry z pohledu serveru.
39
2. Zobrazení výhry Hráči se snaží k dosažení pěti stejných symbolů v libovolném směru. Pokud se tak jedné straně stane, server na to okamžitě reaguje. K zobrazení výhry se využívá vyskakovací okno.
Obrázek 18: Zobrazení zprávy o prohře.
Obrázek 19: Zobrazení zprávy o výherní kombinaci.
40
7 Závěr 7.1 Zhodnocení Cílem mé bakalářské práce bylo navrhnout a naprogramovat jednoduchou asynchronní síťovou aplikaci komunikující na bázi klient-server v programovacím jazyce C#. Aplikaci jsem úspěšně dokončil, její vývoj trval přibližně tři měsíce. Po třech měsících jsem se začal plně věnovat textové části bakalářské práce. I když se samotná aplikace jeví jako jednoduchá záležitost, tak v samotném návrhu a pozdější implementaci bylo nejobtížnější pochopit princip asynchronní komunikace, resp. odesílání zpráv tímto principem na bázi klient-server. Bez pochopení – jak to funguje – není možné fungující aplikaci sestavit. Po skončení implementační části se přešlo na testování a odhalování chyb. V aplikaci se během testování našlo několik závažných a nepříjemných chyb, které omezovaly hratelnost piškvorek. Aplikace se za každých podmínek musí chovat robustně, bez ošetřených vstupů a výstupů nelze pokračovat dál.
7.2 Možnosti dalšího rozšíření aplikace Myslím si, že má aplikace není z mnoha hledisek dokonalá a mnoho věcí se dá vylepšit a doladit. První věcí, kterou bych se chtěl bezesporu v aplikaci zabývat je strohý grafický design, který se mi dostatečně nelíbí. Aplikace je stavěna na rozhraní Windows Forms, což není žádný grafický zázrak, dnes už spíše zastaralá technologie. Několik let poté Microsoft představil Microsoft Windows Forms 2.0, do kterého se přidaly pouze nové komponenty. V roce 2007, ve verzi Frameworku 3.0 se objevuje zcela nová vrstva WPF, která se využívá na vykreslování grafického rozhraní založeném na DirectX. WPF se snaží oddělit grafické rozhraní aplikace od samotné funkčnosti aplikace. Pro popis grafického rozhraní slouží značkovací jazyk XAML, který je založen na XML a podobá se značkovacímu jazyku HTML.
41
WPF nabízí hned několik výhod oproti WF:
Interaktivní animace, není potřeba využití časovačů a složitých vykreslovacích algoritmů, jak tomu bylo ve WF.
Vektorová grafika.
Direct3D: hardwarová akcelerace pomocí grafické karty.
Další věc, která by šla určitě obměnit je samotný kód aplikace. V některých částech používám zcela zbytečné konstrukce, které zpomalují celkový chod aplikace. Od verze programovacího jazyka C# 5.0 se setkáme s asynchronním programováním, které bude pro implementaci jednodušší, než doposud. Určitě by aplikace mohla mít mód špióna, který by pozoroval hru. Počet špionů by byl neomezen, server by si jejich požadavky ukládal do své fronty. Celá aplikace končí, resp. zavře se hlavní okno, jakmile jeden z hráčů vyhraje. To není příliš praktické, ale pro základní demonstraci to postačí. Po skončení hry si představuji dialogovou nabídku, která nabídne oběma hráčům otázku: „Chcete si zahrát novou hru?“. V případě, že obě strany odpoví kladně, začne nová hra. V ostatních případech se aplikace vyresetuje do výchozího stavu a server odpojí protihráče a špiony. Další možností rozšíření je samotné vyhodnocení vítěze. Představuji si, že při vítězství jednoho z hráčů se výherní kombinace proškrtne pro lepší čitelnost. Rozdělení aplikace na dvě části mi též nepřijde dobrým řešením. Určitě lepším řešením je pouze jedna herní část, na které se zvolí alternativa (klient – připojit) nebo (server – vytvořit).
42
Seznam použité literatury 1. RYBKA, Aleš. Česká federace piškvorek a renju: Historie gomoku a renju [online]. [cit. 2012-04-26]. Dostupné z: http://www.piskvorky.cz/clanky/zajimavosti-zesveta-piskvorek-a-renju/historie-gomoku-a-renju/ 2. Piškvorky. In: Wikipedia: otevřená encyklopedie [online]. San Francisco (CA): Wikimedia Foundation, 2005, stránka byla naposledy editována 10. 2. 2012, 17:42 [cit. 2012-04-26]. Dostupné z: http://cs.wikipedia.org/wiki/Piškvorky 3. VRTÍLEK, Michal. Piškvorky [online]. Brno, 2008 [cit. 2012-04-28]. Bakalářská práce. Vysoké učení technické. Vedoucí práce Ing. Jaroslav Rozman. Dostupné z: http://www.fit.vutbr.cz/study/DP/rpfile.php?id=7933 4. BALEJ, Marek. Síťové protokoly a sockety [online]. České Budějovice, 2010. Bakalářská práce. Jihočeská univerzita. Vedoucí práce Ing. Ladislav Beránek, CSc., MBA. Dostupné z: http://theses.cz/id/i663qu/downloadPraceContent_adipIdno_15551 5. RADHAKRISHNAN, Robert; SOLWORTH, Jon. Socket Programming in C/C++ [online prezentace]. 2004 [cit. 2012-05-05]. Dostupné z: http://www.docstoc.com/docs/66706101/Socket-Programming-in-CC 6. Počítače pro řízení: Cvičení 4 - sockety [online]. 2009, stránka byla naposledy editována 9. 3. 2009 [cit. 2012-05-03]. Dostupné z: http://dce.felk.cvut.cz/pos/cv4/ 7. BSD. In: Wikipedia: otevřená encyklopedie [online]. San Francisco (CA): Wikimedia Foundation, 2005, stránka byla naposledy editována 8. 2. 2012, 17:41 [cit. 2012-05-10]. Dostupné z: http://cs.wikipedia.org/wiki/BSD 8. FÁBERA, Vít. Jak naprogramovat internetovou komunikaci? [online prezentace]. Praha: Ústav informatiky a telekomunikací, Fakulta dopravní, ČVUT, [cit. 2012-05-23]. Dostupné z: http://www.fd.cvut.cz/personal/xfabera/BIVS/programovani_inet.pdf 9. POLÁK, Daniel. Programování síťových aplikací [online]. Brno, 2006. Bakalářská práce. Masarykova univerzita. Dostupné z: http://is.muni.cz/th/51885/fi_b/WinSock.pdf
43
10. KOVÁČIK, Lukáš. Bezdrátové dálkové ovládání CNC řídicích systémů [online]. Praha, 2008. Diplomová práce. České vysoké učení technické. Dostupné z: https://support.dce.felk.cvut.cz/mediawiki/images/e/e2/Dp_2008_kovacik_lukas.pdf 11. KADLEC, Václav. Agilní programování [online]. Computer Press, 2004 [cit. 2012-05-20]. Dostupné z: http://johnny.bloguje.cz/740763-klasicke-a-agilnimetodiky-vyvoje-software.php 12. Objekty - Metodiky a Notace: Úvod k problematice popisu reality [online]. 2008, stránka byla naposledy editována 3. 2. 2008, 15:22 (Luboš Pavlíček) [cit. 2012-05-19]. Dostupné z: http://objekty.vse.cz/Objekty/MetodikyANotacePopisReality 13. SVĚT HARDWARE: Klient-server [online]. 2010, [cit. 2012-05-19]. Dostupné z: http://www.svethardware.cz/glos.jsp?doc=1F194B6D2A901 385C125747E007EFA41 14. SYNEK, Martin. Využití modulu s Embedded Linux pro připojení senzorů, ovládání výstupů a komunikaci s PC [online]. Praha, 2010. Bakalářská práce. České vysoké učení technické. Dostupné z: http://cyber.felk.cvut.cz/research/theses/papers/95.pdf 15. KŘENA, Bohuslav; KOČÍ, Radek. Úvod do softwarového inženýrství: IUS. Studijní opora [online]. Brno, 2006. Vysoké učení technické, Fakulta informačních technologií [cit. 2012-05-20]. 100 s. Dostupné z: http://suave_skola.varak.net/lectures_IUS/opora_IUS.pdf 16. VONDRÁK, Ivo. Úvod do softwarového inženýrství [online]. Ostrava, 2002. Technická univerzita Ostrava, Fakulta elektrotechniky a informatiky, katedra informatiky [cit. 2012-05-15]. Dostupné z: http://vondrak.cs.vsb.cz/download/Uvod_do_softwaroveho_inzenyrstvi.pdf 17. OO, UML, analýza, metodologie [online]. [cit. 2012-05-24]. Dostupné z: http://mpavus.wz.cz/uml/uml-uvod-1.php 18. Testování softwaru. In: Wikipedia: otevřená encyklopedie [online]. San Francisco (CA): Wikimedia Foundation, 2005 [cit. 2012-05-24]. Dostupné z: http://cs.wikipedia.org/wiki/Testování_softwaru
44
19. KVASNICA, Josef. Programování v C#. Komplexní informační web o programování v .NET [online]. [cit. 2012-05-03]. Dostupné z: http://csharp.aspone.cz 20. CINGROŠ, Milan. Článek abclinuxu. Výkladový slovník: TCP [online]. 2007, [cit. 2012-04-29]. Dostupné z: http://www.abclinuxu.cz/slovnik/tcp 21. LEE, Wei-Meng. Practical .NET 2.0 networking projects. New ed. Berkeley, Calif: Apress, 2007. ISBN 978-159-0597-903. 22. Budoucnost asynchronního programování v C# [online]. [cit. 2012-04-28]. Dostupné z: http://dotnetco.wordpress.com/2011/05/08/budoucnost-asynchronnihoprogramovani-v-c/
45
Seznam obrázků Obrázek 1: Základní princip socketů na bázi klient-server. ........................................... 12 Obrázek 2: Základní princip asynchronní metody připojení k serveru. ......................... 16 Obrázek 3: Rozdíl mezi tradiční a agilní metodou. ........................................................ 18 Obrázek 4: Sekvenční vodopádový model. .................................................................... 19 Obrázek 5: Diagram případu užití stavějící na bakalářské aplikaci piškvorky. .............. 21 Obrázek 6: Koncepce platformy .NET. .......................................................................... 25 Obrázek 7: Diagram tříd navržený pro aplikaci. ............................................................. 29 Obrázek 8: Podrobné schéma socketové komunikace klient – server. ........................... 30 Obrázek 9: Úvodní okno serveru při spuštění aplikace. ................................................. 35 Obrázek 10: Hlavní herní okno serverové části. ............................................................. 35 Obrázek 11: Server naslouchá na příchozí spojení. ........................................................ 36 Obrázek 12: Úvodní okno klienta při spuštění aplikace. ................................................ 37 Obrázek 13: Hlavní herní okno klientské části. .............................................................. 37 Obrázek 14: Neúspěšný pokus o připojení k serveru. .................................................... 38 Obrázek 15: Úspěšný pokus o připojení k serveru. ........................................................ 38 Obrázek 16: Průběh hry z pohledu klienta...................................................................... 39 Obrázek 17: Průběh hry z pohledu serveru. .................................................................... 39 Obrázek 18: Zobrazení zprávy o prohře. ........................................................................ 40 Obrázek 19: Zobrazení zprávy o výherní kombinaci. ..................................................... 40
46
Seznam použitých zkratek CLR – Common Language Runtime GUI – Graphical User Interface HTML – HyperText Markup Language IDE – Integrated Development Environment IP – Internet Protocol LINQ – Language Integrated Query MSIL – Microsoft Intermediate Language RUP – Rational Unified Process TCP – Transmission Control Protocol UDP – User Datagram Protocol WPF – Windows Presentation Foundation WF – Windows Forms XAML – Extensible Application Markup Language XML – Extensible Markup Language
47
Seznam příloh A Obsah přiloženého CD Na přiloženém CD se v kořenovém adresáři nachází tato bakalářská práce ve formátu bakalarska_prace.pdf s jednoduchým návodem navod.txt pro obsluhu programu. V adresáři PROJEKT se nachází oba celistvé projekty (Klient a Server) včetně sestavovacích souborů a zdrojových kódů. Adresář EXE obsahuje dva samostatné spustitelné soubory (SocketKlient.exe a SocketServer.exe).
48
B Zdrojové kódy Zjednodušená implementace hracího pole. private MyButton[,] hraci_pole; public void HraciPole() { // ... Inicializace proměnných // Vytvoříme pole, do kterého uložíme všechna tlačítka hraci_pole = new MyButton[X_SOURAD, Y_SOURAD]; int x = 0; int y = 0; // Naplníme pole tlačítkama for (int i = 0; i < X_SOURAD; ++i) { x = 0; for (int j = 0; j < Y_SOURAD; ++j) { // Vytvoříme tlačítko MyButton btn = new MyButton(); // Nastavení každého tlačítka btn.ID[0] = i; btn.ID[1] = j; // Pozice tlačítka btn.Location = new Point(x, y); // Přidání události - po kliku se spustí MyBtnClick btn.Click += new EventHandler(MyBtnClick); // Posun o 20, tlačítko má rozměr 20x20 (nový sloupec) x += 20; // Přidání tlačítka na nastavenou Location gbHerniPole.Controls.Add(btn); } // Posun o 20, tlačítko má rozměr 20x20 (nový řádek) y += 20; } }
49
Zjednodušená implementace připojení klienta na server. private void Pripojeni_Klik(object sender, EventArgs e) { try { // Vytvoříme nového socketového klienta socketClient = new Socket( AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP); // Z TextBoxu převezmeme IP jako String String stringIP = txtIPAddress.Text; // Z TextBoxu převezmeme Port jako String String stringPort = txtPort.Text; // Převedeme String na integer int Port = Convert.ToInt16(stringPort, 10); // Převedeme String na IPAddress IPAddress IPAddress = IPAddress.Parse(stringIP); // Máme zapouzdřen koncový bod serveru IPEndPoint EndPoint = new IPEndPoint(IPAddress, Port); // Neblokující socketová komunikace socketClient.Blocking = false; // Delegát, který ukazuje na metodu (callback) OnConnect AsyncCallback connectDelegate = new AsyncCallback(OnConnect); // Zkoušíme se připojit socketClient.BeginConnect(EndPoint, connectDelegate, socketClient); } // Odchytáváme globální chyby při připojení na server catch (Exception e) { MessageBox.Show(e.ToString()); } } // Callback metoda: zpracování (dokončení) public void OnConnect(IAsyncResult ar) { Socket sock = (Socket)ar.AsyncState; try { // Klientův socket připojen: server přijal žádost if (sock.Connected) { socketClient.EndConnect(ar); lblStatusKlient.Text = "Připojeno k serveru"; } else { lblStatusKlient.Text = "Neúspěšný pokus o připojení"; } } catch (Exception e) { MessageBox.Show(e.ToString()); } }
50
Zjednodušená implementace přijmutí klienta serverem. private void Naslouchani_Klik(object sender, EventArgs e) { try { // Vytvoříme server socket socketServer = new Socket( AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); IPEndPoint lokalniServer = new IPEndPoint( IPAddress.Any, Int16.Parse(txtCisloPortu.Text)); // Bind volání kvůli asociaci socketServer.Bind(lokalniServer); // Vytvoření fronty pro požadavky o velikosti 1 socketServer.Listen(1); // Pokud je fronta prázdná, server požadavek přijme socketServer.BeginAccept(new AsyncCallback(OnClientConnect), null); } catch (Exception e) { MessageBox.Show(e.ToString()); } } // Callback metoda: zpracování (dokončení) public void OnClientConnect(IAsyncResult asyn) { try { // Při úspěchu metoda vrací nový socket pro komunikaci s klientem socketClient = socketServer.EndAccept(asyn); // Změníme stav, že se klient připojil je_pripojen = true; lblKlientInfo.Text = "Klient je aktivní, připojen!"; } catch (Exception e) { MessageBox.Show(s.ToString()); } }
51
Zjednodušená implementace příjmu dat na socketu. // Metoda čekající na data public void waitOnData(Socket s) { try { if (delegatCallback == null) { delegatCallback = new AsyncCallback(OnDataReceived); } s.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, delegatCallback, s); } catch (Exception e) { MessageBox.Show(e.ToString()); } } // Callback metoda: zpracování (dokončení) public void OnDataReceived(IAsyncResult asyn) { try { // ZPRACOVÁNÍ PŘIJATÝCH DAT Socket sock = (Socket)asyn.AsyncState; // Konec příjmu dat, metoda vrací počet přijatých bytů int prijateBajty = sock.EndReceive(asyn); // Vytvoříme pole znaků o velikost přijatých bajtů char[] znaky = new char[prijateBajty]; // Vytvoříme dekodér typu UTF-8 Decoder dekoder = Encoding.UTF8.GetDecoder(); // Převedeme bajtové bloky na znakové bloky dekoder.GetChars(buffer, 0, prijateBajty, znaky, 0); // Převedeme znaky na řetězec String prijatyRetezec = new String(znaky); if (prijateBajty > 0) { // ... Zpracování přijatého řetězce na_rade = !na_rade; // Vrátíme se a čekáme na další data waitOnData(socketClient); } } catch (SocketException) { lblKlientInfo.Text = "Klient se odpojil!"; } }
52
Zjednodušená implementace odeslání souřadnic druhé straně. protected void MojeTlacKlik(object sender, EventArgs e) { if (je_pripojen) { if (!na_rade) { // Pomocí senderu zjistíme, které tlačítko bylo stisknuto MyButton btn = (MyButton)sender; string data = ""; // Kontrolujeme, jestli na tuto pozici někdo neklikal if (!hraci_pole[btn.ID[0], btn.ID[1]]) { na_rade = true; // Zaznačíme si, že jsme sem klikli pole_kliknuto[btn.ID[0], btn.ID[1]] = true; // Připravíme si řetězec k odeslání data = btn.ID[0] + " " + btn.ID[1]; } try { // Ukládáme řetězec do pole bajtů a posíláme byte[] byteData = Encoding.ASCII.GetBytes(data); socketClient.Send(byteData); } catch (Exception e) { MessageBox.Show(e.ToString()); } } } }
Zjednodušená implementace odeslání zpráv o konci hry serverem. public void kontrolaPetky(int x, int y, char symbol) { pole_test[x, y] = symbol; try { // Pokud najdeme pět stejných symbolů je konec hry if (najitPetku(x, y, symbol)) { // Vytvoříme zprávu o konci hry, kterou pošleme klientovi string data = "END " + symbol; byte[] byteData = Encoding.ASCII.GetBytes(data); socketClient.Send(byteData); } catch (Exception s) { MessageBox.Show(s.ToString()); } } }
53