Teatud seadmes käivitatava koodi kirjutamine on väga rahuldust pakkuv. Kuid koodi kirjutamine, mis käivitub mitmel üksteisega suhtleval seadmel, on lihtsalt elujaatav. See artikkel õpetab teile, kuidas edastusjuhtimisprotokolli (TCP) abil võrku sõnumeid ühendada ja vahetada.
Selles artiklis seadistate rakenduse, mis ühendab teie arvuti endaga ja muudab selle sisuliselt hulluks - rääkige iseendaga. Samuti saate teada, mis vahe on Java -võrgustike loomiseks kõige enam kasutataval voolul ja kuidas need toimivad.
Andme- ja objektivood
Enne koodiks sukeldumist tuleb eristada artiklis kasutatud kahe voo erinevust.
Andmevoog
Andmevood töötlevad primitiivseid andmetüüpe ja stringe. Andmevoogude kaudu saadetavad andmed tuleb käsitsi serialiseerida ja deserialiseerida, mis raskendab keerukate andmete edastamist. Kuid andmevoog saab suhelda serverite ja klientidega, mis on kirjutatud muudes keeltes kui Java. Toores voolud on selles aspektis sarnased andmevoogudega, kuid andmevoog tagab andmete vormindamise platvormist sõltumatul viisil, mis on kasulik, kuna mõlemad osapooled saavad saadetud andmeid lugeda.
Objekti voog
Objektivoogud töötlevad primitiivseid andmetüüpe ja rakendatavaid objekte
Serialiseeritav
liides. Objektivoogude kaudu saadetavad andmed järjestatakse automaatselt ja deserialiseeritakse, mis lihtsustab keerukate andmete edastamist. Kuid objektivoog saab suhelda ainult Java -keeles kirjutatud serverite ja klientidega. Samuti
ObjectOutputStream
lähtestamisel saadab päise
InputStream
teise osapoole, kes initsialiseerimisel blokeerib täitmise kuni päise kättesaamiseni.
Sammud
Samm 1. Looge klass
Looge klass ja pange sellele nimi, nagu soovite. Selles artiklis nimetatakse seda
NetworkAppExample
avalik klass NetworkAppExample {}
Samm 2. Loo põhimeetod
Looge peamine meetod ja kuulutage, et see võib erandeid teha
Erand
tüüp ja selle alamklass - kõik erandid. Seda peetakse halvaks tavaks, kuid paljaste näidete puhul on see vastuvõetav.
avalik klass NetworkAppExample {public static void main (String args) viskab Erand {}}
Samm 3. Deklareerige serveri aadress
See näide kasutab kohalikku hosti aadressi ja suvalist pordinumbrit. Pordi number peab olema vahemikus 0 kuni 65535 (kaasa arvatud). Vältitavad pordinumbrid on aga vahemikus 0 kuni 1023 (kaasa arvatud), kuna need on reserveeritud süsteemipordid.
public class NetworkAppExample {public static void main (String args) viskab Erand {String host = "localhost"; int port = 10430; }}
Samm 4. Looge server
Server on seotud aadressi ja pordiga ning kuulab sissetulevaid ühendusi. Java keeles
ServerSocket
tähistab serveripoolset lõpp-punkti ja selle funktsioon on uute ühenduste vastuvõtmine.
ServerSocket
ei oma vooge andmete lugemiseks ja saatmiseks, kuna see ei esinda ühendust serveri ja kliendi vahel.
importige java.net. InetAddress; importige java.net. ServerSocket; public class NetworkAppExample {public static void main (String args) viskab Erand {String host = "localhost"; int port = 10430; ServerSocket server = uus ServerSocket (port, 50, InetAddress.getByName (host)); }}
Samm 5. Logiserveri loomine
Logimise eesmärgil printige konsoolile, et server on käivitatud.
importige java.net. InetAddress; importige java.net. ServerSocket; public class NetworkAppExample {public static void main (String args) viskab Erand {String host = "localhost"; int port = 10430; ServerSocket server = uus ServerSocket (port, 50, InetAddress.getByName (host)); System.out.println ("Server käivitati."); }}
Samm 6. Looge klient
Klient on seotud serveri aadressi ja pordiga ning kuulab pakette (sõnumeid) pärast ühenduse loomist. Java keeles
Pistikupesa
tähistab kas kliendipoolset lõpp-punkti, mis on serveriga ühendatud või ühendust (serverist) kliendiga ja seda kasutatakse teise poole osapoolega suhtlemiseks.
importige java.net. InetAddress; importige java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) viskab Erand {String host = "localhost"; int port = 10430; ServerSocket server = uus ServerSocket (port, 50, InetAddress.getByName (host)); System.out.println ("Server käivitati."); Pistikupesa klient = uus pesa (host, port); }}
Samm 7. Logi ühenduse loomise katse
Logimise eesmärgil printige konsoolile, et ühendust prooviti.
importige java.net. InetAddress; importige java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) viskab Erand {String host = "localhost"; int port = 10430; ServerSocket server = uus ServerSocket (port, 50, InetAddress.getByName (host)); System.out.println ("Server käivitati."); Pistikupesa klient = uus pesa (host, port); System.out.println ("Ühendamine serveriga …"); }}
Samm 8. Looge ühendus
Kliendid ei loo kunagi ühendust, kui server ei kuula ja aktsepteeri, teisisõnu ei loo ühendusi. Java -s luuakse ühendused, kasutades
vastu võtma ()
meetod
ServerSocket
klassi. Meetod blokeerib täitmise, kuni klient loob ühenduse.
importige java.net. InetAddress; importige java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) viskab Erand {String host = "localhost"; int port = 10430; ServerSocket server = uus ServerSocket (port, 50, InetAddress.getByName (host)); System.out.println ("Server käivitati."); Pistikupesa klient = uus pesa (host, port); System.out.println ("Ühendamine serveriga …"); Pesaühendus = server.accept (); }}
Samm 9. Logige loodud ühendus sisse
Logimise eesmärgil printige konsooli, et serveri ja kliendi vahel on ühendus loodud.
importige java.net. InetAddress; importige java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) viskab Erand {String host = "localhost"; int port = 10430; ServerSocket server = uus ServerSocket (port, 50, InetAddress.getByName (host)); System.out.println ("Server käivitati."); Pistikupesa klient = uus pesa (host, port); System.out.println ("Ühendamine serveriga …"); Pesaühendus = server.accept (); System.out.println ("Ühendus loodud."); }}
Etapp 10. Valmistage ette suhtlusvoogusid
Suhtlemine toimub voogude kaudu ja selles rakenduses tuleb serveri (kliendist) ja kliendi (ühenduse serverist) ja kliendi toorvoogud siduda kas andmete või objektivoogudega. Pidage meeles, et mõlemad pooled peavad kasutama sama voo tüüpi.
-
Andmevood
importige java.io. DataInputStream; importige java.io. DataOutputStream; importige java.net. InetAddress; importige java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) viskab Erand {String host = "localhost"; int port = 10430; ServerSocket server = uus ServerSocket (port, 50, InetAddress.getByName (host)); System.out.println ("Server käivitati."); Pistikupesa klient = uus pesa (host, port); System.out.println ("Ühendamine serveriga …"); Pesaühendus = server.accept (); System.out.println ("Ühendus loodud."); DataOutputStream clientOut = uus DataOutputStream (client.getOutputStream ()); DataInputStream clientIn = uus DataInputStream (client.getInputStream ()); DataOutputStream serverOut = uus DataOutputStream (connection.getOutputStream ()); DataInputStream serverIn = uus DataInputStream (connection.getInputStream ()); }}
-
Objektide voog
Kui kasutatakse mitut objektivoogu, tuleb sisendvood lähtestada samas järjekorras kui väljundvoogud, sest
ObjectOutputStream
saadab teisele poolele päise ja
ObjectInputStream
blokeerib täitmise, kuni see loeb päise.
importige java.io. ObjectInputStream; importige java.io. ObjectOutputStream; importige java.net. InetAddress; importige java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) viskab Erand {String host = "localhost"; int port = 10430; ServerSocket server = uus ServerSocket (port, 50, InetAddress.getByName (host)); System.out.println ("Server käivitati."); Pistikupesa klient = uus pesa (host, port); System.out.println ("Ühendamine serveriga …"); Pesaühendus = server.accept (); System.out.println ("Ühendus loodud."); ObjectOutputStream clientOut = uus ObjectOutputStream (client.getOutputStream ()); ObjectOutputStream serverOut = uus ObjectOutputStream (connection.getOutputStream ()); ObjectInputStream clientIn = uus ObjectInputStream (client.getInputStream ()); ObjectInputStream serverIn = uus ObjectInputStream (connection.getInputStream ()); }}
Ülaltoodud koodis täpsustatud järjekorda võib olla lihtsam meelde jätta - esmalt lähtestage väljundvoog, seejärel sisestage voog samas järjekorras. Teine järjekord objektivoogude initsialiseerimiseks on aga järgmine:
ObjectOutputStream clientOut = uus ObjectOutputStream (client.getOutputStream ()); ObjectInputStream serverIn = uus ObjectInputStream (connection.getInputStream ()); ObjectOutputStream serverOut = uus ObjectOutputStream (connection.getOutputStream ()); ObjectInputStream clientIn = uus ObjectInputStream (client.getInputStream ());
Samm 11. Logige sisse, et side on valmis
Logimise eesmärgil printige konsoolile, et side on valmis.
// kood jäeti importimata java.net. InetAddress; importige java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) viskab Erand {String host = "localhost"; int port = 10430; ServerSocket server = uus ServerSocket (port, 50, InetAddress.getByName (host)); System.out.println ("Server käivitati."); Pistikupesa klient = uus pesa (host, port); System.out.println ("Ühendamine serveriga …"); Pesaühendus = server.accept (); System.out.println ("Ühendus loodud."); // kood välja jäetud System.out.println ("Side on valmis."); }}
Samm 12. Looge sõnum
Selles rakenduses
Tere, Maailm
tekst saadetakse serverisse kas
bait
või
String
. Deklareerige sellist tüüpi muutuja, mis sõltub kasutatavast voost. Kasutamine
bait
andmevoogude jaoks ja
String
objektivoogude jaoks.
-
Andmevood
Andmevoogude abil toimub serialiseerimine objektide teisendamisega primitiivseteks andmetüüpideks või a
String
. Sel juhul,
String
teisendatakse
bait
kirjutamise asemel
writeBytes ()
meetod, mis näitab, kuidas seda teiste objektidega, näiteks piltide või muude failidega, tehakse.
importige java.io. DataInputStream; importige java.io. DataOutputStream; importige java.net. InetAddress; importige java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) viskab Erand {String host = "localhost"; int port = 10430; ServerSocket server = uus ServerSocket (port, 50, InetAddress.getByName (host)); System.out.println ("Server käivitati."); Pistikupesa klient = uus pesa (host, port); System.out.println ("Ühendamine serveriga …"); Pesaühendus = server.accept (); System.out.println ("Ühendus loodud."); DataOutputStream clientOut = uus DataOutputStream (client.getOutputStream ()); DataInputStream clientIn = uus DataInputStream (client.getInputStream ()); DataOutputStream serverOut = uus DataOutputStream (connection.getOutputStream ()); DataInputStream serverIn = uus DataInputStream (connection.getInputStream ()); System.out.println ("Side on valmis."); bait messageOut = "Tere maailm".getBytes (); }}
-
Objektide voog
importige java.io. ObjectInputStream; importige java.io. ObjectOutputStream; importige java.net. InetAddress; importige java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) viskab Erand {String host = "localhost"; int port = 10430; ServerSocket server = uus ServerSocket (port, 50, InetAddress.getByName (host)); System.out.println ("Server käivitati."); Pistikupesa klient = uus pesa (host, port); System.out.println ("Ühendamine serveriga …"); Pesaühendus = server.accept (); System.out.println ("Ühendus loodud."); ObjectOutputStream clientOut = uus ObjectOutputStream (client.getOutputStream ()); ObjectOutputStream serverOut = uus ObjectOutputStream (connection.getOutputStream ()); ObjectInputStream clientIn = uus ObjectInputStream (client.getInputStream ()); ObjectInputStream serverIn = uus ObjectInputStream (connection.getInputStream ()); System.out.println ("Side on valmis."); String messageOut = "Tere maailm"; }}
Samm 13. Saatke sõnum
Kirjutage andmed väljundvoogu ja loputage voog, et andmed oleksid täielikult kirjutatud.
-
Andmevood
Esmalt tuleb saata sõnumi pikkus, nii et teine osapool teaks, mitu baiti ta peab lugema. Pärast pikkuse saatmist primitiivse täisarvuna saab saata baite.
importige java.io. DataInputStream; importige java.io. DataOutputStream; importige java.net. InetAddress; importige java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) viskab Erand {String host = "localhost"; int port = 10430; ServerSocket server = uus ServerSocket (port, 50, InetAddress.getByName (host)); System.out.println ("Server käivitati."); Pistikupesa klient = uus pesa (host, port); System.out.println ("Ühendamine serveriga …"); Pesaühendus = server.accept (); System.out.println ("Ühendus loodud."); DataOutputStream clientOut = uus DataOutputStream (client.getOutputStream ()); DataInputStream clientIn = uus DataInputStream (client.getInputStream ()); DataOutputStream serverOut = uus DataOutputStream (connection.getOutputStream ()); DataInputStream serverIn = uus DataInputStream (connection.getInputStream ()); System.out.println ("Side on valmis."); bait messageOut = "Tere maailm".getBytes (); clientOut.writeInt (messageOut.length); clientOut.write (messageOut); clientOut.flush (); }}
-
Objektide voog
importige java.io. ObjectInputStream; importige java.io. ObjectOutputStream; importige java.net. InetAddress; importige java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) viskab Erand {String host = "localhost"; int port = 10430; ServerSocket server = uus ServerSocket (port, 50, InetAddress.getByName (host)); System.out.println ("Server käivitati."); Pistikupesa klient = uus pesa (host, port); System.out.println ("Ühendamine serveriga …"); Pesaühendus = server.accept (); System.out.println ("Ühendus loodud."); ObjectOutputStream clientOut = uus ObjectOutputStream (client.getOutputStream ()); ObjectOutputStream serverOut = uus ObjectOutputStream (connection.getOutputStream ()); ObjectInputStream clientIn = uus ObjectInputStream (client.getInputStream ()); ObjectInputStream serverIn = uus ObjectInputStream (connection.getInputStream ()); System.out.println ("Side on valmis."); String messageOut = "Tere maailm"; clientOut.writeObject (messageOut); clientOut.flush (); }}
Samm 14. Logi saadetud sõnum
Logimise eesmärgil printige konsoolile sõnum, mis on saadetud.
-
Andmevood
importige java.io. DataInputStream; importige java.io. DataOutputStream; importige java.net. InetAddress; importige java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) viskab Erand {String host = "localhost"; int port = 10430; ServerSocket server = uus ServerSocket (port, 50, InetAddress.getByName (host)); System.out.println ("Server käivitati."); Pistikupesa klient = uus pesa (host, port); System.out.println ("Ühendamine serveriga …"); Pesaühendus = server.accept (); System.out.println ("Ühendus loodud."); DataOutputStream clientOut = uus DataOutputStream (client.getOutputStream ()); DataInputStream clientIn = uus DataInputStream (client.getInputStream ()); DataOutputStream serverOut = uus DataOutputStream (connection.getOutputStream ()); DataInputStream serverIn = uus DataInputStream (connection.getInputStream ()); System.out.println ("Side on valmis."); bait messageOut = "Tere maailm".getBytes (); clientOut.writeInt (messageOut.length); clientOut.write (messageOut); clientOut.flush (); System.out.println ("Sõnum serverisse saadetud:" + uus string (messageOut)); }}
-
Objektide voog
importige java.io. ObjectInputStream; importige java.io. ObjectOutputStream; importige java.net. InetAddress; importige java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) viskab Erand {String host = "localhost"; int port = 10430; ServerSocket server = uus ServerSocket (port, 50, InetAddress.getByName (host)); System.out.println ("Server käivitati."); Pistikupesa klient = uus pesa (host, port); System.out.println ("Ühendamine serveriga …"); Pesaühendus = server.accept (); System.out.println ("Ühendus loodud."); ObjectOutputStream clientOut = uus ObjectOutputStream (client.getOutputStream ()); ObjectOutputStream serverOut = uus ObjectOutputStream (connection.getOutputStream ()); ObjectInputStream clientIn = uus ObjectInputStream (client.getInputStream ()); ObjectInputStream serverIn = uus ObjectInputStream (connection.getInputStream ()); System.out.println ("Side on valmis."); String messageOut = "Tere maailm"; clientOut.writeObject (messageOut); clientOut.flush (); System.out.println ("Sõnum saadeti serverile:" + messageOut); }}
Samm 15. Lugege sõnumit
Lugege sisendvoost andmeid ja teisendage need. Kuna me teame täpselt saadetud andmete tüüpi, loome kas a
String
alates
bait
või valatud
Objekt
et
String
ilma kontrollimata, olenevalt kasutatavast voost.
-
Andmevood
Kuna pikkus saadeti kõigepealt ja baitid hiljem, tuleb lugemine teha samas järjekorras. Kui pikkus on null, pole midagi lugeda. Objekt deserialiseeritakse, kui baidid teisendatakse tagasi eksemplariks, antud juhul juhul
String
importige java.io. DataInputStream; importige java.io. DataOutputStream; importige java.net. InetAddress; importige java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) viskab Erand {String host = "localhost"; int port = 10430; ServerSocket server = uus ServerSocket (port, 50, InetAddress.getByName (host)); System.out.println ("Server käivitati."); Pistikupesa klient = uus pesa (host, port); System.out.println ("Ühendamine serveriga …"); Pesaühendus = server.accept (); System.out.println ("Ühendus loodud."); DataOutputStream clientOut = uus DataOutputStream (client.getOutputStream ()); DataInputStream clientIn = uus DataInputStream (client.getInputStream ()); DataOutputStream serverOut = uus DataOutputStream (connection.getOutputStream ()); DataInputStream serverIn = uus DataInputStream (connection.getInputStream ()); System.out.println ("Side on valmis."); bait messageOut = "Tere maailm".getBytes (); clientOut.writeInt (messageOut.length); clientOut.write (messageOut); clientOut.flush (); System.out.println ("Sõnum serverisse saadetud:" + uus string (messageOut)); int pikkus = serverIn.readInt (); if (pikkus> 0) {bait messageIn = uus bait [pikkus]; serverIn.readFully (messageIn, 0, messageIn.length); }}}
-
Objektide voog
importige java.io. ObjectInputStream; importige java.io. ObjectOutputStream; importige java.net. InetAddress; importige java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) viskab Erand {String host = "localhost"; int port = 10430; ServerSocket server = uus ServerSocket (port, 50, InetAddress.getByName (host)); System.out.println ("Server käivitati."); Pistikupesa klient = uus pesa (host, port); System.out.println ("Ühendamine serveriga …"); Pesaühendus = server.accept (); System.out.println ("Ühendus loodud."); ObjectOutputStream clientOut = uus ObjectOutputStream (client.getOutputStream ()); ObjectOutputStream serverOut = uus ObjectOutputStream (connection.getOutputStream ()); ObjectInputStream clientIn = uus ObjectInputStream (client.getInputStream ()); ObjectInputStream serverIn = uus ObjectInputStream (connection.getInputStream ()); System.out.println ("Side on valmis."); String messageOut = "Tere maailm"; clientOut.writeObject (messageOut); clientOut.flush (); System.out.println ("Sõnum saadeti serverile:" + messageOut); String messageIn = (String) serverIn.readObject (); }}
Samm 16. Logi loetud sõnum
Logimise eesmärgil printige konsoolile sõnum vastu ja printige selle sisu.
-
Andmevood
importige java.io. DataInputStream; importige java.io. DataOutputStream; importige java.net. InetAddress; importige java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) viskab Erand {String host = "localhost"; int port = 10430; ServerSocket server = uus ServerSocket (port, 50, InetAddress.getByName (host)); System.out.println ("Server käivitati."); Pistikupesa klient = uus pesa (host, port); System.out.println ("Ühendamine serveriga …"); Pesaühendus = server.accept (); System.out.println ("Ühendus loodud."); DataOutputStream clientOut = uus DataOutputStream (client.getOutputStream ()); DataInputStream clientIn = uus DataInputStream (client.getInputStream ()); DataOutputStream serverOut = uus DataOutputStream (connection.getOutputStream ()); DataInputStream serverIn = uus DataInputStream (connection.getInputStream ()); System.out.println ("Side on valmis."); bait messageOut = "Tere maailm".getBytes (); clientOut.writeInt (messageOut.length); clientOut.write (messageOut); clientOut.flush (); System.out.println ("Sõnum serverisse saadetud:" + uus string (messageOut)); int pikkus = serverIn.readInt (); if (pikkus> 0) {bait messageIn = uus bait [pikkus]; serverIn.readFully (messageIn, 0, messageIn.length); System.out.println ("Kliendilt saadud teade:" + uus string (messageIn)); }}}
-
Objektide voog
importige java.io. ObjectInputStream; importige java.io. ObjectOutputStream; importige java.net. InetAddress; importige java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) viskab Erand {String host = "localhost"; int port = 10430; ServerSocket server = uus ServerSocket (port, 50, InetAddress.getByName (host)); System.out.println ("Server käivitati."); Pistikupesa klient = uus pesa (host, port); System.out.println ("Ühendamine serveriga …"); Pesaühendus = server.accept (); System.out.println ("Ühendus loodud."); ObjectOutputStream clientOut = uus ObjectOutputStream (client.getOutputStream ()); ObjectOutputStream serverOut = uus ObjectOutputStream (connection.getOutputStream ()); ObjectInputStream clientIn = uus ObjectInputStream (client.getInputStream ()); ObjectInputStream serverIn = uus ObjectInputStream (connection.getInputStream ()); System.out.println ("Side on valmis."); String messageOut = "Tere maailm"; clientOut.writeObject (messageOut); clientOut.flush (); System.out.println ("Sõnum saadeti serverile:" + messageOut); String messageIn = (String) serverIn.readObject (); System.out.println ("Kliendilt saadud teade:" + messageIn); }}
Samm 17. Ühendage ühendused lahti
Ühendus katkeb, kui üks osapool oma voogud sulgeb. Java -s suletakse ka väljundvoo sulgemisega seotud pistikupesa ja sisendvoog. Kui osapool teises otsas saab teada, et ühendus on surnud, peab ta ka väljundvoo sulgema, et vältida mälulekkeid.
// kood jäeti importimata java.net. InetAddress; importige java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) viskab Erand {String host = "localhost"; int port = 10430; ServerSocket server = uus ServerSocket (port, 50, InetAddress.getByName (host)); System.out.println ("Server käivitati."); Pistikupesa klient = uus pesa (host, port); System.out.println ("Ühendamine serveriga …"); Pesaühendus = server.accept (); System.out.println ("Ühendus loodud."); // kood välja jäetud System.out.println ("Side on valmis."); // kood on välja jäetud clientOut.close (); serverOut.close (); }}
Samm 18. Logi lahtiühendamine
Logimise eesmärgil on konsooliühenduste printimine lahti ühendatud.
// kood jäeti importimata java.net. InetAddress; importige java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) viskab Erand {String host = "localhost"; int port = 10430; ServerSocket server = uus ServerSocket (port, 50, InetAddress.getByName (host)); System.out.println ("Server käivitati."); Pistikupesa klient = uus pesa (host, port); System.out.println ("Ühendamine serveriga …"); Pesaühendus = server.accept (); System.out.println ("Ühendus loodud."); // kood välja jäetud System.out.println ("Side on valmis."); // kood välja jäetud clientOut.close (); serverOut.close (); System.out.println ("Ühendused suletud."); }}
Samm 19. Lõpetage server
Ühendused on katkestatud, kuid server töötab ja töötab. Nagu
ServerSocket
ei ole ühegi vooga seotud, see tuleb helistamisega selgesõnaliselt sulgeda
Sulge()
meetod.
// kood jäeti importimata java.net. InetAddress; importige java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) viskab Erand {String host = "localhost"; int port = 10430; ServerSocket server = uus ServerSocket (port, 50, InetAddress.getByName (host)); System.out.println ("Server käivitati."); Pistikupesa klient = uus pesa (host, port); System.out.println ("Ühendamine serveriga …"); Pesaühendus = server.accept (); System.out.println ("Ühendus loodud."); // kood välja jäetud System.out.println ("Side on valmis."); // kood välja jäetud clientOut.close (); serverOut.close (); System.out.println ("Ühendused suletud."); server.close (); }}
Samm 20. Logi serveri lõpetamine
Logimise eesmärgil on konsooliserverisse printimine lõpetatud.
// kood jäeti importimata java.net. InetAddress; importige java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) viskab Erand {String host = "localhost"; int port = 10430; ServerSocket server = uus ServerSocket (port, 50, InetAddress.getByName (host)); System.out.println ("Server käivitati."); Pistikupesa klient = uus pesa (host, port); System.out.println ("Ühendamine serveriga …"); Pesaühendus = server.accept (); System.out.println ("Ühendus loodud."); // kood välja jäetud System.out.println ("Side on valmis."); // kood välja jäetud clientOut.close (); serverOut.close (); System.out.println ("Ühendused suletud."); server.close (); System.out.println ("Server on lõpetatud."); }}
Samm 21. Koosta ja käivita
Logimine võimaldas meil teada saada, kas rakendus õnnestus või mitte. Eeldatav väljund:
Server käivitati. Ühendamine serveriga… Ühendus loodud. Suhtlus on valmis. Sõnum saadeti serverisse: Tere maailm Sõnum saadi kliendilt: Hello World Connections suleti. Server on lõpetatud.
Kui teie väljund ei ole selline nagu ülaltoodud, mida tõenäoliselt ei juhtu, on mõned lahendused:
-
Kui väljund peatub joonel
Ühendus loodud.
ja objektivooge, loputage igaüks
ObjectOutputStream
- kohe pärast initsialiseerimist, sest päiseid mingil põhjusel ei saadetud.
-
Kui väljund prindib
java.net. BindException: Aadress on juba kasutusel
- valige teine pordinumber, kuna see on juba kasutatud.
Näpunäiteid
- Ühendamine mõne teise võrgu serveriga toimub ühenduse loomisega seadme välise IP -aadressiga, kus töötab server, millel on edastatud port.
- Ühendamine sama võrgu serveriga toimub ühenduse loomisega serverit käitava seadme privaatse IP -aadressiga või pordi edastamisega ja ühenduse loomisega seadme välise IP -aadressiga.
- On tarkvara, näiteks Hamachi, mis võimaldab ühendada serveriga teises võrgus ilma pordi edastamata, kuid see nõuab tarkvara installimist mõlemasse seadmesse.
Näited
Blokeerivat sisendit/väljundit kasutavad võrgurakendused peavad kasutama lõime. Järgmised näited näitavad minimalistlikku lõimega serveri- ja kliendirakendust. Võrgukood on sisuliselt sama, mis artiklis, välja arvatud mõned väljavõtted, mis on sünkroonitud, niididesse teisaldatud ja erandeid käsitletakse.
Server.java
importige java.io. IOException; importige java.net. InetAddress; importige java.net. ServerSocket; importige java.net. SocketException; importige java.net. UnknownHostException; import java.util. ArrayList; import java.util. Collections; import java.util. List; /*** Klass {@code Server} tähistab võrgu serveri lõpp-punkti. Kui {@code Server} on seotud teatud IP * aadressi ja pordiga, loob see klientidega ühendusi ning suudab nendega suhelda või neid katkestada. *
* See klass on niiditurvaline. * * @version 1.0 * @see Client * @see Connection */ public class Server rakendab Runnable {private ServerSocket server; privaatne nimekiri
ühendused; privaatne niit; privaatne lõplik ObjektiühendusedLukk = uus objekt (); /** * Konstrueerib {@code Server}, mis suhtleb klientidega määratud hosti nime ja pordi kaudu koos määratud * soovitud maksimaalse sissetulevate klientide järjekorra pikkusega. * * @param hosti kasutatav hosti aadress. * @param port Kasutatav pordi number. * @parami mahajäämus Soovitud sissetulevate klientide järjekorra maksimaalne pikkus. * @throws NetworkException Kui serveri käivitamisel ilmneb tõrge. */ public Server (String host, int port, int backlog) viskab NetworkException {try {server = new ServerSocket (port, backlog, InetAddress.getByName (host)); } catch (UnknownHostException e) {throws new NetworkException ("Hosti nime ei õnnestunud lahendada:" + host, e); } catch (IllegalArgumentException e) {throws new NetworkException ("Pordi number peab olema vahemikus 0 kuni 65535 (kaasa arvatud):" + port); } catch (IOException e) {viska uus NetworkException ("Serverit ei saanud käivitada.", e); } ühendused = Collections.synchronizedList (uus ArrayList ()); teema = uus Lõng (see); thread.start (); } /*** Loob {@code Server}, mis suhtleb klientidega määratud hosti nime ja pordi kaudu. * * @parami hosti siduv hosti aadress. * @param port Sidumiseks pordi number. * @throws NetworkException Kui serveri käivitamisel ilmneb tõrkeid. */ public Server (String host, int port) viskab NetworkException {this (host, port, 50); } /*** Kuulab, aktsepteerib ja registreerib klientidelt saabuvaid ühendusi. */ @Override public void run () {while (! Server.isClosed ()) {try {connection.add (uus ühendus (server.accept ())); } catch (SocketException e) {if (! e.getMessage (). equals ("Socket closed")) {e.printStackTrace (); }} saak (NetworkException | IOException e) {e.printStackTrace (); }}} /*** Saadab andmed kõigile registreeritud klientidele. * * @param andmed Saadetavad andmed. * @throws IllegalStateException Kui andmeid kirjutatakse, kui server on võrguühenduseta. * @throws IllegalArgumentException Kui saadetavad andmed on tühjad. */ public void broadcast (Object data) {if (server.isClosed ()) {throws new IllegalStateException ("Andmeid ei saadetud, server on võrguühenduseta."); } if (andmed == null) {viska uus IllegalArgumentException ("nullandmed"); } sünkroniseeritud (connectionLock) {for (Ühendusühendus: ühendused) {try {connection.send (data); System.out.println ("Andmed saadeti kliendile edukalt."); } saak (NetworkException e) {e.printStackTrace (); }}}} /*** Saadab lahtiühendamise teate ja katkestab määratud kliendi ühenduse. * * @parami ühendus Klient ühenduse katkestamiseks. * @throws NetworkException Kui ühenduse sulgemisel ilmneb tõrge. */ public void disconnect (Ühendusühendus) viskab välja NetworkException {if (connection.remove (connection)) {connection.close (); }} /*** Saadab katkestusteate kõigile klientidele, katkestab nende ühenduse ja sulgeb serveri. */ public void close () viskab NetworkException {sychronized (connectionLock) {for (Ühendusühendus: ühendused) {try {connection.close (); } saak (NetworkException e) {e.printStackTrace (); }}} ühendused.selge (); proovige {server.close (); } catch (IOException e) {throws new NetworkException ("Viga serveri sulgemisel."); } lõpuks {thread.interrupt (); }} /*** Tagastab, kas server on võrgus või mitte. * * @return Tõsi, kui server on võrgus. Vale, muidu. */ public boolean isOnline () {return! server.isClosed (); } /*** Tagastab registreeritud klientide massiivi. */ public Connection getConnections () {synchronized (linksLock) {return connection.toArray (new Connection [connection.size ()]); }}}
Klient.java
importige java.io. IOException; import java.net. Socket; importige java.net. UnknownHostException; /*** Klass {@code Client} tähistab kliendi lõpp-punkti võrgus. Pärast teatud * serveriga ühendamist saab {@code Client} tagada ainult serveriga suhtlemise. See, kas teised kliendid saavad andmed *, sõltub serveri rakendusest. *
* See klass on niiditurvaline. * * @version 1.0 * @see Server * @see Connection */ public class Client {private Connection ühendus; /*** Ehitab {@code Client} serveriga ühendatud määratud hosti ja pordi. * * @param host Host siduv hosti aadress. * @param port Sidumiseks pordi number. * @throws NetworkException Kui serveri käivitamisel ilmneb tõrge. */ public Client (String host, int port) viskab NetworkException {try {connection = new Connection (new Socket (host, port)); } catch (UnknownHostException e) {throws new NetworkException ("Hosti nime ei õnnestunud lahendada:" + host, e); } catch (IllegalArgumentException e) {throws new NetworkException ("Pordi number peab olema vahemikus 0 kuni 65535 (kaasa arvatud):" + port); } catch (IOException e) {viska uus NetworkException ("Serverit ei saanud käivitada.", e); }} /*** Saadab andmed teisele poolele. * * @param andmed Saadetavad andmed. * @throws NetworkException Kui väljundvoogu kirjutamine ebaõnnestub. * @throws IllegalStateException Kui ühenduse kirjutamise ajal üritatakse andmeid kirjutada. * @throws IllegalArgumentException Kui saadetavad andmed on tühjad. * @throws UnsupportedOperationException Kui toetamata andmetüüpi üritatakse saata. */ public void send (Objekti andmed) viskab NetworkException {connection.send (andmed); } /*** Saadab serverile katkestusteate ja katkestab ühenduse. */ public void close () viskab NetworkException {connection.close (); } /*** Tagastab, kas klient on serveriga ühendatud või mitte. * * @return Tõsi, kui klient on ühendatud. Vale, muidu. */ public boolean isOnline () {return connection.isConnected (); } /*** Tagastab kliendi eksemplari {@link Connection}. */ public Connection getConnection () {tagasipöörduv ühendus; }}
Ühendus.java
importige java.io. DataInputStream; importige java.io. DataOutputStream; importige java.io. IOException; import java.net. Socket; importige java.net. SocketException; /** * Klass {@code Connection} tähistab kas ühendust serverist kliendiga või kliendi lõpp-punkti võrgus * {@code Connection} saab pärast ühenduse loomist vahetada andmeid teiste osapooltega. serveris * juurutamine. *
* See klass on niiditurvaline. * * @version 1.0 * @see Server * @see Client */ public class Ühendusrakendused Runnable {private Socket socket; privaatne DataOutputStream välja; privaatne DataInputStream sisse; privaatne niit; private final Object writeLock = uus objekt (); private final Object readLock = uus objekt (); /*** Ehitab {@code Connection}, kasutades määratud {@link Socket} vooge. * * @param pistikupesa voogude toomiseks.*/ public Connection (pistikupesa) viskab NetworkException {if (pesa == null) {viska uus IllegalArgumentException ("nullpesa"); } this.socket = pesa; try {out = new DataOutputStream (socket.getOutputStream ()); } catch (IOException e) {throws new NetworkException ("Ei saanud juurdepääsu väljundvoole.", e); } try {in = new DataInputStream (socket.getInputStream ()); } catch (IOException e) {throws new NetworkException ("Sisendvoole ei õnnestunud juurde pääseda.", e); } lõng = uus Lõng (see); thread.start (); } /*** Loeb sõnumeid, kui ühendus teise poolega on elav. */ @Override public void run () {while (! Socket.isClosed ()) {try {int identifier; bait baiti; sünkroniseeritud (readLock) {identifikaator = in.readInt (); int pikkus = in.readInt (); if (pikkus> 0) {baiti = uus bait [pikkus]; in.readFully (baiti, 0, baiti.pikkus); } muu {jätka; }} lüliti (identifikaator) {case Identifier. INTERNAL: String käsk = new String (baiti); if (command.equals ("katkesta ühendus")) {if (! socket.isClosed ()) {System.out.println ("Lahutuspakett on vastu võetud."); proovi {close (); } saak (NetworkException e) {return; }}} vaheaeg; juhtumi identifikaator. TEKST: System.out.println ("Sõnum on vastu võetud:" + uus string (baiti)); murda; vaikimisi: System.out.println ("Vastuvõetud tundmatud andmed."); }} catch (SocketException e) {if (! e.getMessage (). equals ("Socket closed")) {e.printStackTrace (); }} saak (IOException e) {e.printStackTrace (); }}} /*** Saadab andmed teisele poolele. * * @param andmed Saadetavad andmed. * @throws NetworkException Kui väljundvoogu kirjutamine ebaõnnestub. * @throws IllegalStateException Kui ühenduse kirjutamise ajal üritatakse andmeid kirjutada. * @throws IllegalArgumentException Kui saadetavad andmed on tühjad. * @throws UnsupportedOperationException Kui toetamata andmetüüpi üritatakse saata. */ public void send (Objekti andmed) viskab NetworkException {if (socket.isClosed ()) {throws new IllegalStateException ("Andmeid ei saadetud, ühendus on suletud."); } if (andmed == null) {viska uus IllegalArgumentException ("nullandmed"); } int identifikaator; bait baiti; if (stringi andmete eksemplar) {identifier = Identifier. TEXT; baiti = ((string) andmed).getBytes (); } else {viska uus UnsupportedOperationException ("Toetamata andmetüüp:" + data.getClass ()); } proovige {synchronized (writeLock) {out.writeInt (identifikaator); out.writeInt (baiti.pikkus); välja kirjutama (baiti); out.flush (); }} catch (IOException e) {viska uus NetworkException ("Andmeid ei saanud saata.", e); }} /*** Saadab teisele osapoolele katkestusteate ja katkestab ühenduse. */ public void close () viskab NetworkException {if (socket.isClosed ()) {viska uus IllegalStateException ("Ühendus on juba suletud."); } proovige {bait sõnum = "katkesta ühendus".getBytes (); sünkroniseeritud (writeLock) {out.writeInt (Identifier. INTERNAL); out.writeInt (sõnumi.pikkus); out.write (sõnum); out.flush (); }} catch (IOException e) {System.out.println ("Katkestusteadet ei saanud saata."); } proovige {sychronized (writeLock) {out.close (); }} catch (IOException e) {viska uus NetworkException ("Viga ühenduse sulgemisel.", e); } lõpuks {thread.interrupt (); }} /*** Tagastab, kas ühendus teise poolega on elav või mitte. * * @return Tõsi, kui ühendus on elav. Vale, muidu. */ public boolean isConnected () {return! socket.isClosed (); }}
Identifier.java
/** * Klass {@code Identifier} sisaldab konstandeid, mida {@link Connection} kasutab võrgu kaudu saadetud andmete * seeria- ja deserialiseerimiseks. * * @version 1.0 * @see Connection * / public final class Identifier { / ** * Sisemiste sõnumite identifikaator. */ avalik staatiline lõpp int SISEMINE = 1; /*** Tekstisõnumite identifikaator. */ public static final int TEXT = 2; }
NetworkException.java
/*** Klass {@code NetworkException} näitab võrguga seotud viga. * / public class NetworkException laiendab erandit { / *** Loob {@code NetworkException}, mille sõnum on {@code null}. * / public NetworkException () {} / *** Ehitab määratud sõnumiga {@code NetworkException}. * * @param message Sõnum vea kirjeldamiseks. */ public NetworkException (String message) {super (sõnum); } /*** Loob määratud sõnumi ja põhjusega {@code NetworkException}. * * @param message Sõnum vea kirjeldamiseks. * @param põhjus Vea põhjus. */ public NetworkException (String -teade, viskatav põhjus) {super (sõnum, põhjus); } /*** Loob määratud põhjusega {@code NetworkException}. * * @param põhjus Vea põhjus. */ public NetworkException (visatav põhjus) {super (põhjus); }}
KasutamineNäide.java
/*** Klass {@code UsageExample} näitab teenuste {@link Server} ja {@link Client} kasutamist. Selles näites kasutatakse * {@link Thread#sleep (long)}, et tagada iga segmendi täitmine, kuna kiire käivitamine ja sulgemine põhjustab mõne * segmendi täitmata jätmise. * * @version 1.0 * @see Server * @see Client */ public class UsageExample {public static void main (String args) viskab Erand {String host = "localhost"; int port = 10430; Serveriserver = uus Server (host, port); Kliendiklient = uus klient (host, port); Niit.unenägu (100L); client.send ("Tere!"); server.broadcast ("Hei, semu!"); Niit.unenägu (100L); server.disconnect (server.getConnections () [0]); // või klient.close () kliendipoolse serveriga ühenduse katkestamiseks.close (); }}