Programiranje

Izdelava sistema internetnega klepeta

Morda ste že videli enega od številnih sistemov za klepet na Javi, ki so se pojavili v spletu. Po branju tega članka boste razumeli, kako delujejo - in vedeli, kako zgraditi svoj preprost sistem za klepet.

Ta preprost primer sistema odjemalca / strežnika je namenjen predstavitvi, kako graditi aplikacije z uporabo samo tokov, ki so na voljo v standardnem API-ju. Klepet za komunikacijo uporablja vtičnice TCP / IP in ga je mogoče enostavno vdelati v spletno stran. Za referenco nudimo stransko vrstico, ki razlaga komponente programskega omrežja Java, ki so pomembne za to aplikacijo. Če še vedno pospešujete, si najprej oglejte stransko vrstico. Če pa že dobro obvladate Javo, lahko skočite naravnost in se preprosto sklicujete na stransko vrstico.

Izdelava odjemalca za klepet

Začnemo s preprostim grafičnim odjemalcem za klepet. Za povezavo potrebujete dva parametra ukazne vrstice - ime strežnika in številko vrat. Vzpostavi povezavo z vtičnico in nato odpre okno z velikim izhodnim območjem in majhnim vhodnim območjem.

Vmesnik ChatClient

Ko uporabnik vnese besedilo v območje vnosa in pritisne tipko Return, se besedilo prenese na strežnik. Strežnik odmeva vse, kar pošlje odjemalec. Naročnik prikaže vse, kar je prejel od strežnika v izhodni regiji. Ko se več odjemalcev poveže z enim strežnikom, imamo preprost sistem za klepet.

Class ChatClient

Ta razred izvaja odjemalca za klepet, kot je opisano. To vključuje nastavitev osnovnega uporabniškega vmesnika, ravnanje z interakcijo uporabnika in prejemanje sporočil s strežnika.

