Tietyllä laitteella suoritettavan koodin kirjoittaminen on erittäin tyydyttävää. Mutta koodin kirjoittaminen, joka suoritetaan useilla toisiinsa kommunikoivilla laitteilla, on yksinkertaisesti elämää vahvistava. Tämä artikkeli opettaa sinulle, miten voit muodostaa yhteyden ja vaihtaa viestejä verkon kautta käyttämällä TCP -protokollaa.
Tässä artikkelissa asennat sovelluksen, joka yhdistää tietokoneesi itseensä ja tekee siitä hullun - keskustele itsesi kanssa. Opit myös eron kahden eniten Java -verkostoitumiseen käytetyn virran välillä ja niiden toiminnan.
Data- ja objektivirrat
Ennen kuin sukellat koodiin, artikkelissa käytettyjen kahden virran ero on erotettava.
Tietovirrat
Tietovirrat käsittelevät alkeellisia tietotyyppejä ja merkkijonoja. Datavirtojen kautta lähetettävät tiedot on sarjoitettava manuaalisesti ja poistettava sarjoista, mikä vaikeuttaa monimutkaisten tietojen siirtämistä. Tietovirrat voivat kuitenkin kommunikoida muilla kielillä kuin Javalla kirjoitettujen palvelimien ja asiakkaiden kanssa. Raakavirrat ovat tältä osin samanlaisia kuin tietovirrat, mutta tietovirrat varmistavat, että tiedot on alustettu alustasta riippumattomalla tavalla, mikä on hyödyllistä, koska molemmat osapuolet voivat lukea lähetetyt tiedot.
Objektivirrat
Objektivirrat käsittelevät primitiivisiä tietotyyppejä ja toteutettavia objekteja
Serialoitavissa
käyttöliittymä. Objektivirtojen kautta lähetetyt tiedot sarjoitetaan ja deserialisoidaan automaattisesti, mikä helpottaa monimutkaisten tietojen siirtämistä. Objektivirrat voivat kuitenkin kommunikoida vain Java -palvelimella kirjoitettujen palvelimien ja asiakkaiden kanssa. Myös,
ObjectOutputStream
alustuksen yhteydessä lähettää otsikon
InputStream
toisen osapuolen, joka alustuksen yhteydessä estää suorituksen, kunnes otsikko on vastaanotettu.
Askeleet
Vaihe 1. Luo luokka
Luo luokka ja anna sille haluamasi nimi. Tässä artikkelissa se nimetään
NetworkAppExample
julkinen luokka NetworkAppExample {}
Vaihe 2. Luo päämenetelmä
Luo päämenetelmä ja ilmoita, että se saattaa heittää poikkeuksia
Poikkeus
tyyppi ja sen alaluokka - kaikki poikkeukset. Tätä pidetään huonona käytäntönä, mutta se voidaan hyväksyä paljaan luun esimerkeissä.
julkinen luokka NetworkAppExample {public static void main (String args) heittää Poikkeus {}}
Vaihe 3. Ilmoita palvelimen osoite
Tässä esimerkissä käytetään paikallista isäntäosoitetta ja mielivaltaista portin numeroa. Portin numeron on oltava välillä 0 - 65535 (mukaan lukien). Vältettävät porttien numerot ovat kuitenkin 0-1023 (mukaan lukien), koska ne ovat varattuja järjestelmäportteja.
public class NetworkAppExample {public static void main (String args) heittää Poikkeus {String host = "localhost"; int -portti = 10430; }}
Vaihe 4. Luo palvelin
Palvelin on sidottu osoitteeseen ja porttiin ja kuuntelee saapuvia yhteyksiä. Java,
ServerSocket
edustaa palvelinpuolen päätepistettä ja sen tehtävänä on hyväksyä uusia yhteyksiä.
ServerSocket
ei ole suoratoistoa tietojen lukemiseen ja lähettämiseen, koska se ei edusta palvelimen ja asiakkaan välistä yhteyttä.
tuo java.net. InetAddress; tuo java.net. ServerSocket; public class NetworkAppExample {public static void main (String args) heittää Poikkeus {String host = "localhost"; int -portti = 10430; ServerSocket -palvelin = uusi ServerSocket (portti, 50, InetAddress.getByName (isäntä)); }}
Vaihe 5. Lokipalvelimen alku
Kirjautumista varten tulosta konsoliin, että palvelin on käynnistetty.
tuo java.net. InetAddress; tuo java.net. ServerSocket; public class NetworkAppExample {public static void main (String args) heittää Poikkeus {String host = "localhost"; int -portti = 10430; ServerSocket -palvelin = uusi ServerSocket (portti, 50, InetAddress.getByName (isäntä)); System.out.println ("Palvelin käynnistetty."); }}
Vaihe 6. Luo asiakas
Asiakas on sidottu palvelimen osoitteeseen ja porttiin ja kuuntelee paketteja (viestejä) yhteyden muodostamisen jälkeen. Java,
Pistorasia
edustaa joko asiakaspuolen päätepistettä, joka on kytketty palvelimeen tai yhteyttä (palvelimelta) asiakkaalle, ja sitä käytetään kommunikoimaan toisessa päässä olevan osapuolen kanssa.
tuo java.net. InetAddress; tuo java.net. ServerSocket; tuo java.net. Socket; public class NetworkAppExample {public static void main (String args) heittää Poikkeus {String host = "localhost"; int -portti = 10430; ServerSocket -palvelin = uusi ServerSocket (portti, 50, InetAddress.getByName (isäntä)); System.out.println ("Palvelin käynnistetty."); Socket client = new Socket (isäntä, portti); }}
Vaihe 7. Lokiyhteysyritys
Tulosta kirjautumista varten konsoliin, että yhteys on muodostettu.
tuo java.net. InetAddress; tuo java.net. ServerSocket; tuo java.net. Socket; public class NetworkAppExample {public static void main (String args) heittää Poikkeus {String host = "localhost"; int -portti = 10430; ServerSocket -palvelin = uusi ServerSocket (portti, 50, InetAddress.getByName (isäntä)); System.out.println ("Palvelin käynnistetty."); Socket client = new Socket (isäntä, portti); System.out.println ("Yhdistetään palvelimeen…"); }}
Vaihe 8. Muodosta yhteys
Asiakkaat eivät koskaan muodosta yhteyttä, ellei palvelin kuuntele ja hyväksy, toisin sanoen muodostaa yhteyksiä. Java -yhteydet muodostetaan käyttämällä
hyväksyä()
menetelmä
ServerSocket
luokka. Menetelmä estää suorituksen, kunnes asiakas muodostaa yhteyden.
tuo java.net. InetAddress; tuo java.net. ServerSocket; tuo java.net. Socket; public class NetworkAppExample {public static void main (String args) heittää Poikkeus {String host = "localhost"; int -portti = 10430; ServerSocket -palvelin = uusi ServerSocket (portti, 50, InetAddress.getByName (isäntä)); System.out.println ("Palvelin käynnistetty."); Socket client = new Socket (isäntä, portti); System.out.println ("Yhdistetään palvelimeen…"); Pistokeliitäntä = server.accept (); }}
Vaihe 9. Kirjaa muodostettu yhteys
Tulosta kirjautumista varten konsoliin, että yhteys palvelimen ja asiakkaan välillä on muodostettu.
tuo java.net. InetAddress; tuo java.net. ServerSocket; tuo java.net. Socket; public class NetworkAppExample {public static void main (String args) heittää Poikkeus {String host = "localhost"; int -portti = 10430; ServerSocket -palvelin = uusi ServerSocket (portti, 50, InetAddress.getByName (isäntä)); System.out.println ("Palvelin käynnistetty."); Socket client = new Socket (isäntä, portti); System.out.println ("Yhdistetään palvelimeen…"); Pistorasiayhteys = server.accept (); System.out.println ("Yhteys muodostettu."); }}
Vaihe 10. Valmistele viestintävirrat
Viestintä tapahtuu virtojen kautta, ja tässä sovelluksessa palvelimen (asiakkaan) ja asiakkaan (yhteys palvelimelta) ja asiakkaan raakavirrat on ketjutettava joko data- tai objektivirtoihin. Muista, että molempien osapuolten on käytettävä samaa virratyyppiä.
-
Tietovirrat
tuo java.io. DataInputStream; tuo java.io. DataOutputStream; tuo java.net. InetAddress; tuo java.net. ServerSocket; tuo java.net. Socket; public class NetworkAppExample {public static void main (String args) heittää Poikkeus {String host = "localhost"; int -portti = 10430; ServerSocket -palvelin = uusi ServerSocket (portti, 50, InetAddress.getByName (isäntä)); System.out.println ("Palvelin käynnistetty."); Socket client = new Socket (isäntä, portti); System.out.println ("Yhdistetään palvelimeen…"); Pistorasiayhteys = server.accept (); System.out.println ("Yhteys muodostettu."); DataOutputStream clientOut = uusi DataOutputStream (client.getOutputStream ()); DataInputStream clientIn = uusi DataInputStream (client.getInputStream ()); DataOutputStream serverOut = uusi DataOutputStream (connection.getOutputStream ()); DataInputStream serverIn = uusi DataInputStream (connection.getInputStream ()); }}
-
Objektivirrat
Kun käytetään useita objektivirtoja, syöttövirrat on alustettava samassa järjestyksessä kuin lähtövirrat, koska
ObjectOutputStream
lähettää otsikon toiselle osapuolelle ja
ObjectInputStream
estää suorituksen, kunnes se lukee otsikon.
tuo java.io. ObjectInputStream; tuo java.io. ObjectOutputStream; tuo java.net. InetAddress; tuo java.net. ServerSocket; tuo java.net. Socket; public class NetworkAppExample {public static void main (String args) heittää Poikkeus {String host = "localhost"; int -portti = 10430; ServerSocket -palvelin = uusi ServerSocket (portti, 50, InetAddress.getByName (isäntä)); System.out.println ("Palvelin käynnistetty."); Socket client = new Socket (isäntä, portti); System.out.println ("Yhdistetään palvelimeen…"); Pistorasiayhteys = server.accept (); System.out.println ("Yhteys muodostettu."); ObjectOutputStream clientOut = uusi ObjectOutputStream (client.getOutputStream ()); ObjectOutputStream serverOut = uusi ObjectOutputStream (connection.getOutputStream ()); ObjectInputStream clientIn = uusi ObjectInputStream (client.getInputStream ()); ObjectInputStream serverIn = uusi ObjectInputStream (connection.getInputStream ()); }}
Yllä olevan koodin mukainen järjestys saattaa olla helpompi muistaa - alusta aluksi lähtövirrat ja syötä virrat samassa järjestyksessä. Toinen järjestys objektivirtojen alustamiseksi on kuitenkin seuraava:
ObjectOutputStream clientOut = uusi ObjectOutputStream (client.getOutputStream ()); ObjectInputStream serverIn = uusi ObjectInputStream (connection.getInputStream ()); ObjectOutputStream serverOut = uusi ObjectOutputStream (connection.getOutputStream ()); ObjectInputStream clientIn = uusi ObjectInputStream (client.getInputStream ());
Vaihe 11. Kirjaa, että tiedonsiirto on valmis
Tulosta kirjautumista varten konsoliin, että tiedonsiirto on valmis.
// koodi puuttui tuonti java.net. InetAddress; tuo java.net. ServerSocket; tuo java.net. Socket; public class NetworkAppExample {public static void main (String args) heittää Poikkeus {String host = "localhost"; int -portti = 10430; ServerSocket -palvelin = uusi ServerSocket (portti, 50, InetAddress.getByName (isäntä)); System.out.println ("Palvelin käynnistetty."); Socket client = new Socket (isäntä, portti); System.out.println ("Yhdistetään palvelimeen…"); Pistorasiayhteys = server.accept (); System.out.println ("Yhteys muodostettu."); // koodi jätetty pois System.out.println ("Tiedonsiirto on valmis."); }}
Vaihe 12. Luo viesti
Tässä sovelluksessa
Hei maailma
teksti lähetetään palvelimelle joko
tavu
tai
Jousisoitin
. Ilmoita tyyppinen muuttuja, joka riippuu käytetystä virrasta. Käyttää
tavu
tietovirtoja ja
Jousisoitin
objektivirtoja varten.
-
Tietovirrat
Datavirtojen avulla sarjoitus tapahtuu muuntamalla objektit alkeellisiksi tietotyypeiksi tai
Jousisoitin
. Tässä tapauksessa,
Jousisoitin
muunnetaan
tavu
kirjoittamisen sijaan
writeBytes ()
tapa näyttää, miten se tehdään muiden objektien, kuten kuvien tai muiden tiedostojen, kanssa.
tuo java.io. DataInputStream; tuo java.io. DataOutputStream; tuo java.net. InetAddress; tuo java.net. ServerSocket; tuo java.net. Socket; public class NetworkAppExample {public static void main (String args) heittää Poikkeus {String host = "localhost"; int -portti = 10430; ServerSocket -palvelin = uusi ServerSocket (portti, 50, InetAddress.getByName (isäntä)); System.out.println ("Palvelin käynnistetty."); Socket client = new Socket (isäntä, portti); System.out.println ("Yhdistetään palvelimeen…"); Pistorasiayhteys = server.accept (); System.out.println ("Yhteys muodostettu."); DataOutputStream clientOut = uusi DataOutputStream (client.getOutputStream ()); DataInputStream clientIn = uusi DataInputStream (client.getInputStream ()); DataOutputStream serverOut = uusi DataOutputStream (connection.getOutputStream ()); DataInputStream serverIn = uusi DataInputStream (connection.getInputStream ()); System.out.println ("Tiedonsiirto on valmis."); tavu messageOut = "Hei maailma".getBytes (); }}
-
Objektivirrat
tuo java.io. ObjectInputStream; tuo java.io. ObjectOutputStream; tuo java.net. InetAddress; tuo java.net. ServerSocket; tuo java.net. Socket; public class NetworkAppExample {public static void main (String args) heittää Poikkeus {String host = "localhost"; int -portti = 10430; ServerSocket -palvelin = uusi ServerSocket (portti, 50, InetAddress.getByName (isäntä)); System.out.println ("Palvelin käynnistetty."); Socket client = new Socket (isäntä, portti); System.out.println ("Yhdistetään palvelimeen…"); Pistorasiayhteys = server.accept (); System.out.println ("Yhteys muodostettu."); ObjectOutputStream clientOut = uusi ObjectOutputStream (client.getOutputStream ()); ObjectOutputStream serverOut = uusi ObjectOutputStream (connection.getOutputStream ()); ObjectInputStream clientIn = uusi ObjectInputStream (client.getInputStream ()); ObjectInputStream serverIn = uusi ObjectInputStream (connection.getInputStream ()); System.out.println ("Tiedonsiirto on valmis."); String messageOut = "Hei maailma"; }}
Vaihe 13. Lähetä viesti
Kirjoita tiedot lähtövirtaan ja huuhtele virta varmistaaksesi, että tiedot on kirjoitettu kokonaan.
-
Tietovirrat
Viestin pituus on lähetettävä ensin, jotta toinen osapuoli tietää kuinka monta tavua se tarvitsee lukea. Kun pituus on lähetetty primitiivisenä kokonaislukutyypinä, tavuja voidaan lähettää.
tuo java.io. DataInputStream; tuo java.io. DataOutputStream; tuo java.net. InetAddress; tuo java.net. ServerSocket; tuo java.net. Socket; public class NetworkAppExample {public static void main (String args) heittää Poikkeus {String host = "localhost"; int -portti = 10430; ServerSocket -palvelin = uusi ServerSocket (portti, 50, InetAddress.getByName (isäntä)); System.out.println ("Palvelin käynnistetty."); Socket client = new Socket (isäntä, portti); System.out.println ("Yhdistetään palvelimeen…"); Pistorasiayhteys = server.accept (); System.out.println ("Yhteys muodostettu."); DataOutputStream clientOut = uusi DataOutputStream (client.getOutputStream ()); DataInputStream clientIn = uusi DataInputStream (client.getInputStream ()); DataOutputStream serverOut = uusi DataOutputStream (connection.getOutputStream ()); DataInputStream serverIn = uusi DataInputStream (connection.getInputStream ()); System.out.println ("Tiedonsiirto on valmis."); tavu messageOut = "Hei maailma".getBytes (); clientOut.writeInt (messageOut.length); clientOut.write (messageOut); clientOut.flush (); }}
-
Objektivirrat
tuo java.io. ObjectInputStream; tuo java.io. ObjectOutputStream; tuo java.net. InetAddress; tuo java.net. ServerSocket; tuo java.net. Socket; public class NetworkAppExample {public static void main (String args) heittää Poikkeus {String host = "localhost"; int -portti = 10430; ServerSocket -palvelin = uusi ServerSocket (portti, 50, InetAddress.getByName (isäntä)); System.out.println ("Palvelin käynnistetty."); Socket client = new Socket (isäntä, portti); System.out.println ("Yhdistetään palvelimeen…"); Pistorasiayhteys = server.accept (); System.out.println ("Yhteys muodostettu."); ObjectOutputStream clientOut = uusi ObjectOutputStream (client.getOutputStream ()); ObjectOutputStream serverOut = uusi ObjectOutputStream (connection.getOutputStream ()); ObjectInputStream clientIn = uusi ObjectInputStream (client.getInputStream ()); ObjectInputStream serverIn = uusi ObjectInputStream (connection.getInputStream ()); System.out.println ("Tiedonsiirto on valmis."); String messageOut = "Hei maailma"; clientOut.writeObject (messageOut); clientOut.flush (); }}
Vaihe 14. Kirjaa lähetetty viesti
Tulosta kirjautumista varten konsoliin, että viesti on lähetetty.
-
Tietovirrat
tuo java.io. DataInputStream; tuo java.io. DataOutputStream; tuo java.net. InetAddress; tuo java.net. ServerSocket; tuo java.net. Socket; public class NetworkAppExample {public static void main (String args) heittää Poikkeus {String host = "localhost"; int -portti = 10430; ServerSocket -palvelin = uusi ServerSocket (portti, 50, InetAddress.getByName (isäntä)); System.out.println ("Palvelin käynnistetty."); Socket client = new Socket (isäntä, portti); System.out.println ("Yhdistetään palvelimeen…"); Pistorasiayhteys = server.accept (); System.out.println ("Yhteys muodostettu."); DataOutputStream clientOut = uusi DataOutputStream (client.getOutputStream ()); DataInputStream clientIn = uusi DataInputStream (client.getInputStream ()); DataOutputStream serverOut = uusi DataOutputStream (connection.getOutputStream ()); DataInputStream serverIn = uusi DataInputStream (connection.getInputStream ()); System.out.println ("Tiedonsiirto on valmis."); tavu messageOut = "Hei maailma".getBytes (); clientOut.writeInt (messageOut.length); clientOut.write (messageOut); clientOut.flush (); System.out.println ("Viesti lähetetty palvelimelle:" + uusi merkkijono (messageOut)); }}
-
Objektivirrat
tuo java.io. ObjectInputStream; tuo java.io. ObjectOutputStream; tuo java.net. InetAddress; tuo java.net. ServerSocket; tuo java.net. Socket; public class NetworkAppExample {public static void main (String args) heittää Poikkeus {String host = "localhost"; int -portti = 10430; ServerSocket -palvelin = uusi ServerSocket (portti, 50, InetAddress.getByName (isäntä)); System.out.println ("Palvelin käynnistetty."); Socket client = new Socket (isäntä, portti); System.out.println ("Yhdistetään palvelimeen…"); Pistorasiayhteys = server.accept (); System.out.println ("Yhteys muodostettu."); ObjectOutputStream clientOut = uusi ObjectOutputStream (client.getOutputStream ()); ObjectOutputStream serverOut = uusi ObjectOutputStream (connection.getOutputStream ()); ObjectInputStream clientIn = uusi ObjectInputStream (client.getInputStream ()); ObjectInputStream serverIn = uusi ObjectInputStream (connection.getInputStream ()); System.out.println ("Tiedonsiirto on valmis."); String messageOut = "Hei maailma"; clientOut.writeObject (messageOut); clientOut.flush (); System.out.println ("Viesti lähetetty palvelimelle:" + messageOut); }}
Vaihe 15. Lue viesti
Lue tiedot syöttövirrasta ja muunna ne. Koska tiedämme tarkasti lähetetyn datan tyypin, luomme joko
Jousisoitin
alkaen
tavu
tai valettu
Esine
kohteeseen
Jousisoitin
tarkistamatta, riippuen käytetystä virrasta.
-
Tietovirrat
Koska pituus lähetettiin ensin ja tavua sen jälkeen, lukeminen on tehtävä samassa järjestyksessä. Jos pituus on nolla, ei ole mitään luettavaa. Objekti deserialisoidaan, kun tavuja muunnetaan takaisin instanssiksi, tässä tapauksessa, of
Jousisoitin
tuo java.io. DataInputStream; tuo java.io. DataOutputStream; tuo java.net. InetAddress; tuo java.net. ServerSocket; tuo java.net. Socket; public class NetworkAppExample {public static void main (String args) heittää Poikkeus {String host = "localhost"; int -portti = 10430; ServerSocket -palvelin = uusi ServerSocket (portti, 50, InetAddress.getByName (isäntä)); System.out.println ("Palvelin käynnistetty."); Socket client = new Socket (isäntä, portti); System.out.println ("Yhdistetään palvelimeen…"); Pistorasiayhteys = server.accept (); System.out.println ("Yhteys muodostettu."); DataOutputStream clientOut = uusi DataOutputStream (client.getOutputStream ()); DataInputStream clientIn = uusi DataInputStream (client.getInputStream ()); DataOutputStream serverOut = uusi DataOutputStream (connection.getOutputStream ()); DataInputStream serverIn = uusi DataInputStream (connection.getInputStream ()); System.out.println ("Tiedonsiirto on valmis."); tavu messageOut = "Hei maailma".getBytes (); clientOut.writeInt (messageOut.length); clientOut.write (messageOut); clientOut.flush (); System.out.println ("Viesti lähetetty palvelimelle:" + uusi merkkijono (messageOut)); int pituus = serverIn.readInt (); if (pituus> 0) {tavu messageIn = uusi tavu [pituus]; serverIn.readFully (messageIn, 0, messageIn.length); }}}
-
Objektivirrat
tuo java.io. ObjectInputStream; tuo java.io. ObjectOutputStream; tuo java.net. InetAddress; tuo java.net. ServerSocket; tuo java.net. Socket; public class NetworkAppExample {public static void main (String args) heittää Poikkeus {String host = "localhost"; int -portti = 10430; ServerSocket -palvelin = uusi ServerSocket (portti, 50, InetAddress.getByName (isäntä)); System.out.println ("Palvelin käynnistetty."); Socket client = new Socket (isäntä, portti); System.out.println ("Yhdistetään palvelimeen…"); Pistorasiayhteys = server.accept (); System.out.println ("Yhteys muodostettu."); ObjectOutputStream clientOut = uusi ObjectOutputStream (client.getOutputStream ()); ObjectOutputStream serverOut = uusi ObjectOutputStream (connection.getOutputStream ()); ObjectInputStream clientIn = uusi ObjectInputStream (client.getInputStream ()); ObjectInputStream serverIn = uusi ObjectInputStream (connection.getInputStream ()); System.out.println ("Tiedonsiirto on valmis."); String messageOut = "Hei maailma"; clientOut.writeObject (messageOut); clientOut.flush (); System.out.println ("Viesti lähetetty palvelimelle:" + messageOut); String messageIn = (String) serverIn.readObject (); }}
Vaihe 16. Luo lokiviesti
Tulosta kirjautumista varten konsoliin, että viesti on vastaanotettu, ja tulosta sen sisältö.
-
Tietovirrat
tuo java.io. DataInputStream; tuo java.io. DataOutputStream; tuo java.net. InetAddress; tuo java.net. ServerSocket; tuo java.net. Socket; public class NetworkAppExample {public static void main (String args) heittää Poikkeus {String host = "localhost"; int -portti = 10430; ServerSocket -palvelin = uusi ServerSocket (portti, 50, InetAddress.getByName (isäntä)); System.out.println ("Palvelin käynnistetty."); Socket client = new Socket (isäntä, portti); System.out.println ("Yhdistetään palvelimeen…"); Pistorasiayhteys = server.accept (); System.out.println ("Yhteys muodostettu."); DataOutputStream clientOut = uusi DataOutputStream (client.getOutputStream ()); DataInputStream clientIn = uusi DataInputStream (client.getInputStream ()); DataOutputStream serverOut = uusi DataOutputStream (connection.getOutputStream ()); DataInputStream serverIn = uusi DataInputStream (connection.getInputStream ()); System.out.println ("Tiedonsiirto on valmis."); tavu messageOut = "Hei maailma".getBytes (); clientOut.writeInt (messageOut.length); clientOut.write (messageOut); clientOut.flush (); System.out.println ("Viesti lähetetty palvelimelle:" + uusi merkkijono (messageOut)); int pituus = serverIn.readInt (); if (pituus> 0) {tavu messageIn = uusi tavu [pituus]; serverIn.readFully (messageIn, 0, messageIn.length); System.out.println ("Viesti vastaanotettu asiakkaalta:" + uusi merkkijono (messageIn)); }}}
-
Objektivirrat
tuo java.io. ObjectInputStream; tuo java.io. ObjectOutputStream; tuo java.net. InetAddress; tuo java.net. ServerSocket; tuo java.net. Socket; public class NetworkAppExample {public static void main (String args) heittää Poikkeus {String host = "localhost"; int -portti = 10430; ServerSocket -palvelin = uusi ServerSocket (portti, 50, InetAddress.getByName (isäntä)); System.out.println ("Palvelin käynnistetty."); Socket client = new Socket (isäntä, portti); System.out.println ("Yhdistetään palvelimeen…"); Pistorasiayhteys = server.accept (); System.out.println ("Yhteys muodostettu."); ObjectOutputStream clientOut = uusi ObjectOutputStream (client.getOutputStream ()); ObjectOutputStream serverOut = uusi ObjectOutputStream (connection.getOutputStream ()); ObjectInputStream clientIn = uusi ObjectInputStream (client.getInputStream ()); ObjectInputStream serverIn = uusi ObjectInputStream (connection.getInputStream ()); System.out.println ("Tiedonsiirto on valmis."); String messageOut = "Hei maailma"; clientOut.writeObject (messageOut); clientOut.flush (); System.out.println ("Viesti lähetetty palvelimelle:" + messageOut); String messageIn = (String) serverIn.readObject (); System.out.println ("Viesti vastaanotettu asiakkaalta:" + messageIn); }}
Vaihe 17. Irrota liitännät
Yhteys katkeaa, kun toinen osapuoli sulkee virtansa. Javassa suljetaan lähtövirta, myös liitetty pistorasia ja tulovirta. Kun osapuoli toisessa päässä huomaa yhteyden olevan kuollut, sen on myös suljettava lähtövirta muistivuotojen estämiseksi.
// koodi puuttui tuonti java.net. InetAddress; tuo java.net. ServerSocket; tuo java.net. Socket; public class NetworkAppExample {public static void main (String args) heittää Poikkeus {String host = "localhost"; int -portti = 10430; ServerSocket -palvelin = uusi ServerSocket (portti, 50, InetAddress.getByName (isäntä)); System.out.println ("Palvelin käynnistetty."); Socket client = new Socket (isäntä, portti); System.out.println ("Yhdistetään palvelimeen…"); Pistorasiayhteys = server.accept (); System.out.println ("Yhteys muodostettu."); // koodi jätetty pois System.out.println ("Tiedonsiirto on valmis."); // koodi puuttui clientOut.close (); serverOut.close (); }}
Vaihe 18. Lokin katkaisu
Kirjautumista varten tulostus konsoliin on katkaistu.
// koodi puuttui tuonti java.net. InetAddress; tuo java.net. ServerSocket; tuo java.net. Socket; public class NetworkAppExample {public static void main (String args) heittää Poikkeus {String host = "localhost"; int -portti = 10430; ServerSocket -palvelin = uusi ServerSocket (portti, 50, InetAddress.getByName (isäntä)); System.out.println ("Palvelin käynnistetty."); Socket client = new Socket (isäntä, portti); System.out.println ("Yhdistetään palvelimeen…"); Pistorasiayhteys = server.accept (); System.out.println ("Yhteys muodostettu."); // koodi jätetty pois System.out.println ("Tiedonsiirto on valmis."); // koodi puuttui clientOut.close (); serverOut.close (); System.out.println ("Yhteydet suljettu."); }}
Vaihe 19. Lopeta palvelin
Yhteydet katkeavat, mutta palvelin on edelleen toiminnassa. Kuten
ServerSocket
ei liity mihinkään streamiin, se on suljettava nimenomaisesti soittamalla
kiinni()
menetelmä.
// koodi puuttui tuonti java.net. InetAddress; tuo java.net. ServerSocket; tuo java.net. Socket; public class NetworkAppExample {public static void main (String args) heittää Poikkeus {String host = "localhost"; int -portti = 10430; ServerSocket -palvelin = uusi ServerSocket (portti, 50, InetAddress.getByName (isäntä)); System.out.println ("Palvelin käynnistetty."); Socket client = new Socket (isäntä, portti); System.out.println ("Yhdistetään palvelimeen…"); Pistorasiayhteys = server.accept (); System.out.println ("Yhteys muodostettu."); // koodi jätetty pois System.out.println ("Tiedonsiirto on valmis."); // koodi puuttui clientOut.close (); serverOut.close (); System.out.println ("Yhteydet suljettu."); server.close (); }}
Vaihe 20. Lokipalvelimen päättäminen
Kirjaamista varten tulostus konsolipalvelimelle on lopetettu.
// koodi puuttui tuonti java.net. InetAddress; tuo java.net. ServerSocket; tuo java.net. Socket; public class NetworkAppExample {public static void main (String args) heittää Poikkeus {String host = "localhost"; int -portti = 10430; ServerSocket -palvelin = uusi ServerSocket (portti, 50, InetAddress.getByName (isäntä)); System.out.println ("Palvelin käynnistetty."); Socket client = new Socket (isäntä, portti); System.out.println ("Yhdistetään palvelimeen…"); Pistorasiayhteys = server.accept (); System.out.println ("Yhteys muodostettu."); // koodi jätetty pois System.out.println ("Tiedonsiirto on valmis."); // koodi puuttui clientOut.close (); serverOut.close (); System.out.println ("Yhteydet suljettu."); server.close (); System.out.println ("Palvelin lopetettu."); }}
Vaihe 21. Käännä ja suorita
Kirjaamisen avulla saimme tietää, onnistuiko sovellus vai ei. Odotettu teho:
Palvelin käynnistyi. Yhdistetään palvelimeen… Yhteys muodostettu. Viestintä on valmis. Viesti lähetetty palvelimelle: Hello World Viesti vastaanotettu asiakkaalta: Hello World Connections suljettu. Palvelin lopetettu.
Jos tuotoksesi ei ole yllä olevan kaltainen, mitä todennäköisesti ei tapahdu, on olemassa muutamia ratkaisuja:
-
Jos lähtö pysähtyy linjalle
Yhteys luotu.
ja objektivirtoja, huuhtele kukin
ObjectOutputStream
- heti alustuksen jälkeen, koska otsikoita ei jostain syystä lähetetty.
-
Jos tulostus tulostuu
java.net. BindException: Osoite on jo käytössä
- valitse toinen portin numero, koska määritetty on jo käytössä.
Vinkkejä
- Yhdistäminen toisen verkon palvelimeen tapahtuu muodostamalla yhteys laitteen ulkoiseen IP -osoitteeseen, jossa on palvelin, jossa on edelleenlähetetty portti.
- Yhdistäminen saman verkon palvelimeen tapahtuu joko muodostamalla yhteys palvelinta käyttävän laitteen yksityiseen IP -osoitteeseen tai välittämällä portti ja muodostamalla yhteys laitteen ulkoiseen IP -osoitteeseen.
- On olemassa ohjelmistoja, kuten Hamachi, jotka mahdollistavat yhteyden muodostamisen palvelimeen eri verkossa ilman portin siirtämistä, mutta se edellyttää ohjelmiston asentamista molempiin laitteisiin.
Esimerkkejä
Verkkosovellusten, jotka käyttävät estävää tuloa/lähtöä, on käytettävä säikeitä. Seuraavat esimerkit esittävät minimalistisen palvelimen ja asiakkaan toteutuksen säikeillä. Verkkokoodi on olennaisesti sama kuin artikkelissa, paitsi että jotkut katkelmat synkronoitiin, siirrettiin säikeisiin ja poikkeuksia käsitellään.
Palvelin.java
tuoda java.io. IOException; tuo java.net. InetAddress; tuo java.net. ServerSocket; tuo java.net. SocketException; tuo java.net. UnknownHostException; tuo java.util. ArrayList; tuonti java.util. Collections; tuonti java.util. List; /*** Luokka {@code Server} edustaa palvelimen päätepistettä verkossa. Kun {@code Server} on sidottu tiettyyn IP * -osoitteeseen ja -porttiin, se muodostaa yhteyden asiakkaisiin ja pystyy kommunikoimaan heidän kanssaan tai katkaisemaan yhteyden. *
* Tämä luokka on langaturvallinen. * * @versio 1.0 * @see Client * @see Connection */ public class Palvelin toteuttaa Runnable {private ServerSocket server; yksityinen lista
yhteydet; yksityinen lanka; yksityinen lopullinen Objektin yhteydetLukko = uusi objekti (); /** * Rakentaa {@code Server} -palvelun, joka on vuorovaikutuksessa asiakkaiden kanssa määritetyllä isäntänimellä ja portilla määritetyn * pyydetyn saapuvien asiakkaiden jonon enimmäispituuden kanssa. * * @param isäntä Isäntäosoite käytettäväksi. * @param -portti Käytettävän portin numero. * @param backlog Pyydetty saapuvien asiakkaiden jonon enimmäispituus. * @throws NetworkException Jos virhe ilmenee palvelinta käynnistettäessä. */ julkinen palvelin (merkkijono isäntä, int -portti, int -kanta) heittää NetworkException {try {server = new ServerSocket (port, backlog, InetAddress.getByName (host)); } saalis (UnknownHostException e) {heittää uusi NetworkException ("Isännän nimeä ei voitu ratkaista:" + isäntä, e); } saalis (IllegalArgumentException e) {heittää uusi NetworkException ("Portin numeron on oltava välillä 0 - 65535 (mukaan lukien):" + portti); } saalis (IOException e) {heittää uusi NetworkException ("Palvelinta ei voitu käynnistää.", e); } yhteydet = Collections.synchronizedList (uusi ArrayList ()); säie = uusi säie (tämä); thread.start (); } /*** Rakentaa {@code Server} -palvelun, joka on vuorovaikutuksessa asiakkaiden kanssa määritetyllä isäntänimellä ja portilla. * * @param isäntä Isäntäosoite sidottavaksi. * @param -portti Sidottava portin numero. * @throws NetworkException Jos palvelimen käynnistyksen yhteydessä ilmenee virheitä. */ julkinen palvelin (merkkijono, int -portti) heittää NetworkException {this (isäntä, portti, 50); } /*** Kuuntelee, hyväksyy ja rekisteröi asiakkailta saapuvat yhteydet. */ @Override public void run () {while (! Server.isClosed ()) {try {connection.add (new Connection (server.accept ()))); } catch (SocketException e) {if (! e.getMessage (). equals ("Socket closed")) {e.printStackTrace (); }} saalis (NetworkException | IOException e) {e.printStackTrace (); }}} /*** Lähettää tietoja kaikille rekisteröityneille asiakkaille. * * @param data Lähetettävät tiedot. * @throws IllegalStateException Jos tietoja yritetään kirjoittaa, kun palvelin on offline -tilassa. * @throws IllegalArgumentException Jos lähetettävät tiedot ovat tyhjiä. */ public void broadcast (Object data) {if (server.isClosed ()) {throws new IllegalStateException ("Tietoja ei lähetetty, palvelin on offline -tilassa."); } if (data == null) {heittää uusi IllegalArgumentException ("null data"); } synkronoitu (connectionLock) {for (Yhteysyhteys: yhteydet) {try {connection.send (data); System.out.println ("Tiedot lähetettiin asiakkaalle onnistuneesti."); } saalis (NetworkException e) {e.printStackTrace (); }}}} /*** Lähettää katkaisuviestin ja katkaisee määritetyn asiakkaan yhteyden. * * @param -yhteys Asiakas irrotettavaksi. * @throws NetworkException Jos yhteys sulkeutuessa ilmenee virhe. */ public void katkaise (Yhteysyhteys) heittää NetworkException {if (yhteydet.poista (yhteys)) {connection.close (); }} /*** Lähettää katkaisuviestin kaikille asiakkaille, katkaisee yhteyden ja sulkee palvelimen. */ public void close () heittää NetworkException {synkronoitu (yhteydetLock) {for (Yhteysyhteys: yhteydet) {try {connection.close (); } saalis (NetworkException e) {e.printStackTrace (); }}} yhteydet. selkeä (); kokeile {server.close (); } saalis (IOException e) {heittää uusi NetworkException ("Virhe suljettaessa palvelinta."); } lopuksi {thread.interrupt (); }} /*** Palauttaa, onko palvelin online -tilassa vai ei. * * @return Totta, jos palvelin on online -tilassa. Väärä, muuten. */ public boolean isOnline () {return! server.isClosed (); } /*** Palauttaa joukon rekisteröityjä asiakkaita. */ julkinen yhteys getConnections () {synkronoitu (yhteydetLock) {palauta yhteydet.toArray (uusi yhteys [yhteydet.koko ()]); }}}
Asiakas.java
tuoda java.io. IOException; tuo java.net. Socket; tuo java.net. UnknownHostException; /*** Luokka {@code Client} edustaa asiakkaan päätepistettä verkossa. Kun {@code Client} on yhdistetty tiettyyn * palvelimeen, se pystyy taatusti kommunikoimaan vain palvelimen kanssa. Saavatko muut asiakkaat tietoja *, riippuu palvelimen toteutuksesta. *
* Tämä luokka on langaturvallinen. * * @versio 1.0 * @näytä palvelin * @näytä yhteys */ julkisen luokan asiakas {yksityinen yhteysyhteys; /*** Luo {@code Client} -palvelimen, joka on yhdistetty palvelimeen määritetyssä isännässä ja portissa. * * @param isäntä Isäntäosoite sidottavaksi. * @param -portti Sidottava portin numero. * @throws NetworkException Jos virhe ilmenee palvelinta käynnistettäessä. */ public Client (String host, int port) heittää NetworkException {try {connection = new Connection (new Socket (host, port)); } saalis (UnknownHostException e) {heittää uusi NetworkException ("Isännän nimeä ei voitu ratkaista:" + isäntä, e); } saalis (IllegalArgumentException e) {heittää uusi NetworkException ("Portin numeron on oltava välillä 0 - 65535 (mukaan lukien):" + portti); } saalis (IOException e) {heittää uusi NetworkException ("Palvelinta ei voitu käynnistää.", e); }} /*** Lähettää tietoja toiselle osapuolelle. * * @param data Lähetettävät tiedot. * @throws NetworkException Jos tulostusvirralle kirjoittaminen epäonnistuu. * @throws IllegalStateException Jos tietoja yritetään kirjoittaa, kun yhteys on suljettu. * @throws IllegalArgumentException Jos lähetettävät tiedot ovat tyhjiä. * @throws UnsupportedOperationException Jos ei -tuettua tietotyyppiä yritetään lähettää. */ public void send (Object data) heittää NetworkException {connection.send (data); } /*** Lähettää katkaisuviestin palvelimelle ja sulkee yhteyden palvelimeen. */ public void close () heittää NetworkException {connection.close (); } /*** Palauttaa, onko asiakas liitetty palvelimeen vai ei. * * @return Totta, jos asiakas on yhteydessä. Väärä, muuten. */ public boolean isOnline () {return connection.isConnected (); } /*** Palauttaa asiakkaan {@link Connection} -ilmentymän. */ public Connection getConnection () {paluuyhteys; }}
Yhteys.java
tuo java.io. DataInputStream; tuo java.io. DataOutputStream; tuoda java.io. IOException; tuo java.net. Socket; tuo java.net. SocketException; /** * Luokka {@code Connection} edustaa joko yhteyttä palvelimelta asiakkaalle tai asiakkaan päätepistettä verkossa * {@code Connection} voi muodostaa yhteyden muodostamisen jälkeen tietoja muiden osapuolten kanssa palvelimen * toteutuksessa. *
* Tämä luokka on langaturvallinen. * * @versio 1.0 * @see Server * @see Client */ public class Yhteysvälineet Runnable {private Socket socket; yksityinen DataOutputStream ulos; yksityinen DataInputStream sisään; yksityinen lanka; private final Object writeLock = uusi objekti (); private final Object readLock = uusi objekti (); /*** Rakentaa {@code Connection} -palvelun määritetyn {@link Socket} -virran avulla. * * @param -pistorasia, josta virrat haetaan.*/ public Connection (Socket socket) heittää NetworkException {if (socket == null) {heittää uuden IllegalArgumentException ("null socket"); } this.socket = pistorasia; try {out = new DataOutputStream (socket.getOutputStream ()); } saalis (IOException e) {heittää uusi NetworkException ("Lähtövirtaa ei voi käyttää.", e); } try {in = new DataInputStream (socket.getInputStream ()); } saalis (IOException e) {heittää uusi NetworkException ("Syöttövirtaa ei voi käyttää.", e); } säie = uusi säie (tämä); thread.start (); } /*** Lukee viestejä, kun yhteys toiseen osapuoleen on elossa. */ @Override public void run () {while (! Socket.isClosed ()) {try {int identifier; tavu tavua; synkronoitu (readLock) {identifier = in.readInt (); int pituus = in.readInt (); if (pituus> 0) {tavua = uusi tavu [pituus]; in.readFully (tavua, 0, tavua.pituus); } muu {jatka; }} switch (identifier) {case Identifier. INTERNAL: String -komento = new String (tavua); if (command.equals ("irrota")) {if (! socket.isClosed ()) {System.out.println ("Katkaisupaketti vastaanotettu."); kokeile {close (); } saalis (NetworkException e) {return; } } } tauko; tapaustunniste. TEKSTI: System.out.println ("Viesti vastaanotettu:" + uusi merkkijono (tavua)); tauko; oletus: System.out.println ("Tuntemattomia tietoja vastaanotettu."); }} catch (SocketException e) {if (! e.getMessage (). equals ("Socket closed")) {e.printStackTrace (); }} saalis (IOException e) {e.printStackTrace (); }}} /*** Lähettää tietoja toiselle osapuolelle. * * @param data Lähetettävät tiedot. * @throws NetworkException Jos tulostusvirralle kirjoittaminen epäonnistuu. * @throws IllegalStateException Jos tietoja yritetään kirjoittaa, kun yhteys on suljettu. * @throws IllegalArgumentException Jos lähetettävät tiedot ovat tyhjiä. * @throws UnsupportedOperationException Jos ei -tuettua tietotyyppiä yritetään lähettää. */ public void send (Objektitiedot) heittää NetworkException {if (socket.isClosed ()) {heittää uuden IllegalStateException ("Tietoja ei lähetetty, yhteys on suljettu."); } if (data == null) {heittää uusi IllegalArgumentException ("null data"); } int -tunniste; tavu tavua; if (merkkijonon dataesimerkki) {identifier = Identifier. TEXT; tavua = ((String) data).getBytes (); } else {heittää uusi UnsupportedOperationException ("Ei tuettu tietotyyppi:" + data.getClass ()); } try {synchronized (writeLock) {out.writeInt (tunniste); out.writeInt (tavua.pituus); out.write (tavua); ulos.huuhtelu (); }} saalis (IOException e) {heittää uusi NetworkException ("Tietoja ei voitu lähettää.", e); }} /*** Lähettää katkaisuviestin toiselle osapuolelle ja sulkee yhteyden siihen. */ public void close () heittää NetworkException {if (socket.isClosed ()) {heittää uuden IllegalStateException ("Yhteys on jo suljettu."); } kokeile {tavu message = "katkaise yhteys".getBytes (); synkronoitu (writeLock) {out.writeInt (Identifier. INTERNAL); out.writeInt (viestin pituus); out.write (viesti); ulos.huuhtelu (); }} catch (IOException e) {System.out.println ("Katkaisusanomaa ei voitu lähettää."); } kokeile {synkronoitu (writeLock) {out.close (); }} saalis (IOException e) {heittää uusi NetworkException ("Virhe yhteyden sulkemisessa.", e); } lopuksi {thread.interrupt (); }} /*** Palauttaa, onko yhteys toiseen osapuoleen elossa vai ei. * * @return Tosi, jos yhteys on elossa. Väärä, muuten. */ public boolean isConnected () {return! socket.isClosed (); }}
Tunniste.java
/** * Luokka {@code Identifier} sisältää vakioita, joita {@link Connection} käyttää verkon kautta lähetettyjen tietojen * sarjoittamiseen ja sarjojen poistamiseen. * * @version 1.0 * @see Connection * / public final class Identifier { / ** * Tunniste sisäisille viesteille. */ julkinen staattinen lopullinen int INTERNAL = 1; /*** Tekstiviestien tunniste. */ public staattinen final int TEXT = 2; }
NetworkException.java
/*** Luokka {@code NetworkException} osoittaa verkkoon liittyvän virheen. * / public class NetworkException laajentaa poikkeusta { / *** Luo {@code NetworkException} -viestin, jonka viesti on {@code null}. * / public NetworkException () {} / *** Luo {@code NetworkException} määritetyn viestin kanssa. * * @param message Viesti virheen kuvaamiseksi. */ public NetworkException (String message) {super (message); } /*** Muodostaa {@code NetworkException} -asetuksen, jossa on määritetty viesti ja syy. * * @param message Viesti virheen kuvaamiseksi. * @param syy Virheen syy. */ public NetworkException (merkkijonoviesti, heitettävä syy) {super (viesti, syy); } /*** Muodostaa {@code NetworkException} -asetuksen määritetyllä syyllä. * * @param syy Virheen syy. */ public NetworkException (Heitettävä syy) {super (syy); }}
Käyttöesimerkki.java
/*** Luokka {@code UsageExample} näyttää osoitteiden {@link Server} ja {@link Client} käytön. Tässä esimerkissä * {@link Thread#sleep (long)} varmistetaan, että jokainen segmentti suoritetaan, koska nopea aloittaminen ja sulkeminen saa jotkin * segmentit suorittamatta. * * @versio 1.0 * @näytä palvelin * @näke asiakas */ public class UsageExample {public static void main (String args) heittää Poikkeus {String host = "localhost"; int -portti = 10430; Palvelinpalvelin = uusi palvelin (isäntä, portti); Asiakasasiakas = uusi asiakas (isäntä, portti); Kierre.unen (100L); client.send ("Hei"); server.broadcast ("Hei, kaveri!"); Kierteet.unen (100L); server.disconnect (server.getConnections () [0]); // tai client.close () katkaistaksesi yhteyden asiakaspuolen palvelimeen.close (); }}