Skrabák Csaba QXH4PC Linux programozás házi feladat Tömör dokumentáció Feladat ~~~~~~~ Server megvalósítása Linuxon C++-ban egy coco nevű protokollhoz, ami a saját agyrémem. Lejjebb van a leírása. Változások a specifikáció óta ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Az egész TCP felett működik, mert nagyon fontos a sorrendtartás és a megbízhatóság is. Ráadásul UDP esetén előfordulhat, hogy rossz szándékú felhasználók más nevében küldenek csomagokat, és ez a szerver oldalán már nem látszik. TCP esetén nem tudja két különböző processz ugyanazt a kapcsolatot használni. Fordítás ~~~~~~~~ A forrás egyetlen fájl: g++ -ococosvr cocosvr.cpp * Befolyásolni lehet makrók definiálásával: -DSESS_MAX= - ennyi egyidejű csatlakozást fogad el a szerver legfeljebb -DDEBUG - debug üzeneteket is kiír -DDEBUG_MORE - részletesebb debug üzeneteket is kiír -DQUIET - normál üzenetek kiírását sem kérjük Tesztelés ~~~~~~~~~ Érdemes kipróbálni, hogy elindítunk sok CocoClient alkalmazást, miközben a szerver fut. Ezeknek a címsorát leenterezzük, erre becsatlakoznak a szerverre, és megjelenítik a tesztoldalt. A tesztoldalon lesz egy Increment gomb, bármelyik kliensen nyomjuk meg, mindegyikre hatni fog. A kliens jelenlegi változata nem tud minden funkciót kihasználni. Telnettel is érdemes tesztelni: telnet localhost 7061 Például ki lehet próbálni a letöltést: DOWNLOAD index.cjd Illetve azt, hogy több klienssel csatlakozunk, majd azokkal különböző oldalt figyelünk: WATCH Ennek az lesz az eredménye, hogy ha két kliensnél ugyanazt a bármit írtuk be, akkor azok ugyanazt az oldalt figyelik. Ezt is lehet tesztelni úgy, hogy az egyikkel megváltoztatjuk az oldalt, és nézzük, hogy a másik megkapja-e az értesítést erről: REFRESH Normális esetben a küldővel azonos oldalt figyelő klienseknél megjelenik a REFRESH , míg a többinél nem. A protokoll ~~~~~~~~~~~ Lényege, hogy egy szerverhez kliensek csatlakoznak nagy számban, és azok figyelni kívánják a szerveren tárolt oldalak valamelyikét. Eddig a http-re hasonlít a dolog. Miután letöltötték a tartalmát, egyrészt parancsok által meg tudják változtatni az oldalak bizonyos részeit (pl. egy számlálót növelhetnek, vagy egy chat log végére írhatnak). A változásokról minden olyan kliens értesül, amelyik ugyanezt az oldalt figyeli, a többi nem. Így a kliensprogram képes arra, hogy a megjelenített oldal kövesse a változást, és minden kliensnél pillanatról pillanatra azonosan fog kinézni az oldal. Így lehet pl. chatelni is. Itt az összes lehetséges üzenet, a tipikus sorrendben: szerver: 'HELLO ' - csatlakozás visszaigazolása, vagy... szerver: 'FULL' - csatlakozás visszautasítva, a szerver túlterhelt kliens: 'VERSION ' - a kliensnek megvan a cache-ben az oldal, de nem akar fájlnév alapján ítélni; ellenőrzi, hogy azonos-e a verziószám, és ha nem, újra le kell tölteni az oldalt szerver: 'VERSION ' - válaszol a kliens kérdésére kliens: 'DOWNLOAD ' - szerveren tárolt fájl, pl. oldal letöltése szerver: 'FILE ' - letöltés következik kliens: 'WATCH ' - figyelni akarja az adott oldalt, azaz a kliens mostantól szeretné megkapni az oldal változásairól az értesítéseket szerver: 'REGISTERED' - visszaigazolja a WATCH kérés teljesítését kliens: 'REFRESH ' - a kliens meg akarja változtatni az oldal valamelyik részét. A parancsot magát az oldal saját hatáskörben értelmezi szerver: 'REFRESH ' - értesíti a klienst, hogy az általa figyelt oldalt valamelyik nézője (pl. ő maga) megváltoztatta kliens: 'LEAVE' - megkéri a szervert, hogy bontsa a kapcsolatot Minden üzenetet soremelés karakter zár, minden ASCII-ben van, a szóközök 0x20 karakterek, nincs szóköztöbbszörözés, nincs üres hely sem a stringek elején, sem a végükön. A soremelés lehet UNIX-féle ("\n") is, DOS stílusú ("\r\n") is. Megvalósítás ~~~~~~~~~~~~ Letöltés: kérés beérkezése után fork() hívás történik, a gyerekfolyamat letölti a kért fájlt, hogy nagy méretű fájlok lassú átvitele esetén a többi kliens kiszolgálása ne késlekedjen. Egyéb funkciók: egyszálú szerver, select() hívással oldom meg, hogy több kliensre egyszerre figyel. Ez meg azért kell, mert nagyon sok olyan változó van, amit többszálú megoldás esetén megosztva kellene kezelni, és dinamikusan nő a közös terület.