» »

[JAVA]pošiljanje sporočil vsem klientom pri non blocking serverju

[JAVA]pošiljanje sporočil vsem klientom pri non blocking serverju

Binji ::

Spravil sem se pisati non blocking server (za nalogo imam implementirati asinhrono komunikacijo) in imam ze eno vprasanje... namrec kako zagotovim, da bo neko sporocilo s serverja poslano vsem klientom?
Pri blokirajocem serverju bi preprosto vzel seznam klientov in v zanki poslal na vsakega to sporocilo. Kako pa to naredim pri blokirajocem? Se vedno v zanki in hkrati preverjam ali je key writable ali moram narediti cisto drugace?

Hvala!
Kdor ne navija ni Slovenc, hej, hej, hej!

morbo ::

Najprej rabiš Selector objekt, pri kateremu potem registriraš kanale za pisanje. Ko registriraš kanal pri selektorju, mu lahko prilepiš tudi nek atačment, ki ti služi kot handler, ki ga boš klical kadar preverjaš stanje kanala (ni pa nujno).
Selector selector = Selector.open();
channel.register(selector, SelectionKey.OP_WRITE, handler);

Potem v zanki izvedeš select(), pridobiš ključe ready kanalov in obdelaš tiste ki so readable.
selector.select();
Set<SelectionKey> kljuci = selector.selectedKeys();
Iterator<SelectionKey> iter = kljuci.iterator();

while (iter.hasNext()) {
     SelectionKey kljuc = iter.next();
     iter.remove(); // ključ je treba ročno odstranit iz seta!
     // pregledamo tudi če je ključ še veljaven (lahko se je
     // razveljavil med branjem -> v prim. zaprtja vtičnice)
     if (kljuc.isValid() && kljuc.isWritable()) {
          // tukaj nerediš nekaj s kanalom 
          SelectableChannel kanal = kljuc.channel();
          // oz. z njegovim attachmentom
          Handler h = kljuc.attachment();
     }
}

Tako iteriraš skozi vse kanale, ki si jih prijavil kot writable.

Zgodovina sprememb…

  • spremenil: morbo ()

Binji ::

hvala za odgovor, ampak kolikor vidim je tam samo napisano kdaj vidis, da lahko posiljas sporocilo na socket.
Kaj pa ko dobis sporocilo od klienta, ki bi ga potem rad poslal vsem ostalim klientom? Tukaj uporablja sezname in poseben thread za delo s podatki (vstavlja noter in caka, da bo kaj na razpolago) in pa za spreminjanje statusa socketa. Ampak kolikor vidim je delano tako, da dobi odgovor samo klient, ki je stvar poslal.
Kaj pa drugace? Kako lahko zagotovo iteriram med vsemi klienti, jim spremenim status na OP_WRITE in posljem neko sporocilo?
Kdor ne navija ni Slovenc, hej, hej, hej!

morbo ::

V bistvu rabiš dve niti - ena se ukvarja z izbiranjem ready kanalov in branjem prihajajočih ter pisanjem odhajajočih podatkov, druga te podatke obdeluje in jih postavlja v vrsto za pisanje v socket, ter prvi nalaga updejatnje WRITE statusa kanalov. Vse kliente imaš pa zbrane na nekem seznamu.

Štos pravilnega delovanja pa je da te dve niti komunicirata asinhrono. Recimo ko prva (ki bere in piše v socket) dobi nek paket, ga da v obdelavo tadrugi - ampak tako da doda neko opravilo na seznam opravil. Druga nit periodično pregleduje seznam, obdela zahtevke in ko so podatki pripravljeni, naloži spremembo interesta v OP_WRITE pri prvi niti. Primer takega komuniciranja je recimo EventQueue.invokeLater(new Runnable()), ko v aktivni niti registriraš nek Runnable proces, ki se pa bo začel izvajat v event dispatch niti, ob tebi neznanem času. Metoda invokeLater() ne čaka na začetek izvajanja procesa, ampak ga le prijavi (schedule) in takoj vrne. Seznam opravil mora bit seveda sinhroniziran.

private void invokeLater(Runnable task) {
        
        synchronized(tasks) {
            tasks.add(task);
        }
    }

Podatke vsem klientom pa pošlješ tako da iteriraš skozi vse predmete, ki predstavljajo nek klient (uporaba attachmenta pri registraciji kanala je kot nalašč za to) in vsem nastaviš interest na OP_WRITE. Še eno bistvo pravilnega delovanje je menjavanje interesta - v grobem je tako ko nekaj uspešno zapišeš v socket, menjaš interest na OP_READ, medtem ko OP_WRITE zahtevaš le takrat ko se neki podatki pripravljeni. Tako da kanal večino časa preživi na čakanju za branje. Seznam vseh klientov rabi le nit ki pripravlja podatke, tako da sinhronizacija ni potrebna.

Mnja, upam da je kaj bolj jasno... NIO je rahlo zafrknjen in jst ne ravno blestim v razlaganju... :P

Zgodovina sprememb…

  • spremenil: morbo ()

Binji ::

Spet jaz:D Mi je celo uspelo nekaj spraviti skupaj, ampak imam spet problem... Narejeno imam namrec tako, da ko se priklopita 2 uporabnika sprozi broadcast in poslje string uporabnikom, tam se pa to raztolmaci. Poslje pa vsakemu ob priklopu tudi svoj id.
Problem pa je, ker vsake toliko drugemi priklopljeni, namesto da bi imel 2 stringa (enega kot ukaz za dodelitev idja, drugi kot ukaz za zacetek), dobi kar 2 skupaj. Takole:
SET_CLIENT_ID 2RUN_GAME

Zdaj pa ne vem ali tle kak buffer zajebava ali kaj;( Ukaze doda v listo za poslat vse ok, potem pa ne vem kaj se zmestra...

edit: ce debugiram in grem po breakpointih dela lepo. Ce samo zalaufam pride zmeri do napake. Pa jst bom znoru...
Kdor ne navija ni Slovenc, hej, hej, hej!

Zgodovina sprememb…

  • spremenil: Binji ()

kopernik ::

Z debuggerjem je zelo težko najti napake, ki pridejo do izraza šele pri sočasnem izvajanju več niti. In seveda, sprogramirati pravilno in robustno paralelno izvajanje ni tako trivialno, zato priporočam ogled izvorne kode kakšne knjižnice, ki je preverjena iz strani veliko uporabnikov, npr. apache mina.

Binji ::

bom pogledal ceprav zaenkrat se tam nic ne znajdem.. Sem pa ugotovil, da klient na socket zapise ok, server pa prebere s socketa vec naenkrat.
Svasta? Sem poskusal z raznimi sinhronizacijami ampak zaenkrat nic ne zaleze...;(
Kdor ne navija ni Slovenc, hej, hej, hej!


Vredno ogleda ...

TemaSporočilaOglediZadnje sporočilo
TemaSporočilaOglediZadnje sporočilo
»

[Java] Multi Client chat server

Oddelek: Programiranje
262346 (1617) javaMaster
»

[Java] Preverjanje polja za iste stringe

Oddelek: Programiranje
81077 (955) infiniteLoop
»

[JAVA] zaustavitev niti (threadov)

Oddelek: Programiranje
223045 (3045) morbo
»

[NALOGA][JAVA]Vodoravni met

Oddelek: Programiranje
112604 (2293) BCSman
»

[JAVA] rekurzivni izpis seznama z kazalci

Oddelek: Programiranje
151653 (1411) l0g1t3ch

Več podobnih tem