Programmēšana

Interneta tērzēšanas sistēmas izveide

Iespējams, esat redzējis vienu no daudzajām Java balstītajām tērzēšanas sistēmām, kas parādījās tīmeklī. Pēc šī raksta izlasīšanas jūs sapratīsit, kā viņi darbojas, un zināsit, kā izveidot vienkāršu savu tērzēšanas sistēmu.

Šis vienkāršais klienta / servera sistēmas piemērs ir paredzēts, lai parādītu, kā veidot lietojumprogrammas, izmantojot tikai standarta API pieejamās straumes. Tērzēšanā saziņai tiek izmantotas TCP / IP ligzdas, un to var viegli iegult Web lapā. Atsauces nolūkā mēs nodrošinām sānjoslu, kurā paskaidroti Java tīkla programmēšanas komponenti, kas ir svarīgi šai lietojumprogrammai. Ja jūs joprojām esat ātrumā, vispirms ieskatieties sānjoslā. Tomēr, ja jūs jau labi pārzināt Java valodu, jūs varat uzreiz pāriet un vienkārši atsaukties uz sānjoslu.

Tērzēšanas klienta veidošana

Mēs sākam ar vienkāršu grafisko tērzēšanas klientu. Lai izveidotu savienojumu, nepieciešami divi komandrindas parametri - servera nosaukums un porta numurs. Tas izveido kontaktligzdas savienojumu un pēc tam atver logu ar lielu izvades un mazu ievades reģionu.

ChatClient saskarne

Pēc tam, kad lietotājs ievada tekstu ievades reģionā un nospiež Return, teksts tiek pārsūtīts uz serveri. Serveris atkārto visu, ko sūta klients. Klients parāda visu, kas saņemts no servera izvades reģionā. Kad vairāki klienti izveido savienojumu ar vienu serveri, mums ir vienkārša tērzēšanas sistēma.

Klases tērzēšanas klients

Šī klase ievieš tērzēšanas klientu, kā aprakstīts. Tas ietver pamata lietotāja saskarnes iestatīšanu, lietotāja mijiedarbības apstrādi un ziņojumu saņemšanu no servera.