uvoz java.net. *; uvoz java.io. *; uvoz java.awt. *; javni razred ChatClient razširja Frame implementira Runnable {// javni ChatClient (naslov niza, InputStream i, OutputStream o) ... // public void run () ... // javni logični handleEvent (Event e) ... // javni static void main (String args []) vrže IOException ...} 

The ChatClient razred se razširi Okvir; to je značilno za grafično aplikacijo. Izvajamo Teče vmesnik, da lahko začnemo Navoj ki sprejema sporočila s strežnika. Konstruktor izvede osnovno nastavitev grafičnega uporabniškega vmesnika, teči () metoda prejema sporočila s strežnika, handleEvent () metoda obravnava interakcijo uporabnika in glavni () metoda izvede začetno omrežno povezavo.

 zaščiten DataInputStream i; zaščiten DataOutputStream o; zaščiten izhod TextArea; zaščiten vnos TextField; zaščiten poslušalec niti; javni ChatClient (naslov niza, InputStream i, OutputStream o) {super (naslov); this.i = new DataInputStream (new BufferedInputStream (i)); this.o = nov DataOutputStream (nov BufferedOutputStream (o)); setLayout (novo BorderLayout ()); add ("Center", output = new TextArea ()); output.setEditable (false); add ("South", input = new TextField ()); paket (); show (); input.requestFocus (); poslušalec = nova nit (ta); listener.start (); } 

Konstruktor ima tri parametre: naslov okna, vhodni tok in izhodni tok. The ChatClient komunicira prek določenih tokov; ustvarjamo medpomnilniške tokove podatkov i in o, da zagotovimo učinkovite komunikacijske zmogljivosti na višji ravni prek teh tokov. Nato nastavimo naš preprost uporabniški vmesnik, sestavljen iz TextArea proizvodnja in TextField vhod. Postavimo in pokažemo okno ter zaženemo a Navoj poslušalec, ki sprejema sporočila s strežnika.

public void run () {try {while (true) {String line = i.readUTF (); output.appendText (vrstica + "\ n"); }} catch (IOException ex) {ex.printStackTrace (); } končno {poslušalec = null; input.hide (); potrdi (); poskusite {o.close (); } catch (IOException ex) {ex.printStackTrace (); }}} 

Ko nit poslušalca vstopi v način izvajanja, sedimo v neskončno branje zanke Vrvicas iz vhodnega toka. Ko a Vrvica prispe, ga dodamo izhodnemu območju in ponovimo zanko. An IOException lahko pride do izgube povezave s strežnikom. V tem primeru natisnemo izjemo in izvedemo čiščenje. Upoštevajte, da bo to označeno z EOFException Iz readUTF () metoda.

Za čiščenje najprej dodelimo referenco poslušalcu Navoj do nič; to pomeni preostali kodi, da je nit končana. Nato skrijemo vnosno polje in pokličemo potrdi () tako da je vmesnik spet postavljen, in zaprite Izhodni tok o zagotoviti, da je povezava zaprta.

Upoštevajte, da vsa čiščenja izvajamo v a končno klavzulo, zato se bo to zgodilo, če IOException se zgodi tukaj ali pa se nit prisilno ustavi. Okna ne zapremo takoj; domneva se, da bo uporabnik morda želel prebrati sejo tudi po prekinitvi povezave.

javni logični handleEvent (dogodek e) {if ((e.target == input) && (e.id == Event.ACTION_EVENT)) {try {o.writeUTF ((String) e.arg); o.flush (); } catch (IOException ex) {ex.printStackTrace (); listener.stop (); } input.setText (""); vrni res; } else if ((e.target == this) && (e.id == Event.WINDOW_DESTROY)) {if (poslušalec! = null) listener.stop (); skrij (); vrni res; } vrnitev super.handleEvent (e); } 

V handleEvent () , moramo preveriti dva pomembna dogodka uporabniškega vmesnika:

Prvi je akcijski dogodek v TextField, kar pomeni, da je uporabnik pritisnil tipko Return. Ko ujamemo ta dogodek, zapišemo sporočilo v izhodni tok, nato pokličemo flush () da se zagotovi, da se pošlje takoj. Izhodni tok je DataOutputStream, tako da lahko uporabimo writeUTF () poslati a Vrvica. Če je IOException zgodi se, da povezava ni uspela, zato ustavimo nit poslušalca; to bo samodejno izvedlo vsa potrebna čiščenja.

Drugi dogodek je uporabnik, ki poskuša zapreti okno. Programer mora poskrbeti za to nalogo; ustavimo nit poslušalca in skrijemo Okvir.

public static void main (String args []) vrže IOException {if (args.length! = 2) vrže nov RuntimeException ("Sintaksa: ChatClient"); Vtičnica s = nova vtičnica (args [0], Integer.parseInt (args [1])); nov ChatClient ("Klepet" + args [0] + ":" + args [1], s.getInputStream (), s.getOutputStream ()); } 

The glavni () metoda zažene odjemalca; če zagotovimo pravilno število argumentov, odpremo a Vtičnica na določeni gostitelj in vrata, in ustvarimo ChatClient priključen na tokove vtičnice. Ustvarjanje vtičnice lahko povzroči izjemo, ki bo zapustila to metodo in bo prikazana.

Izdelava večnitnega strežnika

Zdaj razvijamo klepetalniški strežnik, ki lahko sprejme več povezav in ki bo predvajal vse, kar bere od katere koli stranke. Branje in pisanje je težko Vrvicas v obliki UTF.

V tem programu sta dva razreda: glavni razred, ChatServer, je strežnik, ki sprejema povezave odjemalcev in jih dodeli novim objektom za obdelavo povezav. The ChatHandler class dejansko opravlja poslušanje sporočil in njihovo oddajanje vsem povezanim odjemalcem. Ena nit (glavna nit) obravnava nove povezave, obstaja pa nit ( ChatHandler razred) za vsako stranko.

Vsako novo ChatClient se bo povezal z ChatServer; to ChatServer bo izročil povezavo novemu primerku ChatHandler razred, ki bo prejemal sporočila od novega odjemalca. Znotraj ChatHandler razred, se vodi seznam trenutnih upravljavcev; oddaja () metoda uporablja ta seznam za pošiljanje sporočila vsem povezanim ChatClients.

Class ChatServer

Ta razred se ukvarja s sprejemanjem povezav od odjemalcev in lansiranjem niti obdelave za njihovo obdelavo.

uvoz java.net. *; uvoz java.io. *; uvoz java.util. *; javni razred ChatServer {// javni ChatServer (int port) vrže IOException ... // javni statični void main (String args []) vrže IOException ...} 

Ta razred je preprosta samostojna aplikacija. Dobavimo konstruktor, ki opravi vsa dejanska dela za razred, in a glavni () metoda, ki jo dejansko zažene.

 javni ChatServer (int port) vrže IOException {ServerSocket server = new ServerSocket (port); while (true) {Odjemalec vtičnice = server.accept (); System.out.println ("Sprejeto iz" + client.getInetAddress ()); ChatHandler c = nov ChatHandler (odjemalec); c.start (); }} 

Ta konstruktor, ki izvaja vsa dela strežnika, je dokaj preprost. Ustvarimo a ServerSocket in nato sedite v zanki in sprejemate stranke z sprejme () metoda ServerSocket. Za vsako povezavo ustvarimo nov primerek datoteke ChatHandler razred, mimo novega Vtičnica kot parameter. Ko smo ustvarili ta vodnik, ga začnemo s svojim začetek () metoda. S tem se zažene nova nit za obdelavo povezave, tako da lahko naša glavna strežniška zanka še naprej čaka na nove povezave.

public static void main (String args []) vrže IOException {if (args.length! = 1) vrže nov RuntimeException ("Sintaksa: ChatServer"); novi ChatServer (Integer.parseInt (args [0])); } 

The glavni () metoda ustvari primerek datoteke ChatServer, kot parameter posreduje vrata ukazne vrstice. To so vrata, na katera se bodo stranke povezale.

Razred ChatHandler

Ta razred se ukvarja z obdelavo posameznih povezav. Od stranke moramo prejeti sporočila in jih ponovno poslati vsem ostalim povezavam. Vzdržujemo seznam povezav v a

statično

Vektor.

uvoz java.net. *; uvoz java.io. *; uvoz java.util. *; javni razred ChatHandler razširi nit {// javni ChatHandler (vtičnice) vrže IOException ... // public void run () ...} 

Podaljšujemo Navoj razred, da dovoli ločeni niti za obdelavo povezanega odjemalca. Konstruktor sprejme a Vtičnica na katero se vežemo; teči () metoda, ki jo pokliče nova nit, izvede dejansko obdelavo odjemalca.

 zaščitena vtičnica s; zaščiten DataInputStream i; zaščiten DataOutputStream o; javni ChatHandler (vtičnice) vrže IOException {this.s = s; i = nov DataInputStream (nov BufferedInputStream (s.getInputStream ())); o = nov DataOutputStream (nov BufferedOutputStream (s.getOutputStream ())); } 

Konstruktor ohrani sklic na vtičnico odjemalca in odpre vhodni in izhodni tok. Spet uporabljamo medpomnilniške tokove podatkov; ti nam zagotavljajo učinkovite V / I in metode za sporočanje podatkovnih vrst na visoki ravni - v tem primeru Vrvicas.

zaščiteni statični obdelovalci vektorjev = new Vector (); javna void run () {try {handlers.addElement (this); while (true) {String msg = i.readUTF (); oddajanje (sporočilo); }} catch (IOException ex) {ex.printStackTrace (); } končno {handlers.removeElement (this); poskusite {s.close (); } catch (IOException ex) {ex.printStackTrace (); }}} // zaščitena statična void oddaja (sporočilo v nizu) ... 

The teči () metoda vstopi v naš nit. Najprej dodamo svojo nit v Vektor od ChatHandlervodniki. Vodniki Vektor vodi seznam vseh trenutnih upravljavcev. Je statično spremenljivka in tako obstaja en primerek Vektor za celoto ChatHandler razreda in vseh njegovih primerov. Tako vsi ChatHandlerlahko dostopate do seznama trenutnih povezav.

Upoštevajte, da je za nas zelo pomembno, da se kasneje odstranimo s tega seznama, če naša povezava ne uspe; v nasprotnem primeru nam bodo vsi drugi upravljavci poskušali pisati, ko bodo oddajali informacije. Ta vrsta primerov, kjer je nujno, da se dejanje izvede po zaključku dela kode, je glavna uporaba poskusite ... končno konstruirati; zato vse svoje delo opravljamo v okviru poskusite ... ulovite ... končno konstruirati.

Telo te metode prejme sporočila od odjemalca in jih znova pošlje vsem ostalim odjemalcem, ki uporabljajo oddaja () metoda. Ko zanka izstopi, bodisi zaradi branja izjeme od odjemalca bodisi zaradi zaustavitve te niti, se končno klavzula zagotovljena za izvedbo. V tem stavku odstranimo svojo nit s seznama upravljavcev in zapremo vtičnico.

zaščitena statična void oddaja (sporočilo v nizu) {sinhronizirano (handlers) {Enumeration e = handlers.elements (); while (e.hasMoreElements ()) {ChatHandler c = (ChatHandler) e.nextElement (); poskusite {sinhronizirano (c.o) {c.o.writeUTF (sporočilo); } c.o.flush (); } ulov (IOException ex) {c.stop (); }}}} 

Ta metoda pošilja sporočilo vsem strankam. Najprej sinhroniziramo na seznamu upravljavcev. Nočemo, da se ljudje pridružijo ali odidejo, medtem ko zapeljemo, če poskušamo oddajati komu, ki ne obstaja več; to prisili stranke, da počakajo, da končamo s sinhronizacijo. Če mora strežnik prenašati posebej velike obremenitve, bomo morda zagotovili bolj natančno sinhronizacijo.

V tem sinhroniziranem bloku dobimo Naštevanje sedanjih upravljavcev. The Naštevanje class ponuja priročen način za ponavljanje vseh elementov a Vektor. Naša zanka preprosto zapiše sporočilo v vsak element datoteke Naštevanje. Upoštevajte, da če pride do izjeme med pisanjem v ChatClient, nato pokličemo strankino stop () metoda; to ustavi naročnikovo nit in zato izvede ustrezno čiščenje, vključno z odstranjevanjem odjemalca iz upravljavcev.

$config[zx-auto] not found$config[zx-overlay] not found