At skrive kode, der udføres på en bestemt enhed, er meget tilfredsstillende. Men at skrive kode, der udføres på flere enheder, der kommunikerer med hinanden, er simpelthen livsbekræftende. Denne artikel lærer dig, hvordan du opretter forbindelse og udveksler meddelelser over netværk ved hjælp af transmissionskontrolprotokol (TCP).
I denne artikel vil du konfigurere et program, der forbinder din computer til sig selv og i det væsentlige gør det vanvittigt - tal med sig selv. Du vil også lære forskellen mellem de to mest udbredte streams til netværk i Java og hvordan de fungerer.
Data- og objektstrømme
Inden du dykker ned i kode, skal forskellen mellem de to strømme, der bruges i artiklen, skelnes.
Datastrømme
Datastrømme behandler primitive datatyper og strenge. Data, der sendes over datastrømme, skal serialiseres og deserialiseres manuelt, hvilket gør det sværere at overføre komplekse data. Men datastrømme kan kommunikere med servere og klienter, der er skrevet på andre sprog end Java. Råstrømme ligner datastrømme i det aspekt, men datastrømme sikrer, at dataene formateres på en platformuafhængig måde, hvilket er fordelagtigt, fordi begge parter vil kunne læse sendte data.
Objektstrømme
Objektstrømme behandler primitive datatyper og objekter, der implementerer
Serialiserbar
grænseflade. Data, der sendes over objektstrømme, serialiseres og deserialiseres automatisk, hvilket gør det lettere at overføre komplekse data. Men objektstrømme kan kun kommunikere med servere og klienter, der er skrevet i Java. Også,
ObjectOutputStream
ved initialisering, sender en overskrift til
InputStream
fra den anden part, der ved initialisering blokerer udførelse, indtil overskriften er modtaget.
Trin
Trin 1. Opret en klasse
Opret en klasse, og navngiv den, som du vil. I denne artikel vil den blive navngivet
NetworkAppExample
public class NetworkAppExample {}
Trin 2. Opret en hovedmetode
Opret en hovedmetode, og erklær, at den kan kaste undtagelser fra
Undtagelse
type og enhver underklasse af den - alle undtagelser. Dette betragtes som en dårlig praksis, men er acceptabelt for barebone -eksempler.
public class NetworkAppExample {public static void main (String args) kaster undtagelse {}}
Trin 3. Angiv serveradresse
Dette eksempel vil bruge lokal værtsadresse og et vilkårligt portnummer. Portnummer skal være i området fra 0 til 65535 (inklusive). Portnumre, der skal undgås, spænder imidlertid fra 0 til 1023 (inklusive), fordi de er reserverede systemporte.
public class NetworkAppExample {public static void main (String args) kaster undtagelse {String host = "localhost"; int port = 10430; }}
Trin 4. Opret en server
Serveren er bundet til adressen og porten og lytter efter indgående forbindelser. I Java,
ServerSocket
repræsenterer slutpunkt på serversiden, og dens funktion er at acceptere nye forbindelser.
ServerSocket
har ikke streams til læsning og afsendelse af data, fordi det ikke repræsenterer forbindelse mellem en server og en klient.
import java.net. InetAddress; import java.net. ServerSocket; public class NetworkAppExample {public static void main (String args) kaster undtagelse {String host = "localhost"; int port = 10430; ServerSocket -server = ny ServerSocket (port, 50, InetAddress.getByName (vært)); }}
Trin 5. Log server start
Til logning skal du udskrive til konsollen, at serveren er startet.
import java.net. InetAddress; import java.net. ServerSocket; public class NetworkAppExample {public static void main (String args) kaster undtagelse {String host = "localhost"; int port = 10430; ServerSocket -server = ny ServerSocket (port, 50, InetAddress.getByName (vært)); System.out.println ("Server startet."); }}
Trin 6. Opret en klient
Klienten er bundet til adressen og porten på en server og lytter efter pakker (meddelelser), efter at forbindelsen er etableret. I Java,
Stikkontakt
repræsenterer enten et slutpunkt på klientsiden, der er forbundet til serveren, eller en forbindelse (fra server) til klienten og bruges til at kommunikere med parten i den anden ende.
import java.net. InetAddress; import java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) kaster undtagelse {String host = "localhost"; int port = 10430; ServerSocket -server = ny ServerSocket (port, 50, InetAddress.getByName (vært)); System.out.println ("Server startet."); Socket -klient = ny Socket (vært, port); }}
Trin 7. Logforbindelsesforsøg
Til logning skal du udskrive til konsollen, at forbindelsen er forsøgt.
import java.net. InetAddress; import java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) kaster undtagelse {String host = "localhost"; int port = 10430; ServerSocket -server = ny ServerSocket (port, 50, InetAddress.getByName (vært)); System.out.println ("Server startet."); Socket -klient = ny Socket (vært, port); System.out.println ("Opretter forbindelse til server …"); }}
Trin 8. Opret forbindelse
Klienter vil aldrig oprette forbindelse, medmindre serveren lytter til og accepterer, med andre ord etablerer, forbindelser. I Java etableres forbindelser vha
acceptere()
metode til
ServerSocket
klasse. Metoden blokerer udførelse, indtil en klient opretter forbindelse.
import java.net. InetAddress; import java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) kaster undtagelse {String host = "localhost"; int port = 10430; ServerSocket -server = ny ServerSocket (port, 50, InetAddress.getByName (vært)); System.out.println ("Server startet."); Socket -klient = ny Socket (vært, port); System.out.println ("Opretter forbindelse til server …"); Socketforbindelse = server.accept (); }}
Trin 9. Log oprettet forbindelse
Til logning skal du udskrive til konsollen, at forbindelsen mellem server og klient er etableret.
import java.net. InetAddress; import java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) kaster undtagelse {String host = "localhost"; int port = 10430; ServerSocket -server = ny ServerSocket (port, 50, InetAddress.getByName (vært)); System.out.println ("Server startet."); Socket -klient = ny Socket (vært, port); System.out.println ("Opretter forbindelse til server …"); Socketforbindelse = server.accept (); System.out.println ("Forbindelse oprettet."); }}
Trin 10. Forbered kommunikationsstrømme
Kommunikation foregår over streams, og i denne applikation skal råstrømme fra (forbindelse fra) server (til klient) og klient kædes til enten data- eller objektstrømme. Husk, at begge parter skal bruge den samme strømtype.
-
Datastrømme
importer java.io. DataInputStream; importer java.io. DataOutputStream; import java.net. InetAddress; import java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) kaster undtagelse {String host = "localhost"; int port = 10430; ServerSocket -server = ny ServerSocket (port, 50, InetAddress.getByName (vært)); System.out.println ("Server startet."); Socket -klient = ny Socket (vært, port); System.out.println ("Opretter forbindelse til server …"); Socketforbindelse = server.accept (); System.out.println ("Forbindelse oprettet."); DataOutputStream clientOut = ny DataOutputStream (client.getOutputStream ()); DataInputStream clientIn = ny DataInputStream (client.getInputStream ()); DataOutputStream serverOut = ny DataOutputStream (connection.getOutputStream ()); DataInputStream serverIn = ny DataInputStream (connection.getInputStream ()); }}
-
Objektstrømme
Når der bruges flere objektstrømme, skal inputstrømme initialiseres i samme rækkefølge som outputstrømme, fordi
ObjectOutputStream
sender en header til den anden part og
ObjectInputStream
blokerer udførelse, indtil den læser overskriften.
import java.io. ObjectInputStream; import java.io. ObjectOutputStream; import java.net. InetAddress; import java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) kaster undtagelse {String host = "localhost"; int port = 10430; ServerSocket -server = ny ServerSocket (port, 50, InetAddress.getByName (vært)); System.out.println ("Server startet."); Socket -klient = ny Socket (vært, port); System.out.println ("Opretter forbindelse til server …"); Socketforbindelse = server.accept (); System.out.println ("Forbindelse oprettet."); ObjectOutputStream clientOut = ny ObjectOutputStream (client.getOutputStream ()); ObjectOutputStream serverOut = ny ObjectOutputStream (connection.getOutputStream ()); ObjectInputStream clientIn = ny ObjectInputStream (client.getInputStream ()); ObjectInputStream serverIn = ny ObjectInputStream (connection.getInputStream ()); }}
Ordre som angivet i koden ovenfor kan være lettere at huske - initialiser først outputstrømme og derefter inputstrømme i samme rækkefølge. En anden ordre til initialisering af objektstrømme er imidlertid følgende:
ObjectOutputStream clientOut = ny ObjectOutputStream (client.getOutputStream ()); ObjectInputStream serverIn = ny ObjectInputStream (connection.getInputStream ()); ObjectOutputStream serverOut = ny ObjectOutputStream (connection.getOutputStream ()); ObjectInputStream clientIn = ny ObjectInputStream (client.getInputStream ());
Trin 11. Log på, at kommunikationen er klar
Til logning skal du udskrive til konsollen, at kommunikationen er klar.
// kode udeladt import java.net. InetAddress; import java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) kaster undtagelse {String host = "localhost"; int port = 10430; ServerSocket -server = ny ServerSocket (port, 50, InetAddress.getByName (vært)); System.out.println ("Server startet."); Socket -klient = ny Socket (vært, port); System.out.println ("Opretter forbindelse til server …"); Socketforbindelse = server.accept (); System.out.println ("Forbindelse oprettet."); // kode udeladt System.out.println ("Kommunikation er klar."); }}
Trin 12. Opret en besked
I denne ansøgning,
Hej Verden
tekst sendes til serveren enten som
byte
eller
Snor
. Angiv en variabel af typen, der afhænger af den anvendte strøm. Brug
byte
til datastrømme og
Snor
til objektstrømme.
-
Datastrømme
Ved hjælp af datastrømme udføres serialisering ved at konvertere objekter til primitive datatyper eller a
Snor
. I dette tilfælde,
Snor
er konverteret til
byte
i stedet for at skrive med
writeBytes ()
metode til at vise, hvordan det ville blive gjort med andre objekter, f.eks. billeder eller andre filer.
importer java.io. DataInputStream; import java.io. DataOutputStream; import java.net. InetAddress; import java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) kaster undtagelse {String host = "localhost"; int port = 10430; ServerSocket -server = ny ServerSocket (port, 50, InetAddress.getByName (vært)); System.out.println ("Server startet."); Socket -klient = ny Socket (vært, port); System.out.println ("Opretter forbindelse til server …"); Socketforbindelse = server.accept (); System.out.println ("Forbindelse oprettet."); DataOutputStream clientOut = ny DataOutputStream (client.getOutputStream ()); DataInputStream clientIn = ny DataInputStream (client.getInputStream ()); DataOutputStream serverOut = ny DataOutputStream (connection.getOutputStream ()); DataInputStream serverIn = ny DataInputStream (connection.getInputStream ()); System.out.println ("Kommunikation er klar."); byte messageOut = "Hello World".getBytes (); }}
-
Objektstrømme
import java.io. ObjectInputStream; import java.io. ObjectOutputStream; import java.net. InetAddress; import java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) kaster undtagelse {String host = "localhost"; int port = 10430; ServerSocket -server = ny ServerSocket (port, 50, InetAddress.getByName (vært)); System.out.println ("Server startet."); Socket -klient = ny Socket (vært, port); System.out.println ("Opretter forbindelse til server …"); Socketforbindelse = server.accept (); System.out.println ("Forbindelse oprettet."); ObjectOutputStream clientOut = ny ObjectOutputStream (client.getOutputStream ()); ObjectOutputStream serverOut = ny ObjectOutputStream (connection.getOutputStream ()); ObjectInputStream clientIn = ny ObjectInputStream (client.getInputStream ()); ObjectInputStream serverIn = ny ObjectInputStream (connection.getInputStream ()); System.out.println ("Kommunikation er klar."); String messageOut = "Hej verden"; }}
Trin 13. Send beskeden
Skriv data til outputstrømmen og skyl strømmen for at sikre, at dataene er blevet skrevet helt.
-
Datastrømme
Beskedets længde skal først sendes, så den anden part ved, hvor mange bytes den skal læse. Efter at længden er sendt som en primitiv heltalstype, kan bytes sendes.
importer java.io. DataInputStream; importer java.io. DataOutputStream; import java.net. InetAddress; import java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) kaster undtagelse {String host = "localhost"; int port = 10430; ServerSocket -server = ny ServerSocket (port, 50, InetAddress.getByName (vært)); System.out.println ("Server startet."); Socket -klient = ny Socket (vært, port); System.out.println ("Opretter forbindelse til server …"); Socketforbindelse = server.accept (); System.out.println ("Forbindelse oprettet."); DataOutputStream clientOut = ny DataOutputStream (client.getOutputStream ()); DataInputStream clientIn = ny DataInputStream (client.getInputStream ()); DataOutputStream serverOut = ny DataOutputStream (connection.getOutputStream ()); DataInputStream serverIn = ny DataInputStream (connection.getInputStream ()); System.out.println ("Kommunikation er klar."); byte messageOut = "Hello World".getBytes (); clientOut.writeInt (messageOut.length); clientOut.write (messageOut); clientOut.flush (); }}
-
Objektstrømme
import java.io. ObjectInputStream; import java.io. ObjectOutputStream; import java.net. InetAddress; import java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) kaster undtagelse {String host = "localhost"; int port = 10430; ServerSocket -server = ny ServerSocket (port, 50, InetAddress.getByName (vært)); System.out.println ("Server startet."); Socket -klient = ny Socket (vært, port); System.out.println ("Opretter forbindelse til server …"); Socketforbindelse = server.accept (); System.out.println ("Forbindelse oprettet."); ObjectOutputStream clientOut = ny ObjectOutputStream (client.getOutputStream ()); ObjectOutputStream serverOut = ny ObjectOutputStream (connection.getOutputStream ()); ObjectInputStream clientIn = ny ObjectInputStream (client.getInputStream ()); ObjectInputStream serverIn = ny ObjectInputStream (connection.getInputStream ()); System.out.println ("Kommunikation er klar."); String messageOut = "Hej verden"; clientOut.writeObject (messageOut); clientOut.flush (); }}
Trin 14. Log sendt besked
Med henblik på logning skal du udskrive den meddelelse, der er sendt til konsollen.
-
Datastrømme
importer java.io. DataInputStream; import java.io. DataOutputStream; import java.net. InetAddress; import java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) kaster undtagelse {String host = "localhost"; int port = 10430; ServerSocket -server = ny ServerSocket (port, 50, InetAddress.getByName (vært)); System.out.println ("Server startet."); Socket -klient = ny Socket (vært, port); System.out.println ("Opretter forbindelse til server …"); Socketforbindelse = server.accept (); System.out.println ("Forbindelse oprettet."); DataOutputStream clientOut = ny DataOutputStream (client.getOutputStream ()); DataInputStream clientIn = ny DataInputStream (client.getInputStream ()); DataOutputStream serverOut = ny DataOutputStream (connection.getOutputStream ()); DataInputStream serverIn = ny DataInputStream (connection.getInputStream ()); System.out.println ("Kommunikation er klar."); byte messageOut = "Hello World".getBytes (); clientOut.writeInt (messageOut.length); clientOut.write (messageOut); clientOut.flush (); System.out.println ("Besked sendt til server:" + ny streng (messageOut)); }}
-
Objektstrømme
import java.io. ObjectInputStream; import java.io. ObjectOutputStream; import java.net. InetAddress; import java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) kaster undtagelse {String host = "localhost"; int port = 10430; ServerSocket -server = ny ServerSocket (port, 50, InetAddress.getByName (vært)); System.out.println ("Server startet."); Socket -klient = ny Socket (vært, port); System.out.println ("Opretter forbindelse til server …"); Socketforbindelse = server.accept (); System.out.println ("Forbindelse oprettet."); ObjectOutputStream clientOut = ny ObjectOutputStream (client.getOutputStream ()); ObjectOutputStream serverOut = ny ObjectOutputStream (connection.getOutputStream ()); ObjectInputStream clientIn = ny ObjectInputStream (client.getInputStream ()); ObjectInputStream serverIn = ny ObjectInputStream (connection.getInputStream ()); System.out.println ("Kommunikation er klar."); String messageOut = "Hej verden"; clientOut.writeObject (messageOut); clientOut.flush (); System.out.println ("Besked sendt til server:" + messageOut); }}
Trin 15. Læs meddelelsen
Læs data fra inputstrømmen, og konverter dem. Da vi præcis kender typen af sendte data, opretter vi enten en
Snor
fra
byte
eller støbt
Objekt
til
Snor
uden at kontrollere, afhængigt af den anvendte strøm.
-
Datastrømme
Da længden først blev sendt og bytes bagefter, skal læsning foretages i samme rækkefølge. Hvis længden er nul, er der intet at læse. Objektet deserialiseres, når bytes konverteres tilbage til en forekomst, i dette tilfælde, af
Snor
importer java.io. DataInputStream; import java.io. DataOutputStream; import java.net. InetAddress; import java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) kaster undtagelse {String host = "localhost"; int port = 10430; ServerSocket -server = ny ServerSocket (port, 50, InetAddress.getByName (vært)); System.out.println ("Server startet."); Socket -klient = ny Socket (vært, port); System.out.println ("Opretter forbindelse til server …"); Socketforbindelse = server.accept (); System.out.println ("Forbindelse oprettet."); DataOutputStream clientOut = ny DataOutputStream (client.getOutputStream ()); DataInputStream clientIn = ny DataInputStream (client.getInputStream ()); DataOutputStream serverOut = ny DataOutputStream (connection.getOutputStream ()); DataInputStream serverIn = ny DataInputStream (connection.getInputStream ()); System.out.println ("Kommunikation er klar."); byte messageOut = "Hello World".getBytes (); clientOut.writeInt (messageOut.length); clientOut.write (messageOut); clientOut.flush (); System.out.println ("Besked sendt til server:" + ny streng (messageOut)); int length = serverIn.readInt (); hvis (længde> 0) {byte messageIn = ny byte [længde]; serverIn.readFully (messageIn, 0, messageIn.length); }}}
-
Objektstrømme
import java.io. ObjectInputStream; import java.io. ObjectOutputStream; import java.net. InetAddress; import java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) kaster undtagelse {String host = "localhost"; int port = 10430; ServerSocket -server = ny ServerSocket (port, 50, InetAddress.getByName (vært)); System.out.println ("Server startet."); Socket -klient = ny Socket (vært, port); System.out.println ("Opretter forbindelse til server …"); Socketforbindelse = server.accept (); System.out.println ("Forbindelse oprettet."); ObjectOutputStream clientOut = ny ObjectOutputStream (client.getOutputStream ()); ObjectOutputStream serverOut = ny ObjectOutputStream (connection.getOutputStream ()); ObjectInputStream clientIn = ny ObjectInputStream (client.getInputStream ()); ObjectInputStream serverIn = ny ObjectInputStream (connection.getInputStream ()); System.out.println ("Kommunikation er klar."); String messageOut = "Hej verden"; clientOut.writeObject (messageOut); clientOut.flush (); System.out.println ("Besked sendt til server:" + messageOut); String messageIn = (String) serverIn.readObject (); }}
Trin 16. Log læs besked
Til logning skal du udskrive den konsol, at meddelelsen er modtaget, og udskrive dens indhold.
-
Datastrømme
importer java.io. DataInputStream; import java.io. DataOutputStream; import java.net. InetAddress; import java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) kaster undtagelse {String host = "localhost"; int port = 10430; ServerSocket -server = ny ServerSocket (port, 50, InetAddress.getByName (vært)); System.out.println ("Server startet."); Socket -klient = ny Socket (vært, port); System.out.println ("Opretter forbindelse til server …"); Socketforbindelse = server.accept (); System.out.println ("Forbindelse oprettet."); DataOutputStream clientOut = ny DataOutputStream (client.getOutputStream ()); DataInputStream clientIn = ny DataInputStream (client.getInputStream ()); DataOutputStream serverOut = ny DataOutputStream (connection.getOutputStream ()); DataInputStream serverIn = ny DataInputStream (connection.getInputStream ()); System.out.println ("Kommunikation er klar."); byte messageOut = "Hello World".getBytes (); clientOut.writeInt (messageOut.length); clientOut.write (messageOut); clientOut.flush (); System.out.println ("Besked sendt til server:" + ny streng (messageOut)); int length = serverIn.readInt (); hvis (længde> 0) {byte messageIn = ny byte [længde]; serverIn.readFully (messageIn, 0, messageIn.length); System.out.println ("Besked modtaget fra klient:" + ny streng (messageIn)); }}}
-
Objektstrømme
import java.io. ObjectInputStream; import java.io. ObjectOutputStream; import java.net. InetAddress; import java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) kaster undtagelse {String host = "localhost"; int port = 10430; ServerSocket -server = ny ServerSocket (port, 50, InetAddress.getByName (vært)); System.out.println ("Server startet."); Socket -klient = ny Socket (vært, port); System.out.println ("Opretter forbindelse til server …"); Socketforbindelse = server.accept (); System.out.println ("Forbindelse oprettet."); ObjectOutputStream clientOut = ny ObjectOutputStream (client.getOutputStream ()); ObjectOutputStream serverOut = ny ObjectOutputStream (connection.getOutputStream ()); ObjectInputStream clientIn = ny ObjectInputStream (client.getInputStream ()); ObjectInputStream serverIn = ny ObjectInputStream (connection.getInputStream ()); System.out.println ("Kommunikation er klar."); String messageOut = "Hej verden"; clientOut.writeObject (messageOut); clientOut.flush (); System.out.println ("Besked sendt til server:" + messageOut); String messageIn = (String) serverIn.readObject (); System.out.println ("Besked modtaget fra klient:" + messageIn); }}
Trin 17. Afbryd forbindelser
Forbindelsen afbrydes, når den ene part lukker sine strømme. I Java lukkes også den tilhørende sokkel og inputstrøm ved at lukke outputstrømmen. Når en part i den anden ende finder ud af, at forbindelsen er død, skal den også lukke sin output -strøm for at forhindre hukommelseslækager.
// kode udeladt import java.net. InetAddress; import java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) kaster undtagelse {String host = "localhost"; int port = 10430; ServerSocket -server = ny ServerSocket (port, 50, InetAddress.getByName (vært)); System.out.println ("Server startet."); Socket -klient = ny Socket (vært, port); System.out.println ("Opretter forbindelse til server …"); Socketforbindelse = server.accept (); System.out.println ("Forbindelse oprettet."); // kode udeladt System.out.println ("Kommunikation er klar."); // kode udeladt clientOut.close (); serverOut.close (); }}
Trin 18. Logafbrydelse
Til logning er forbindelser til print til konsollen blevet afbrudt.
// kode udeladt import java.net. InetAddress; import java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) kaster undtagelse {String host = "localhost"; int port = 10430; ServerSocket -server = ny ServerSocket (port, 50, InetAddress.getByName (vært)); System.out.println ("Server startet."); Socket -klient = ny Socket (vært, port); System.out.println ("Opretter forbindelse til server …"); Socketforbindelse = server.accept (); System.out.println ("Forbindelse oprettet."); // kode udeladt System.out.println ("Kommunikation er klar."); // kode udeladt clientOut.close (); serverOut.close (); System.out.println ("Forbindelser lukket."); }}
Trin 19. Afslut server
Forbindelser er afbrudt, men serveren er stadig i gang. Som
ServerSocket
ikke er forbundet med nogen strøm, skal den eksplicit lukkes ved at ringe
tæt()
metode.
// kode udeladt import java.net. InetAddress; import java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) kaster undtagelse {String host = "localhost"; int port = 10430; ServerSocket -server = ny ServerSocket (port, 50, InetAddress.getByName (vært)); System.out.println ("Server startet."); Socket -klient = ny Socket (vært, port); System.out.println ("Opretter forbindelse til server …"); Socketforbindelse = server.accept (); System.out.println ("Forbindelse oprettet."); // kode udeladt System.out.println ("Kommunikation er klar."); // kode udeladt clientOut.close (); serverOut.close (); System.out.println ("Forbindelser lukket."); server.close (); }}
Trin 20. Log server opsigelse
Til logning er udskrivning til konsolserveren afsluttet.
// kode udeladt import java.net. InetAddress; import java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) kaster undtagelse {String host = "localhost"; int port = 10430; ServerSocket -server = ny ServerSocket (port, 50, InetAddress.getByName (vært)); System.out.println ("Server startet."); Socket -klient = ny Socket (vært, port); System.out.println ("Opretter forbindelse til server …"); Socketforbindelse = server.accept (); System.out.println ("Forbindelse oprettet."); // kode udeladt System.out.println ("Kommunikation er klar."); // kode udeladt clientOut.close (); serverOut.close (); System.out.println ("Forbindelser lukket."); server.close (); System.out.println ("Server afsluttet."); }}
Trin 21. Kompilér og kør
Logning gjorde det muligt for os at vide, om applikationen var vellykket eller ej. Forventet output:
Serveren startede. Opretter forbindelse til serveren … Forbindelse oprettet. Kommunikation er klar. Besked sendt til server: Hello World Besked modtaget fra klient: Hello World Connections lukket. Server afsluttet.
Hvis dit output ikke ligner ovenstående, hvilket sandsynligvis ikke sker, er der et par løsninger:
-
Hvis output stopper ved linjen
Forbindelse etableret.
og objektstrømme bruges, skyl hver
ObjectOutputStream
- umiddelbart efter initialisering, fordi overskrifter af en eller anden grund ikke blev sendt.
-
Hvis output udskrives
java.net. BindException: Adresse, der allerede er i brug
- vælg et andet portnummer, fordi det angivne allerede er brugt.
Tips
- Tilslutning til en server på et andet netværk sker ved at oprette forbindelse til den eksterne IP -adresse på en enhed, der kører serveren, der har en videresendt port.
- Tilslutning til en server på det samme netværk sker ved enten at oprette forbindelse til den private IP -adresse på en enhed, der kører serveren, eller videresende en port og oprette forbindelse til enhedens eksterne IP -adresse.
- Der er software, f.eks. Hamachi, der tillader forbindelse til serveren på et andet netværk uden at videresende en port, men det kræver installation af softwaren på begge enheder.
Eksempler
Netværksapplikationer, der bruger blokerende input/output, skal bruge tråde. Følgende eksempler viser en minimalistisk server- og klientimplementering med tråde. Netværkskode er i det væsentlige den samme som i artiklen, bortset fra at nogle uddrag blev synkroniseret, flyttet til tråde og undtagelser håndteres.
Server.java
import java.io. IOException; import java.net. InetAddress; import java.net. ServerSocket; import java.net. SocketException; import java.net. UnknownHostException; import java.util. ArrayList; import java.util. Collections; import java.util. List; /*** Klassen {@code Server} repræsenterer et serverslutpunkt i et netværk. {@code Server}, når den er bundet til en bestemt IP * -adresse og port, etablerer forbindelser med klienter og kan kommunikere med dem eller afbryde forbindelsen. *
* Denne klasse er trådsikker. * * @version 1.0 * @see Client * @see Connection */ public class Server implementerer Runnable {private ServerSocket server; privat liste
forbindelser; privat tråd; private final Object connectionsLock = new Object (); /** * Konstruerer en {@code Server}, der interagerer med klienter på det angivne værtsnavn og port med den angivne * anmodede maksimale længde for en kø af indgående klienter. * * @param -vært Værtsadresse, der skal bruges. * @param -port Portnummer, der skal bruges. * @param backlog Anmodede om maksimal længde på køen for indgående klienter. * @kaster NetworkException Hvis der opstår fejl under opstart af en server. */ public Server (String host, int port, int backlog) kaster NetworkException {try {server = new ServerSocket (port, backlog, InetAddress.getByName (host)); } catch (UnknownHostException e) {throw new NetworkException ("Værtsnavn kunne ikke løses:" + vært, e); } catch (IllegalArgumentException e) {throw new NetworkException ("Portnummer skal være mellem 0 og 65535 (inklusive):" + port); } catch (IOException e) {throw new NetworkException ("Serveren kunne ikke startes.", e); } forbindelser = Collections.synchronizedList (ny ArrayList ()); tråd = ny tråd (denne); thread.start (); } /*** Konstruerer en {@code Server}, der interagerer med klienter på det angivne værtsnavn og port. * * @param -vært Værtsadresse, der skal bindes. * @param -port Portnummer, der skal bindes. * @kaster NetworkException Hvis der opstår fejl under opstart af en server. */ public Server (String host, int port) kaster NetworkException {dette (host, port, 50); } /*** Lytter efter, accepterer og registrerer indgående forbindelser fra klienter. */ @Override public void run () {while (! Server.isClosed ()) {try {connections.add (new Connection (server.accept ())); } catch (SocketException e) {if (! e.getMessage (). er lig med ("Socket lukket")) {e.printStackTrace (); }} catch (NetworkException | IOException e) {e.printStackTrace (); }}} /*** Sender data til alle registrerede klienter. * * @param data Data, der skal sendes. * @kaster IllegalStateException Hvis der forsøges at skrive data, når serveren er offline. * @throws IllegalArgumentException Hvis data, der skal sendes, er nul. */ public void broadcast (Object data) {if (server.isClosed ()) {throw new IllegalStateException ("Data ikke sendt, serveren er offline."); } if (data == null) {throw new IllegalArgumentException ("null data"); } synkroniseret (connectionsLock) {for (Connection connection: connections) {try {connection.send (data); System.out.println ("Data sendt til klienten med succes."); } catch (NetworkException e) {e.printStackTrace (); }}}} /*** Sender en afbrydelsesmeddelelse og afbryder den angivne klient. * * @param forbindelse Klient til at afbryde forbindelsen. * @kaster NetworkException Hvis der opstår fejl under lukning af forbindelsen. */ public void disconnect (Connection connection) kaster NetworkException {if (connections.remove (forbindelse)) {connection.close (); }} /*** Sender en afbrydelsesmeddelelse til alle klienter, afbryder dem og afslutter serveren. */ public void close () kaster NetworkException {synchronized (connectionsLock) {for (Connection connection: connections) {try {connection.close (); } catch (NetworkException e) {e.printStackTrace (); }}} connections.clear (); prøv {server.close (); } catch (IOException e) {throw new NetworkException ("Fejl under lukning af server."); } endelig {thread.interrupt (); }} /*** Returnerer, om serveren er online eller ej. * * @return Sandt hvis serveren er online. Falsk, ellers. */ public boolean isOnline () {return! server.isClosed (); } /*** Returnerer en række registrerede klienter. */ public Connection getConnections () {synchronized (connectionsLock) {return connections.toArray (new Connection [connections.size ()]); }}}
Client.java
import java.io. IOException; import java.net. Socket; import java.net. UnknownHostException; /*** Klassen {@code Client} repræsenterer et klientslutpunkt i et netværk. {@code Client}, når den først er forbundet til en bestemt * server, kan garanteret kun kommunikere med serveren. Om andre klienter modtager dataene * afhænger af serverimplementeringen. *
* Denne klasse er trådsikker. * * @version 1.0 * @see Server * @see Connection */ public class Client {private Connection connection; /*** Konstruerer en {@code Client}, der er forbundet til serveren på den angivne vært og port. * * @param -vært Værtsadresse, der skal bindes. * @param -port Portnummer, der skal bindes. * @kaster NetworkException Hvis der opstår fejl under opstart af en server. */ public Client (String host, int port) kaster NetworkException {try {connection = new Connection (new Socket (host, port)); } catch (UnknownHostException e) {throw new NetworkException ("Værtsnavn kunne ikke løses:" + vært, e); } catch (IllegalArgumentException e) {throw new NetworkException ("Portnummer skal være mellem 0 og 65535 (inklusive):" + port); } catch (IOException e) {throw new NetworkException ("Serveren kunne ikke startes.", e); }} /*** Sender data til den anden part. * * @param data Data, der skal sendes. * @kaster NetworkException Hvis skrivning til output -stream mislykkes. * @kaster IllegalStateException Hvis der forsøges at skrive data, når forbindelsen lukkes. * @throws IllegalArgumentException Hvis data, der skal sendes, er nul. * @kaster UnsupportedOperationException Hvis der forsøges afsendt datatype, der ikke understøttes. */ public void send (Objektdata) kaster NetworkException {connection.send (data); } /*** Sender en afbrydelsesmeddelelse til og afslutter forbindelsen til serveren. */ public void close () smider NetworkException {connection.close (); } /*** Returnerer, om klienten er forbundet til serveren eller ej. * * @return True, hvis klienten er tilsluttet. Falsk, ellers. */ public boolean isOnline () {returforbindelse.isConnected (); } /*** Returnerer {@link Connection} -forekomsten af klienten. */ public Connection getConnection () {returforbindelse; }}
Forbindelse. Java
importer java.io. DataInputStream; import java.io. DataOutputStream; import java.io. IOException; import java.net. Socket; import java.net. SocketException; /** * Klassen {@code Connection} repræsenterer enten en forbindelse fra server til klient eller et klientslutpunkt i et netværk * {@code Connection}, når den er tilsluttet, er i stand til at udveksle data med andre parter eller parter, afhængigt på en server * implementering. *
* Denne klasse er trådsikker. * * @version 1.0 * @see Server * @see Client */ public class Forbindelse implementerer Runnable {private Socket -stik; private DataOutputStream ud; private DataInputStream i; privat tråd; private final Object writeLock = new Object (); private final Object readLock = new Object (); /*** Konstruerer {@code Connection} ved hjælp af streams af en bestemt {@link Socket}. * * @param socket Socket til at hente streams fra.*/ public Connection (Socket socket) kaster NetworkException {if (socket == null) {throw new IllegalArgumentException ("null socket"); } this.socket = stikkontakt; prøv {out = ny DataOutputStream (socket.getOutputStream ()); } catch (IOException e) {throw new NetworkException ("Kunne ikke få adgang til output stream.", e); } prøv {in = new DataInputStream (socket.getInputStream ()); } catch (IOException e) {throw new NetworkException ("Kunne ikke få adgang til inputstrøm.", e); } tråd = ny tråd (denne); thread.start (); } /*** Læser beskeder, mens forbindelsen til den anden part er i live. */ @Override public void run () {while (! Socket.isClosed ()) {try {int identifier; byte bytes; synkroniseret (readLock) {identifier = in.readInt (); int længde = in.readInt (); hvis (længde> 0) {bytes = ny byte [længde]; in.readFully (bytes, 0, bytes.length); } andet {fortsætte; }} switch (identifier) {case Identifier. INTERNAL: String command = new String (bytes); if (command.equals ("afbryd")) {if (! socket.isClosed ()) {System.out.println ("Afbrydelsespakke modtaget."); prøv {close (); } catch (NetworkException e) {return; } } } pause; case Identifier. TEXT: System.out.println ("Besked modtaget:" + ny streng (bytes)); pause; standard: System.out.println ("Ukendte data modtaget."); }} catch (SocketException e) {if (! e.getMessage (). er lig med ("Socket lukket")) {e.printStackTrace (); }} catch (IOException e) {e.printStackTrace (); }}} /*** Sender data til den anden part. * * @param data Data, der skal sendes. * @kaster NetworkException Hvis skrivning til output -stream mislykkes. * @kaster IllegalStateException Hvis der forsøges at skrive data, når forbindelsen lukkes. * @throws IllegalArgumentException Hvis data, der skal sendes, er nul. * @kaster UnsupportedOperationException Hvis der forsøges afsendt datatype, der ikke understøttes. */ public void send (Object data) kaster NetworkException {if (socket.isClosed ()) {throw new IllegalStateException ("Data ikke sendt, forbindelsen er lukket."); } if (data == null) {throw new IllegalArgumentException ("null data"); } int -id; byte bytes; hvis (data forekomst af streng) {identifier = Identifier. TEXT; bytes = ((String) data).getBytes (); } else {throw new UnsupportedOperationException ("Ikke understøttet datatype:" + data.getClass ()); } prøv {synkroniseret (writeLock) {out.writeInt (identifikator); out.writeInt (bytes.length); out.write (bytes); out.flush (); }} catch (IOException e) {throw new NetworkException ("Data kunne ikke sendes.", e); }} /*** Sender en afbrydelsesmeddelelse til og lukker forbindelsen til den anden part. */ public void close () kaster NetworkException {if (socket.isClosed ()) {throw new IllegalStateException ("Forbindelsen er allerede lukket."); } prøv {byte message = "afbryd".getBytes (); synkroniseret (writeLock) {out.writeInt (Identifier. INTERNAL); out.writeInt (message.length); out.write (besked); out.flush (); }} catch (IOException e) {System.out.println ("Afbrydelsesmeddelelse kunne ikke sendes."); } prøv {synkroniseret (writeLock) {out.close (); }} catch (IOException e) {throw new NetworkException ("Fejl ved lukning af forbindelse.", e); } endelig {thread.interrupt (); }} /*** Returnerer, om forbindelsen til den anden part er i live eller ej. * * @return Sand hvis forbindelsen er i live. Falsk, ellers. */ public boolean isConnected () {return! socket.isClosed (); }}
Identifier.java
/** * Klassen {@code Identifier} indeholder konstanter, der bruges af {@link Connection} til at serialisere og deserialisere de data *, der sendes over netværket. * * @version 1.0 * @see Connection * / public final class Identifier { / ** * Identifier for interne meddelelser. */ public static final int INTERN = 1; /*** Identifikator for tekstbeskeder. */ public static final int TEKST = 2; }
NetworkException.java
/*** Klassen {@code NetworkException} angiver en fejl i forbindelse med netværket. * / public class NetworkException udvider undtagelse { / *** Konstruerer en {@code NetworkException} med {@code null} som besked. * / public NetworkException () {} / *** Konstruerer en {@code NetworkException} med den angivne meddelelse. * * @param -besked En meddelelse til beskrivelse af fejl. */ public NetworkException (strengbesked) {super (meddelelse); } /*** Konstruerer en {@code NetworkException} med den angivne meddelelse og årsag. * * @param -besked En meddelelse til beskrivelse af fejl. * @param årsag En årsag til fejl. */ public NetworkException (strengbesked, årsag, der kan kastes) {super (meddelelse, årsag); } /*** Konstruerer en {@code NetworkException} med den angivne årsag. * * @param årsag En årsag til fejl. */ public NetworkException (årsag, der kan kastes) {super (årsag); }}
UsageExample.java
/*** Klassen {@code UsageExample} viser brugen af {@link Server} og {@link Client}. Disse eksempler bruger * {@link Thread#sleep (lang)} til at sikre, at hvert segment udføres, fordi hurtig start og lukning forårsager, at nogle * segmenter ikke udføres. * * @version 1.0 * @see Server * @see Client */ public class UsageExample {public static void main (String args) kaster undtagelse {String host = "localhost"; int port = 10430; Server server = ny server (vært, port); Klientklient = ny klient (vært, port); Tråd. Søvn (100L); client.send ("Hej."); server.broadcast ("Hey, fyr!"); Tråd. Søvn (100L); server.disconnect (server.getConnections () [0]); // eller client.close () for at afbryde forbindelsen til server.close () på klientsiden; }}