Online verseny

Sziasztok!

Egy városi matekversenynek, amelyet félig-meddig (vagyis lassan inkább teljesen) én szervezek, szokott lenni szóbeli fordulója is (a legjobb 12 szóbeli fordulóba jut, ahol néhány, viszonylag egyszerű kérdésre is kell válaszolni). A gyorsaság is fontos, ui. a legelső jól válaszoló (papíron adták be eddig) indokolhat, amiért pluszpont jár.

Tavaly újítottam: a szóbeli forduló online lett. Tanulói laptopok voltak a diákoknál, a saját laptopomon pedig követtem az eseményeket. A program elve: a saját laptopom a szerver. A tanulói laptopok néhány másodpercenként (javascript/jquery alapon) lekérdezik a szervert, hogy van-e új feladat (egy php-t hív meg). A szerveren én irányítom ("admin felület"), mikor kerül ki az új feladat.

A kérdésem, hogy ennél van-e normálisabb megoldás (és ha van, akkor mi lenne), esetleg valami kész, komplett megoldás.

Hozzászólások

Vannak vele tapasztalataid? Mennyire támogatott pl. a régi böngészőkben? (a tanulói laptopokon nem tudunk telepíteni, így ami azon van, azzal kell dolgozni - meg nem mondom, hanyas explorer, de a jquery-féle load se ment, ezért egy portable firefox-ot "telepítettem" mindegyikre)

Szerintem nem tetted jól, jó az a websocket :). Régebbi böngésző alatt mit értünk? Nálam XP+IE7 kategória ugrik be ennek hallatán, viszont még egy régi gépre is lehet új Chrome-ot pattintani, és máris van websocket támogatás. .NET világban SignalR a király, úgy tud pusht, hogy ha adott böngésző nem tud websocketet, akkor XHR-rel emulálja. Ha a PHP világban ilyen nincs, simán lehet nyers XHR-rel is pusholni (http://en.wikipedia.org/wiki/Comet_%28programming%29).
--

A gépekre nem tudok telepíteni, max. csak portable verziókat (rendszergazdai jogosultság hiánya).
Régebbi böngésző: a fene tudja, hanyas. A rendszer emlékeim szerint XP, de majd szerdán megnézem.

Ennyire sajnos nem vagyok képben (SingalR, XHR, stb.), nem főfoglalkozás a programozás :)

Pedig már használsz XHR-t, csak esetleg nem tudsz róla :). $.ajax = XHR, azaz XMLHttpRequest. A comet annyival tud többet ennél, hogy a kliens indít egy XHR-t, a szerver pedig nem válaszol azonnal, hanem vár valami történésre, és majd ha van mondanivalója, akkor küldi. Nagyon röviden egy lehetséges megvalósítás:

- Van egy szerver oldali állapot, ami pl. az utoljára kiadott feladat sorszáma, de más is lehet benne, ezt pl. tárolhatod adatbázisban vagy fájlban.
- A szerver tárolja az aktuális állapot verziószámát is, induljon pl. 1-től (ez nem azonos a feladat sorszámával, tágabban kell értelmezni). Tehát amikor bármi változik, pl. új feladat jelenik meg, vagy akármi, akkor növeled 1-el.
- Írsz egy AJAX kiszolgáló PHP scriptet, aminek bemenete egy verziószám, kimenete egy állapot. Működése: amint megjelenik az inputban kapottól egy újabb verziójú állapot, azt kiküldi, egyébként vár*. A válaszban benne van az állapot aktuális verziószáma is.
- Kliens oldalon induláskor kérsz egy állapotot 0 verzióval, magyarul a szerver nem vár, azonnal kiküldi a legfrissebb állapotot.
- Kliens oldalon minden egyes szervertől kapott válasz után indítasz egy XHR-t, amiben kéred a következő verziójú állapotot, és vársz. Ha ez timeout-ol, vagy bármi miatt megszakad, akkor újra, és újra.

Ennek az a nettó eredménye, hogy amikor változik az állapot a szerveren, azt a kliensek _azonnal_ megkapják. Hálózati gond, újraindulás, stb. sem akasztja meg a folyamatot.

A valódi probléma a *-gal jelzett rész a szerver oldalon. Tehát fut a tucatnyi PHP scripted, akár egy Apache processzben, akár többen is. Mindegyik vár valamire, de mire? Tipikusan valami IPC mechanizmus szokott kelleni, amivel ki tudsz küldeni sok várakozó szálnak egy üzenetet. Ha nincs ilyened, akkor ugyanott vagy, sleep-elni kell, és időnként újra lekérdezni, van-e frissülés, csak áttoltad ezt a feladatot szerver oldalra. A folyamatos kérdezgetés gyorsabb, lehet sűrűbben csinálni (pl. akár 0.01s), mert szerver oldalon vagy, nincs kliens-szerver kommunikáció, amivel kicsit javítottál a válaszidőn, már az is valami.

Chat alkalmazást is lehet így csinálni, csak egy apró csavar kell bele: a szerver nem csak az utolsó állapotot tárolja, hanem történetiséget kezelve az összeset. Pl. 1 üzenet = 1 állapotváltozás. Ha már jött 5 üzenet, és a kliens eddig 2-t látott, akkor kéri a szervertől a 2-nél frissebb cuccokat, ekkor sorban egymás után megkapja a 3-as, 4-es, 5-ös üzenetet is.

--