Programmēšana

Socket programmēšana Java: apmācība

Šī apmācība ir ievads ligzdu programmēšanā Java, sākot ar vienkāršu klienta-servera piemēru, kas demonstrē Java I / O pamata funkcijas. Jūs tiksiet iepazīstināts gan ar oriģinālujava.io pakete un NIO, nebloķējošais I / O (java.nio) API, kas ieviesti Java 1.4. Visbeidzot, NIO.2 jūs redzēsit piemēru, kas parāda Java tīklošanu, kas ieviesta no Java 7 uz priekšu.

Socket programmēšana ir saistīta ar divām sistēmām, kas savstarpēji sazinās. Parasti tīkla komunikācijai ir divas garšas: Transporta vadības protokols (TCP) un Lietotāju datagrammas protokols (UDP). TCP un UDP tiek izmantoti dažādiem mērķiem, un abiem ir unikāli ierobežojumi:

  • TCP ir salīdzinoši vienkāršs un uzticams protokols, kas ļauj klientam izveidot savienojumu ar serveri un abām sistēmām sazināties. TCP gadījumā katra entītija zina, ka ir saņemtas tās komunikācijas lietderīgās slodzes.
  • UDP ir a bezsaistes protokols un tas ir piemērots scenārijiem, kur, lai sasniegtu galamērķi, nav obligāti vajadzīga katra pakete, piemēram, multivides straumēšanai.

Lai novērtētu atšķirību starp TCP un UDP, apsveriet, kas notiktu, ja straumētu video no savas iecienītās vietnes un tas nomestu rāmjus. Vai vēlaties, lai klients palēnina filmas uzņemšanu, lai saņemtu trūkstošos kadrus, vai vēlaties turpināt video atskaņošanu? Video straumēšanas protokoli parasti izmanto UDP. Tā kā TCP garantē piegādi, tas ir izvēlētais protokols HTTP, FTP, SMTP, POP3 un tā tālāk.

Šajā apmācībā es jūs iepazīstinu ar ligzdu programmēšanu Java. Es iepazīstinu ar virkni klientu-serveru piemēru, kas demonstrē sākotnējā Java I / O ietvara funkcijas, pēc tam pakāpeniski pāriet uz NIO ieviesto funkciju izmantošanu.

Vecās skolas Java kontaktligzdas

Īstenojot pirms NIO, Java TCP klienta ligzdas kodu apstrādā java.net.Socket klasē. Šis kods atver savienojumu ar serveri:

 Socket socket = jauns Socket (serveris, ports); 

Reiz mūsu kontaktligzda gadījums ir savienots ar serveri, mēs varam sākt iegūt ievades un izvades straumes uz atsevišķu. Ievades straumes tiek izmantotas, lai nolasītu datus no servera, savukārt izvades straumes tiek izmantotas datu ierakstīšanai serverī. Mēs varam izpildīt šādas metodes, lai iegūtu ievades un izvades plūsmas:

 InputStream iekš = socket.getInputStream (); OutputStream out = socket.getOutputStream (); 

Tā kā tās ir parastas straumes, tās pašas straumes, kuras mēs izmantotu, lai lasītu un rakstītu failā, mēs varam tās pārveidot formā, kas vislabāk atbilst mūsu lietošanas gadījumam. Piemēram, mēs varētu ietīt OutputStream ar PrintStream lai mēs varētu viegli rakstīt tekstu ar tādām metodēm kā println (). Citu piemēru mēs varētu ietīt InputStream ar BufferedReader, izmantojot an InputStreamReader, lai tekstu varētu viegli nolasīt ar tādām metodēm kā readLine ().

lejupielādēt Lejupielādēt avota kodu "Socket programmēšana Java: apmācība". Izveidoja Steven Haines JavaWorld.

Java kontaktligzdas klienta piemērs

Apskatīsim īsu piemēru, kas izpilda HTTP GET pret HTTP serveri. HTTP ir sarežģītāks nekā pieļauj mūsu piemērs, taču mēs varam uzrakstīt klienta kodu, lai rīkotos vienkāršākajā gadījumā: pieprasiet resursam no servera, un serveris atgriež atbildi un aizver straumi. Šajā gadījumā ir jāveic šādas darbības:

  1. Izveidojiet ligzdu tīmekļa serverim, kas klausās 80. portu.
  2. Iegūt a PrintStream uz serveri un nosūtiet pieprasījumu IEGŪT CELU HTTP / 1.0, kur CELS ir pieprasītais resurss serverī. Piemēram, ja mēs vēlētos atvērt tīmekļa vietnes sakni, ceļš būtu /.
  3. Iegūstiet InputStream uz serveri, aptiniet to ar BufferedReader un rindu pa rindai lasiet atbildi.

1. saraksts parāda šī piemēra avota kodu.

Saraksts 1. SimpleSocketClientExample.java

