Primjer implementacije tekstualnog razgovora u stvarnom vremenu s bibliotekom SignalR
Autor: Denis Balant, Enej Hudobreznik
HTTP (Hypertext Transfer Protocol) protokol još uvijek se primarno koristi za prijenos podataka preko Interneta. njegov moderniji i sigurniji šifrirani derivat HTTPS (HTTP Secure). Temelje se na arhitekturi klijent-poslužitelj, gdje klijent (engleski client) šalje zahtjev (engleski HTTP request) poslužitelju (engleski Server), a poslužitelj na njega odgovara odgovorom (engleski HTTP response).
HTTP i HTTPS protokoli prikladni su za jednostavne prijenose zahtjev-odgovor (npr. prijenos HTML datoteke na zahtjev klijenta). Korištenjem ova dva protokola korisnik može dobiti ažurirane podatke tek kada pošalje novi zahtjev, stoga oni nisu najprikladniji za prijenos podataka u stvarnom vremenu (npr. online chat, online video igre, praćenje lokacije... ), na kojem velik dio funkcionalnosti modernih web aplikacija temelji se. Agilnost se može implementirati na mnogo različitih i boljih načina, svaki sa svojim prednostima i nedostacima.
Najjednostavniji način implementacije je redovno prozivanje, gdje klijent u svakom intervalu prozivanja poslužitelju više puta šalje zahtjeve za novim podacima, bez obzira je li se sadržaj uopće promijenio. Unatoč jednostavnosti, ovaj pristup nije prikladan za veće servise gdje je za pristup serveru potreban veliki broj klijenata, jer ga velika količina nepotrebnih i ponavljanih zahtjeva može preopteretiti i time usporiti rad servisa.
Poboljšanje je postignuto uvođenjem dugotrajnog anketiranja, gdje klijent na isti način šalje zahtjeve poslužitelju, ali poslužitelj na njih ne odgovara dok ne detektira prisutnost novih podataka. Nedostatak ovakvog pristupa je što klijent mora imati definiran određeni vremenski interval nakon kojeg neaktivnost poslužitelja prepoznaje kao grešku. To dodaje dodatnu razinu složenosti postavljanju klijenta i poslužitelja.
Moderni HTML5 standard također nudi API koji se zove Server-Sent Events. To je protokol u kojem klijent ne mora povremeno slati zahtjeve poslužitelju, već poslužitelj ponovno šalje potrebne podatke kada se naprave promjene, čime se olakšava komunikacija u stvarnom vremenu.
Standard HTML5 nudi i protokol WebSockets, koji omogućuje pravu dvosmjernu komunikaciju u stvarnom vremenu. Na početku uspostave provodi se rukovanje, gdje se klijent i poslužitelj dogovaraju oko standarda koje će koristiti. Nakon uspješnog rukovanja, između dva sudionika se otvara trajna veza s malom odgodom. Ovaj protokol je posebno koristan kada se radi o vezi od točke do točke (izravna veza između klijenta i poslužitelja).
Osim klasične klijent-poslužiteljske arhitekture, postoje i druga rješenja gdje veza između klijenata ne teče preko poslužitelja, već izravno između klijenata koji igraju ulogu i klijenta i poslužitelja (ove peer-to-peer mreže). Popularan protokol za komunikaciju u stvarnom vremenu u takvim mrežama je WebRTC.
U .NET okruženju za komunikaciju u stvarnom vremenu možemo koristiti biblioteku otvorenog koda SignalR, koja je dio web okvira ASP.NET Core, pa ju je lako dodati postojećim projektima kao dodatnu razinu međuprograma kada obrada dolaznih zahtjeva. Knjižnica simulira pozive metoda na klijentu sa strane poslužitelja i pozive metoda na poslužitelju sa strane klijenta (Remote Procedure Call - RPC), ali ne jamči prikladnost br. parametri i njihove vrste. S poslužitelja možemo pozivati metode na svim klijentima, na određenoj grupi klijenata ili samo na jednom klijentu.
Njegova glavna prednost je jednostavnost implementacije zahvaljujući paketima za razvoj softvera (SDK) za mnoge različite platforme, koji skrivaju unutarnje funkcioniranje usluge od programera, te mogućnost jednostavnog hostinga uz uslugu Azure SignalR. Dodatna prednost je što usluga sama odabire najprikladniju vrstu veze (gore opisanu) između klijenta i poslužitelja.
Korištenje biblioteke temelji se na posebnim klasama zvanim hubovi, koje predstavljaju apstrakciju veze između klijenata i poslužitelja. Za njih definiramo metode koje klijenti mogu pozivati na poslužitelju.
Primjer u nastavku prikazuje primjer jednostavne implementacije tekstualnog razgovora. Prvo, definiramo osnovni čvor za razgovor na poslužitelju. Metode ove klase predstavljaju metode koje mogu pozivati klijenti na poslužitelju. Kada se pozove metoda SendMessage, klijent šalje ID korisnika (userId) i sadržaj poruke (message), dok poslužitelj poziva metodu ReceiveMessage na svim klijentima sa zadanim parametrima.
Primjer u nastavku prikazuje implementaciju JavaScript web klijenta pomoću službene biblioteke (@microsoft/signalr). Klijenti se povezuju na URL čvora (/chat u donjem primjeru). Veza je predstavljena objektom veze. Metoda on predstavlja slušatelja poziva metode, čiji je naziv zadan kao prvi parametar, a kao drugi funkcija koja se izvršava na događaj. Implementiramo metode na poslužitelju kroz invoke metodu objekta veze, koja zahtijeva ime metode kao prvi argument, nakon čega slijede njezini parametri.
Prema zadanim postavkama, podaci se prenose između poslužitelja i klijenata u JSON formatu, ali biblioteka podržava i učinkovitiji format MessagePack.
Iako knjižnica uvelike olakšava razvoj, ona ima svoje nedostatke. Jedan od glavnih je skalabilnost sustava za samostalno hosting i osiguravanje neprekidnog rada, budući da je njegovu implementaciju vrlo teško distribuirati na nekoliko zasebnih poslužitelja. To se pokazalo posebno teškim ako želimo smanjiti kašnjenje za udaljene korisnike i hostirati na nekoliko različitih lokacija, jer je dizajn rješenja ograničen na samo jednu. Također, knjižnica ne osigurava pouzdanu dostavu i naručivanje poruka, što može degradirati korisničko iskustvo.