importēt java.net. *; importēt java.io. *; importēt java.awt. *; publiskā klase ChatClient paplašina rāmja ieviešanas iespējas Runnable {// public ChatClient (virknes nosaukums, InputStream i, OutputStream o) ... // public void run () ... // public boolean handleEvent (Event e) ... // public static void main (String args []) met IOException ...} 

The ChatClient klase pagarinās Rāmis; tas ir raksturīgi grafiskai lietošanai. Mēs īstenojam Skrienams interfeisu, lai mēs varētu sākt a Vītne kas saņem ziņojumus no servera. Konstruktors veic GUI pamata iestatīšanu palaist () metode saņem ziņojumus no servera, handleEvent () metode apstrādā lietotāja mijiedarbību, un galvenais () metode veic sākotnējo tīkla savienojumu.

 aizsargāta DataInputStream i; aizsargāta DataOutputStream o; aizsargāta TextArea izeja; aizsargāta TextField ievade; aizsargāts pavedienu klausītājs; publiskais ChatClient (virknes nosaukums, InputStream i, OutputStream o) {super (nosaukums); this.i = jauns DataInputStream (jauns BufferedInputStream (i)); this.o = new DataOutputStream (jauns BufferedOutputStream (o)); setLayout (jauns BorderLayout ()); add ("Center", output = new TextArea ()); output.setEditable (false); pievienot ("Dienvidi", ievade = jauns TextField ()); komplekts (); izrāde (); ievade.requestFocus (); klausītājs = new Thread (šī); klausītājs.sākt (); } 

Konstruktors ņem trīs parametrus: loga nosaukumu, ievades straumi un izvades plūsmu. The ChatClient sazinās pa norādītajām straumēm; mēs izveidojam buferētas datu plūsmas i un o, lai nodrošinātu efektīvas augstāka līmeņa komunikācijas iespējas pār šīm straumēm. Pēc tam mēs izveidojām mūsu vienkāršo lietotāja saskarni, kas sastāv no TextArea produkcija un Teksta lauks ievade. Mēs izkārtojam un parādām logu un sākam a Vītne klausītājs, kas pieņem ziņojumus no servera.

public void run () {try {while (true) {String line = i.readUTF (); output.appendText (rinda + "\ n"); }} catch (IOException ex) {ex.printStackTrace (); } beidzot {klausītājs = null; ievade.slēpt (); apstiprināt (); mēģiniet {o.close (); } catch (IOException ex) {ex.printStackTrace (); }}} 

Kad klausītāja pavediens nonāk palaišanas metodē, mēs sēžam bezgalīgā cikla lasījumā Stīgas no ievades straumes. Kad Stīga pienāk, mēs pievienojam to izejas reģionam un atkārtojam cilpu. An IOException var rasties, ja ir zaudēts savienojums ar serveri. Šajā gadījumā mēs izdrukājam izņēmumu un veicam tīrīšanu. Ņemiet vērā, ka par to ziņos EOFException no readUTF () metodi.

Lai sakoptu, vispirms tam piešķiram klausītāja atsauci Vītne uz nulle; tas pārējam kodam norāda, ka pavediens ir pārtraukts. Pēc tam mēs slēpjam ievades lauku un zvanām apstiprināt () tā, lai saskarne būtu atkal izkārtota, un aizveriet OutputStream o lai nodrošinātu savienojuma slēgšanu.

Ņemiet vērā, ka mēs veicam visu tīrīšanu a beidzot klauzulu, tāpēc tas notiks, ja IOException šeit notiek vai pavediens tiek piespiedu kārtā pārtraukts. Mēs nekavējoties neaizveram logu; tiek pieņemts, ka lietotājs var vēlēties lasīt sesiju pat pēc savienojuma zaudēšanas.

public boolean handleEvent (notikums e) {if ((e.target == ievade) && (e.id == Event.ACTION_EVENT)) {mēģiniet {o.writeUTF ((virkne) e.arg); o.skalot (); } catch (IOException ex) {ex.printStackTrace (); klausītājs.stop (); } input.setText (""); atgriezties taisnība; } else if ((e.target == šis) && (e.id == Notikums.WINDOW_DESTROY)) {if (klausītājs! = null) klausītājs.stop (); slēpt (); atgriezties taisnība; } atgriešanās super.handleEvent (e); } 

Iekš handleEvent () metodi, mums jāpārbauda divi nozīmīgi lietotāja saskarnes notikumi:

Pirmais ir darbības notikums TextField, kas nozīmē, ka lietotājs ir nospiedis Return taustiņu. Kad mēs noķeram šo notikumu, mēs ierakstām ziņojumu izvades straumē, pēc tam piezvanām noskalot () lai tā tiktu nekavējoties nosūtīta. Izejas plūsma ir a DataOutputStream, lai mēs varētu izmantot writeUTF () nosūtīt a Stīga. Ja an IOException notiek savienojums, iespējams, nav izdevies, tāpēc mēs pārtraucam klausītāja pavedienu; tas automātiski veiks visu nepieciešamo tīrīšanu.

Otrais notikums ir lietotājs, kurš mēģina aizvērt logu. Programmētāja ziņā ir rūpēties par šo uzdevumu; mēs pārtraucam klausītāja pavedienu un paslēpjam Rāmis.

public static void main (String args []) iemet IOException {if (args.length! = 2) mest jaunu RuntimeException ("Sintakse: ChatClient"); Socket s = jauns Socket (args [0], Integer.parseInt (args [1])); jauns ChatClient ("Chat" + args [0] + ":" + args [1], s.getInputStream (), s.getOutputStream ()); } 

The galvenais () metode palaiž klientu; mēs nodrošinām, ka ir iesniegts pareizs argumentu skaits, mēs atveram a Kontaktligzda uz norādīto resursdatoru un portu, un mēs izveidojam a ChatClient savienots ar kontaktligzdas straumēm. Izveidojot kontaktligzdu, var rasties izņēmums, kas izies no šīs metodes un tiks parādīts.

Vairāku pavedienu servera izveide

Tagad mēs izstrādājam tērzēšanas serveri, kas var pieņemt vairākus savienojumus un pārraidīs visu, ko tas lasīs no jebkura klienta. Tas ir vadīts, lai lasītu un rakstītu Stīgas UTF formātā.

Šajā programmā ir divas klases: galvenā klase, ChatServer, ir serveris, kas pieņem savienojumus no klientiem un piešķir tos jauniem savienojumu apstrādes objektiem. The ChatHandler klase faktiski veic ziņojumu noklausīšanos un to pārraidīšanu visiem saistītajiem klientiem. Viens pavediens (galvenais pavediens) apstrādā jaunus savienojumus, un ir pavediens ( ChatHandler klase) katram klientam.

Katrs jauns ChatClient izveidos savienojumu ar ChatServer; šo ChatServer nodos savienojumu ar jaunu ChatHandler klase, kas saņems ziņojumus no jaunā klienta. Ietvaros ChatHandler klasē tiek saglabāts pašreizējo apstrādātāju saraksts; apraide () metode izmanto šo sarakstu, lai pārsūtītu ziņojumu visiem savienotajiem ChatClients.

Klases tērzēšanas serveris

Šī klase ir saistīta ar klientu savienojumu pieņemšanu un apstrādātāju pavedienu palaišanu, lai tos apstrādātu.

importēt java.net. *; importēt java.io. *; importēt java.util. *; public class ChatServer {// public ChatServer (int port) izmet IOException ... // public static void main (String args []) throws IOException ...} 

Šī klase ir vienkārša atsevišķa lietojumprogramma. Mēs piegādājam konstruktoru, kurš klasē veic visu faktisko darbu, un a galvenais () metode, kas to faktiski sāk.

 publiskais ChatServer (int ports) izmet IOException {ServerSocket server = new ServerSocket (ports); while (true) {Socket klients = serveris.accept (); System.out.println ("Pieņemts no" + client.getInetAddress ()); ChatHandler c = jauns ChatHandler (klients); c. sākt (); }} 

Šis konstruktors, kas veic visu servera darbu, ir diezgan vienkāršs. Mēs izveidojam a ServerSocket un pēc tam sēdēt cilpā, pieņemot klientus ar pieņemt () metode ServerSocket. Katram savienojumam mēs izveidojam jaunu ChatHandler klasē, nokārtojot jauno Kontaktligzda kā parametru. Pēc šī apdarinātāja izveidošanas mēs to sākam ar to sākt() metodi. Tas sāk jaunu pavedienu, lai apstrādātu savienojumu, lai mūsu galvenā servera cilpa varētu turpināt gaidīt jaunus savienojumus.

public static void main (String args []) iemet IOException {if (args.length! = 1) mest jaunu RuntimeException ("Sintakse: ChatServer"); jauns ChatServer (Integer.parseInt (args [0])); } 

The galvenais () metode izveido ChatServer, pārejot komandrindas portu kā parametru. Šī ir osta, ar kuru klienti izveidos savienojumu.

Klase ChatHandler

Šī klase ir saistīta ar atsevišķu savienojumu apstrādi. Mums jāsaņem ziņojumi no klienta un tie jānosūta atkārtoti visiem citiem savienojumiem. Mēs uzturam savienojumu sarakstu a

statisks

Vector.

importēt java.net. *; importēt java.io. *; importēt java.util. *; publiskā klase ChatHandler paplašina pavedienu {// public ChatHandler (Socket s) izmet IOException ... // public void run () ...} 

Mēs pagarinām Vītne klasei, lai ļautu atsevišķam pavedienam apstrādāt saistīto klientu. Konstruktors pieņem a Kontaktligzda kurai mēs piestiprināmies; palaist () metode, ko sauc par jauno pavedienu, veic faktisko klienta apstrādi.

 aizsargātas kontaktligzdas; aizsargāta DataInputStream i; aizsargāta DataOutputStream o; publiskais ChatHandler (Socket s) iemet IOException {this.s = s; i = jauns DataInputStream (jauns BufferedInputStream (s.getInputStream ())); o = new DataOutputStream (jauns BufferedOutputStream (s.getOutputStream ())); } 

Konstruktors saglabā atsauci uz klienta kontaktligzdu un atver ieejas un izvades plūsmu. Atkal mēs izmantojam buferētas datu plūsmas; tie mums nodrošina efektīvu I / O un metodes augsta līmeņa datu tipu saziņai - šajā gadījumā Stīgas.

aizsargāti statisko vektoru apstrādātāji = new Vector (); public void run () {try {handlers.addElement (this); while (patiess) {String msg = i.readUTF (); apraide (msg); }} catch (IOException ex) {ex.printStackTrace (); } visbeidzot {handlers.removeElement (this); mēģiniet {s.close (); } catch (IOException ex) {ex.printStackTrace (); }}} // aizsargāta statiska tukša apraide (virknes ziņojums) ... 

The palaist () metode ir vieta, kur ienāk mūsu pavediens. Vispirms mēs pievienojam savu pavedienu Vector gada ChatHandlers apstrādātāji. Apstrādātāji Vector uztur visu pašreizējo apstrādātāju sarakstu. Tas ir statisks mainīgais, un tāpēc ir viens Vector visam ChatHandler klase un visas tās instances. Tādējādi visi ChatHandlers var piekļūt pašreizējo savienojumu sarakstam.

Ņemiet vērā, ka mums ir ļoti svarīgi pēc tam svītrot sevi no šī saraksta, ja savienojums neizdodas; pretējā gadījumā visi pārējie apstrādātāji mēģinās rakstīt mums, kad viņi pārraidīs informāciju. Šāda veida situācija, kad darbība ir obligāta pēc koda sadaļas pabeigšanas, ir galvenā mēģiniet ... beidzot konstruēt; tāpēc mēs visu savu darbu veicam a mēģini ... noķert ... beidzot konstruēt.

Šīs metodes pamatteksts saņem ziņojumus no klienta un pārraida tos visiem citiem klientiem, izmantojot apraide () metodi. Kad cilpa iziet, vai klienta izņēmuma dēļ vai tāpēc, ka šī pavediens ir apturēts, beidzot tiek garantēta klauzulas izpilde. Šajā klauzulā mēs noņemam mūsu pavedienu no apstrādātāju saraksta un aizveriet kontaktligzdu.

aizsargāta statiska tukšuma apraide (virknes ziņojums) {sinhronizēts (apstrādātāji) {Uzskaitījums e = apstrādātāji.elementi (); while (e.hasMoreElements ()) {ChatHandler c = (ChatHandler) e.nextElement (); mēģiniet {synchronized (c.o) {c.o.writeUTF (message); } c.o. skalot (); } catch (IOException ex) {c.stop (); }}}} 

Šī metode pārraida ziņojumu visiem klientiem. Vispirms mēs sinhronizējamies apstrādātāju sarakstā. Mēs nevēlamies, lai cilvēki pievienotos vai aizietu, kamēr mēs turpinām darbu, ja mēs mēģinātu raidīt kādam, kura vairs nav; tas liek klientiem gaidīt, līdz sinhronizēšana būs pabeigta. Ja serverim jāpārvar īpaši lielas slodzes, mēs varētu nodrošināt precīzāku sinhronizāciju.

Šajā sinhronizētajā blokā mēs iegūstam Uzskaitīšana no pašreizējiem apstrādātājiem. The Uzskaitīšana klase nodrošina ērtu veidu, kā atkārtot visus a elementus Vector. Mūsu cilpa vienkārši raksta ziņojumu katram elementam Uzskaitīšana. Ņemiet vērā, ka, rakstot uz a, rodas izņēmums ChatClient, tad mēs piezvanām klientam apstāties () metode; tas pārtrauc klienta pavedienu un tāpēc veic atbilstošu tīrīšanu, ieskaitot klienta noņemšanu no apstrādātājiem.

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