pakete com.geekcap.javaworld.simplesocketclient; importēt java.io.BufferedReader; importēt java.io.InputStreamReader; importēt java.io.PrintStream; importēt java.net.Socket; public class SimpleSocketClientExample {public static void main (String [] args) {if (args.length <2) {System.out.println ("Lietojums: SimpleSocketClientExample"); System.exit (0); } Stīgu serveris = args [0]; Virknes ceļš = args [1]; System.out.println ("URL satura ielāde:" + serveris); mēģiniet {// izveidot savienojumu ar serveri Socket socket = new Socket (server, 80); // Izveidojiet ievades un izvades straumes lasīšanai un rakstīšanai uz serveri PrintStream out = new PrintStream (socket.getOutputStream ()); BufferedReader in = new BufferedReader (jauns InputStreamReader (socket.getInputStream ())); // Izpildiet GET HTTP / 1.0 HTTP protokolu, kam seko tukša rinda out.println ("GET" + ceļš + "HTTP / 1.0"); out.println (); // Datu lasīšana no servera, līdz pabeidzim lasīt dokumentu String line = in.readLine (); while (līnija! = null) {System.out.println (līnija); līnija = in.readLine (); } // Aizveriet mūsu straumes in.close (); out.close (); ligzda.slēgt (); } catch (izņēmums e) {e.printStackTrace (); }}} 

1. sarakstā tiek pieņemti divi komandrindas argumenti: serveris, ar kuru izveidot savienojumu (pieņemot, ka mēs izveidojam savienojumu ar serveri 80. portā), un resurss, kuru izgūt. Tas rada a Kontaktligzda kas norāda uz serveri un skaidri norāda portu 80. Pēc tam tā izpilda komandu:

IEGŪT CELU HTTP / 1.0 

Piemēram:

GET / HTTP / 1.0 

Kas tikko notika?

Ielādējot tīmekļa lapu no tīmekļa servera, piemēram, www.google.lv, HTTP klients izmanto DNS serverus, lai atrastu servera adresi: tas sākas ar augstākā līmeņa domēna servera pieprasīšanu com domēns, kurā domēnam domēna vārdu serveris ir domāts www.google.lv. Tad tā pieprasa, lai domēna vārdu serveris piešķir IP adresi (vai adreses) www.google.lv. Pēc tam tas atver ligzdu šim serverim 80. portā. (Vai arī, ja vēlaties definēt citu portu, varat to izdarīt, pievienojot kolu, kam seko porta numurs, piemēram: :8080.) Visbeidzot, HTTP klients izpilda norādīto HTTP metodi, piemēram, GŪT, POST, PUT, DZĒST, GALVAvai OPTI / ONS. Katrai metodei ir sava sintakse. Kā parādīts iepriekšējos koda fragmentos, GŪT metode prasa ceļu, kam seko HTTP / versijas numurs un tukša rinda. Ja mēs vēlētos pievienot HTTP galvenes, mēs to būtu varējuši izdarīt pirms ievadīšanas jaunajā rindā.

1. sarakstā mēs izguvām OutputStream un ietin to a PrintStream lai mēs varētu vieglāk izpildīt savas teksta komandas. Mūsu kods ieguva InputStream, ietin to InputStreamReader, kas to pārveidoja par a Lasītājsun pēc tam ietin to a BufferedReader. Mēs izmantojām PrintStream izpildīt mūsu GŪT metodi un pēc tam izmantoja BufferedReader lasīt atbildi pa rindai, līdz saņēmām a nulle atbildi, norādot, ka kontaktligzda ir aizvērta.

Tagad izpildiet šo klasi un nododiet šādus argumentus:

java com.geekcap.javaworld.simplesocketclient.SimpleSocketClientExample www.javaworld.com / 

Jums vajadzētu redzēt izvadi, kas ir līdzīgs zemāk redzamajam:

Notiek URL satura ielāde: www.javaworld.com HTTP / 1.1 200 OK Datums: svētdiena, 2014. gada 21. septembris 22:20:13 GMT serveris: Apache X-Gas_TTL: 10 Kešatmiņas kontrole: maksimālais vecums = 10 X-GasHost: gas2 .usw X-Cooking-With: Benzīns-Vietējais X-Benzīns-Vecums: 8 Satura garums: 168 Pēdējoreiz modificēts: otrdien, 2012. gada 24. janvārī 00:09:09 GMT Etags: "60001b-a8-4b73af4bf3340" Satura tips : text / html Various: Accept-Encoding Connection: aizvērt benzīna testa lapu

Panākumi

Šī izeja parāda testa lapu JavaWorld vietnē. Tā atbildēja, ka runā HTTP versijā 1.1 un atbilde ir 200 OK.

Java ligzdas servera piemērs

Mēs esam aptvēruši klienta pusi, un, par laimi, servera puses komunikācijas aspekts ir tikpat vienkāršs. No vienkāršota viedokļa process ir šāds:

  1. Izveidojiet a ServerSocket, norādot ostu, kurā klausīties.
  2. Izsaukt ServerSocket's pieņemt () metode, lai klausītos klienta savienojuma konfigurētajā portā.
  3. Kad klients izveido savienojumu ar serveri, pieņemt () metode atgriež a Kontaktligzda caur kuru serveris var sazināties ar klientu. Tas ir tas pats Kontaktligzda klase, kuru izmantojām klientam, tāpēc process ir tāds pats: iegūstiet InputStream lasīt no klienta un OutputStream rakstiet klientam.
  4. Ja jūsu serverim jābūt mērogojamam, jūs vēlaties nodot Kontaktligzda uz citu pavedienu, lai apstrādātu, lai jūsu serveris varētu turpināt klausīties papildu savienojumus.
  5. Zvaniet ServerSocket's pieņemt () vēlreiz, lai klausītos citu savienojumu.

Kā jūs drīz redzēsiet, NIO rīcība ar šo scenāriju būtu nedaudz savādāka. Tomēr pagaidām mēs varam tieši izveidot ServerSocket nododot to ostai, kur klausīties (vairāk par ServerSocketFactorys nākamajā sadaļā):

 ServerSocket serverSocket = jauns ServerSocket (ports); 

Un tagad mēs varam pieņemt ienākošos savienojumus, izmantojot pieņemt () metode:

 Socket socket = serverSocket.accept (); // Rīkojieties ar savienojumu ... 

Daudzlīniju programmēšana ar Java ligzdām

Zemāk esošajā 2. sarakstā viss servera kods līdz šim tiek apvienots nedaudz stabilākā piemērā, kurā vairāku pieprasījumu apstrādei tiek izmantoti pavedieni. Parādītais serveris ir atbalss serveris, kas nozīmē, ka tas atsaucas pret jebkuru saņemto ziņojumu.

Kaut arī 2. saraksta piemērs nav sarežģīts, tas paredz dažus no nākamajiem NIO sadaļas jautājumiem. Pievērsiet īpašu uzmanību vītnes koda apjomam, kas mums ir jāraksta, lai izveidotu serveri, kas spēj apstrādāt vairākus vienlaicīgus pieprasījumus.

Saraksts 2. SimpleSocketServer.java

pakete com.geekcap.javaworld.simplesocketclient; importēt java.io.BufferedReader; importēt java.io.I / OException; importēt java.io.InputStreamReader; importēt java.io.PrintWriter; importēt java.net.ServerSocket; importēt java.net.Socket; publiskā klase SimpleSocketServer paplašina Thread {private ServerSocket serverSocket; privātā int osta; privāta būla skriešana = false; public SimpleSocketServer (int ports) {this.port = ports; } public void startServer () {mēģiniet {serverSocket = jauns ServerSocket (ports); this.sākt (); } catch (I / OException e) {e.printStackTrace (); }} public void stopServer () {running = false; tas.traucēt (); } @Orride public void run () {running = true; kamēr (darbojas) {mēģiniet {System.out.println ("Savienojuma klausīšanās"); // Zvans accept (), lai saņemtu nākamo savienojumu Socket socket = serverSocket.accept (); // nododiet ligzdu RequestHandler pavedienam apstrādei RequestHandler requestHandler = jauns RequestHandler (ligzda); requestHandler.start (); } catch (I / OException e) {e.printStackTrace (); }}} public static void main (String [] args) {if (args.length == 0) {System.out.println ("Lietojums: SimpleSocketServer"); System.exit (0); } int ports = Integer.parseInt (args [0]); System.out.println ("Sākt serveri portā:" + ports); SimpleSocketServer serveris = jauns SimpleSocketServer (ports); server.startServer (); // Automātiska izslēgšanās 1 minūtes laikā mēģiniet {Thread.sleep (60000); } catch (izņēmums e) {e.printStackTrace (); } server.stopServer (); }} klases RequestHandler paplašina Thread {private Socket socket; RequestHandler (kontaktligzdas ligzda) {this.socket = ligzda; } @Orride public void run () {mēģiniet {System.out.println ("Saņemts savienojums"); // Iegūt ievades un izvades straumes BufferedReader in = new BufferedReader (new InputStreamReader (socket.getInputStream ())); PrintWriter out = jauns PrintWriter (socket.getOutputStream ()); // izrakstiet mūsu galveni klientam out.println ("Echo Server 1.0"); out.skalot (); // Atbalss rindas atpakaļ klientam, līdz klients aizver savienojumu vai mēs saņemam tukšu rindu String line = in.readLine (); while (līnija! = null && līnija.length ()> 0) {out.println ("Atbalss:" + līnija); out.skalot (); līnija = in.readLine (); } // Aizveriet mūsu savienojumu in.close (); out.close (); ligzda.slēgt (); System.out.println ("Savienojums slēgts"); } catch (izņēmums e) {e.printStackTrace (); }}} 
$config[zx-auto] not found$config[zx-overlay] not found