Å skrive kode som kjøres på en bestemt enhet er veldig tilfredsstillende. Men å skrive kode som kjøres på flere enheter som kommuniserer med hverandre er ganske enkelt livsbekreftende. Denne artikkelen vil lære deg hvordan du kobler til og utveksler meldinger over nettverk ved hjelp av overføringskontrollprotokoll (TCP).
I denne artikkelen vil du sette opp et program som vil koble datamaskinen til seg selv og i hovedsak gjøre den gal - snakk til seg selv. Du vil også lære forskjellen mellom de to mest brukte strømmer for nettverk i Java og hvordan de fungerer.
Data- og objektstrømmer
Før du dykker ned i kode, må forskjellen mellom de to strømmer som brukes i artikkelen skilles.
Datastrømmer
Datastrømmer behandler primitive datatyper og strenger. Data som sendes over datastrømmer må manuelt serialiseres og deserialiseres, noe som gjør det vanskeligere å overføre komplekse data. Men datastrømmer kan kommunisere med servere og klienter skrevet på andre språk enn Java. Råstrømmer ligner datastrømmer i det aspektet, men datastrømmer sikrer at dataene formateres på en plattformuavhengig måte, noe som er fordelaktig fordi begge parter vil kunne lese sendte data.
Objektstrømmer
Objektstrømmer behandler primitive datatyper og objekter som implementerer
Serialiserbar
grensesnitt. Data som sendes over objektstrømmer blir automatisk seriell og deserialisert, noe som gjør det lettere å overføre komplekse data. Men objektstrømmer kan bare kommunisere med servere og klienter skrevet i Java. Også,
ObjectOutputStream
ved initialisering, sender en overskrift til
InputStream
av den andre parten, som ved initialisering blokkerer kjøring til overskriften er mottatt.
Trinn
Trinn 1. Lag en klasse
Lag en klasse og navngi den som du vil. I denne artikkelen vil den bli navngitt
NetworkAppExample
offentlig klasse NetworkAppExample {}
Trinn 2. Lag en hovedmetode
Lag en hovedmetode og erklær at den kan kaste unntak fra
Unntak
type og enhver underklasse av den - alle unntak. Dette regnes som en dårlig praksis, men er akseptabelt for barebone -eksempler.
public class NetworkAppExample {public static void main (String args) kaster unntak {}}
Trinn 3. Angi serveradresse
Dette eksemplet vil bruke lokal vertsadresse og et vilkårlig portnummer. Portnummer må være i området fra 0 til 65535 (inkludert). Imidlertid varierer portnumre fra 0 til 1023 (inkludert) fordi de er reserverte systemporter.
public class NetworkAppExample {public static void main (String args) kaster Unntak {String host = "localhost"; int port = 10430; }}
Trinn 4. Opprett en server
Serveren er bundet til adressen og porten og lytter etter innkommende tilkoblinger. I Java,
ServerSocket
representerer endepunktet på serversiden, og funksjonen er å godta nye tilkoblinger.
ServerSocket
har ikke strømmer for lesing og sending av data fordi den ikke representerer tilkobling mellom en server og en klient.
importer java.net. InetAddress; importer java.net. ServerSocket; public class NetworkAppExample {public static void main (String args) kaster Unntak {String host = "localhost"; int port = 10430; ServerSocket -server = ny ServerSocket (port, 50, InetAddress.getByName (vert)); }}
Trinn 5. Start av loggserver
For loggformål, skriv ut til konsollen at serveren er startet.
importer java.net. InetAddress; importer java.net. ServerSocket; public class NetworkAppExample {public static void main (String args) kaster Unntak {String host = "localhost"; int port = 10430; ServerSocket -server = ny ServerSocket (port, 50, InetAddress.getByName (vert)); System.out.println ("Server startet."); }}
Trinn 6. Opprett en klient
Klienten er bundet til adressen og porten til en server og lytter etter pakker (meldinger) etter at tilkoblingen er opprettet. I Java,
Stikkontakt
representerer enten et endepunkt på klientsiden som er koblet til serveren eller en tilkobling (fra server) til klient og brukes til å kommunisere med parten i den andre enden.
importer java.net. InetAddress; importer java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) kaster Unntak {String host = "localhost"; int port = 10430; ServerSocket -server = ny ServerSocket (port, 50, InetAddress.getByName (vert)); System.out.println ("Server startet."); Socket -klient = ny Socket (vert, port); }}
Trinn 7. Loggforsøk
For loggformål, skriv ut til konsollen at tilkoblingen er forsøkt.
importer java.net. InetAddress; importer java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) kaster Unntak {String host = "localhost"; int port = 10430; ServerSocket -server = ny ServerSocket (port, 50, InetAddress.getByName (vert)); System.out.println ("Server startet."); Socket -klient = ny Socket (vert, port); System.out.println ("Kobler til server …"); }}
Trinn 8. Etabler tilkobling
Klienter vil aldri koble til med mindre serveren lytter etter og godtar, med andre ord, etablerer tilkoblinger. I Java etableres tilkoblinger med
aksepterer()
Metode av
ServerSocket
klasse. Metoden vil blokkere utførelsen til en klient kobler seg til.
importer java.net. InetAddress; importer java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) kaster Unntak {String host = "localhost"; int port = 10430; ServerSocket -server = ny ServerSocket (port, 50, InetAddress.getByName (vert)); System.out.println ("Server startet."); Socket -klient = ny Socket (vert, port); System.out.println ("Kobler til server …"); Socket -tilkobling = server.accept (); }}
Trinn 9. Logg etablert tilkobling
For loggformål, skriv ut til konsollen at forbindelsen mellom server og klient er etablert.
importer java.net. InetAddress; importer java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) kaster Unntak {String host = "localhost"; int port = 10430; ServerSocket -server = ny ServerSocket (port, 50, InetAddress.getByName (vert)); System.out.println ("Server startet."); Socket -klient = ny Socket (vert, port); System.out.println ("Kobler til server …"); Socket -tilkobling = server.accept (); System.out.println ("Tilkobling etablert."); }}
Trinn 10. Forbered kommunikasjonsstrømmer
Kommunikasjon skjer over strømmer, og i denne applikasjonen må råstrømmer fra (tilkobling fra) server (til klient) og klient lenkes til data- eller objektstrømmer. Husk at begge parter må bruke samme strømtype.
-
Datastrømmer
importer java.io. DataInputStream; importer java.io. DataOutputStream; importer java.net. InetAddress; importer java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) kaster Unntak {String host = "localhost"; int port = 10430; ServerSocket -server = ny ServerSocket (port, 50, InetAddress.getByName (vert)); System.out.println ("Server startet."); Socket -klient = ny Socket (vert, port); System.out.println ("Kobler til server …"); Socket -tilkobling = server.accept (); System.out.println ("Tilkobling etablert."); 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ømmer
Når flere objektstrømmer brukes, må inndatastrømmer initialiseres i samme rekkefølge som utgangsstrømmer fordi
ObjectOutputStream
sender en header til den andre parten og
ObjectInputStream
blokkerer kjøring til den leser overskriften.
importer java.io. ObjectInputStream; importer java.io. ObjectOutputStream; importer java.net. InetAddress; importer java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) kaster Unntak {String host = "localhost"; int port = 10430; ServerSocket -server = ny ServerSocket (port, 50, InetAddress.getByName (vert)); System.out.println ("Server startet."); Socket -klient = ny Socket (vert, port); System.out.println ("Kobler til server …"); Socket -tilkobling = server.accept (); System.out.println ("Tilkobling etablert."); ObjectOutputStream clientOut = ny ObjectOutputStream (client.getOutputStream ()); ObjectOutputStream serverOut = ny ObjectOutputStream (connection.getOutputStream ()); ObjectInputStream clientIn = nytt ObjectInputStream (client.getInputStream ()); ObjectInputStream serverIn = nytt ObjectInputStream (connection.getInputStream ()); }}
Rekkefølgen som er angitt i koden ovenfor, kan være lettere å huske - initialiser først utgangsstrømmer og deretter inndatastrømmer i samme rekkefølge. En annen ordre for initialisering av objektstrømmer er imidlertid følgende:
ObjectOutputStream clientOut = ny ObjectOutputStream (client.getOutputStream ()); ObjectInputStream serverIn = nytt ObjectInputStream (connection.getInputStream ()); ObjectOutputStream serverOut = ny ObjectOutputStream (connection.getOutputStream ()); ObjectInputStream clientIn = nytt ObjectInputStream (client.getInputStream ());
Trinn 11. Logg på at kommunikasjonen er klar
For loggformål, skriv ut til konsollen at kommunikasjonen er klar.
// kode utelatt import java.net. InetAddress; importer java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) kaster Unntak {String host = "localhost"; int port = 10430; ServerSocket -server = ny ServerSocket (port, 50, InetAddress.getByName (vert)); System.out.println ("Server startet."); Socket -klient = ny Socket (vert, port); System.out.println ("Kobler til server …"); Socket -tilkobling = server.accept (); System.out.println ("Tilkobling etablert."); // kode utelatt System.out.println ("Kommunikasjon er klar."); }}
Trinn 12. Lag en melding
I denne applikasjonen,
Hei Verden
teksten vil bli sendt til serveren enten som
byte
eller
String
. Angi en variabel av typen som er avhengig av strømmen som brukes. Bruk
byte
for datastrømmer og
String
for objektstrømmer.
-
Datastrømmer
Ved hjelp av datastrømmer utføres serialisering ved å konvertere objekter til primitive datatyper eller a
String
. I dette tilfellet,
String
blir konvertert til
byte
i stedet for å skrive med
writeBytes ()
metode for å vise hvordan det ville bli gjort med andre objekter, for eksempel bilder eller andre filer.
importer java.io. DataInputStream; importer java.io. DataOutputStream; importer java.net. InetAddress; importer java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) kaster Unntak {String host = "localhost"; int port = 10430; ServerSocket -server = ny ServerSocket (port, 50, InetAddress.getByName (vert)); System.out.println ("Server startet."); Socket -klient = ny Socket (vert, port); System.out.println ("Kobler til server …"); Socket -tilkobling = server.accept (); System.out.println ("Tilkobling etablert."); 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 ("Kommunikasjon er klar."); byte messageOut = "Hello World".getBytes (); }}
-
Objektstrømmer
importer java.io. ObjectInputStream; importer java.io. ObjectOutputStream; importer java.net. InetAddress; importer java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) kaster Unntak {String host = "localhost"; int port = 10430; ServerSocket -server = ny ServerSocket (port, 50, InetAddress.getByName (vert)); System.out.println ("Server startet."); Socket -klient = ny Socket (vert, port); System.out.println ("Kobler til server …"); Socket -tilkobling = server.accept (); System.out.println ("Tilkobling etablert."); ObjectOutputStream clientOut = ny ObjectOutputStream (client.getOutputStream ()); ObjectOutputStream serverOut = ny ObjectOutputStream (connection.getOutputStream ()); ObjectInputStream clientIn = nytt ObjectInputStream (client.getInputStream ()); ObjectInputStream serverIn = nytt ObjectInputStream (connection.getInputStream ()); System.out.println ("Kommunikasjon er klar."); String messageOut = "Hei verden"; }}
Trinn 13. Send meldingen
Skriv data til utgangsstrømmen og skyll strømmen for å sikre at dataene er skrevet helt.
-
Datastrømmer
Lengden på en melding må sendes først slik at den andre parten vet hvor mange byte den trenger å lese. Etter at lengden er sendt som en primitiv heltallstype, kan byte sendes.
importer java.io. DataInputStream; importer java.io. DataOutputStream; importer java.net. InetAddress; importer java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) kaster Unntak {String host = "localhost"; int port = 10430; ServerSocket -server = ny ServerSocket (port, 50, InetAddress.getByName (vert)); System.out.println ("Server startet."); Socket -klient = ny Socket (vert, port); System.out.println ("Kobler til server …"); Socket -tilkobling = server.accept (); System.out.println ("Tilkobling etablert."); 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 ("Kommunikasjon er klar."); byte messageOut = "Hello World".getBytes (); clientOut.writeInt (messageOut.length); clientOut.write (messageOut); clientOut.flush (); }}
-
Objektstrømmer
importer java.io. ObjectInputStream; importer java.io. ObjectOutputStream; importer java.net. InetAddress; importer java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) kaster Unntak {String host = "localhost"; int port = 10430; ServerSocket -server = ny ServerSocket (port, 50, InetAddress.getByName (vert)); System.out.println ("Server startet."); Socket -klient = ny Socket (vert, port); System.out.println ("Kobler til server …"); Socket -tilkobling = server.accept (); System.out.println ("Tilkobling etablert."); ObjectOutputStream clientOut = ny ObjectOutputStream (client.getOutputStream ()); ObjectOutputStream serverOut = ny ObjectOutputStream (connection.getOutputStream ()); ObjectInputStream clientIn = nytt ObjectInputStream (client.getInputStream ()); ObjectInputStream serverIn = nytt ObjectInputStream (connection.getInputStream ()); System.out.println ("Kommunikasjon er klar."); String messageOut = "Hei verden"; clientOut.writeObject (messageOut); clientOut.flush (); }}
Trinn 14. Logg sendt melding
For loggformål, skriver du ut til konsollen at meldingen er sendt.
-
Datastrømmer
importer java.io. DataInputStream; importer java.io. DataOutputStream; importer java.net. InetAddress; importer java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) kaster Unntak {String host = "localhost"; int port = 10430; ServerSocket -server = ny ServerSocket (port, 50, InetAddress.getByName (vert)); System.out.println ("Server startet."); Socket -klient = ny Socket (vert, port); System.out.println ("Kobler til server …"); Socket -tilkobling = server.accept (); System.out.println ("Tilkobling etablert."); 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 ("Kommunikasjon er klar."); byte messageOut = "Hello World".getBytes (); clientOut.writeInt (messageOut.length); clientOut.write (messageOut); clientOut.flush (); System.out.println ("Melding sendt til server:" + ny streng (meldingOut)); }}
-
Objektstrømmer
importer java.io. ObjectInputStream; importer java.io. ObjectOutputStream; importer java.net. InetAddress; importer java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) kaster Unntak {String host = "localhost"; int port = 10430; ServerSocket -server = ny ServerSocket (port, 50, InetAddress.getByName (vert)); System.out.println ("Server startet."); Socket -klient = ny Socket (vert, port); System.out.println ("Kobler til server …"); Socket -tilkobling = server.accept (); System.out.println ("Tilkobling etablert."); ObjectOutputStream clientOut = ny ObjectOutputStream (client.getOutputStream ()); ObjectOutputStream serverOut = ny ObjectOutputStream (connection.getOutputStream ()); ObjectInputStream clientIn = nytt ObjectInputStream (client.getInputStream ()); ObjectInputStream serverIn = nytt ObjectInputStream (connection.getInputStream ()); System.out.println ("Kommunikasjon er klar."); String messageOut = "Hei verden"; clientOut.writeObject (messageOut); clientOut.flush (); System.out.println ("Melding sendt til server:" + meldingOut); }}
Trinn 15. Les meldingen
Les data fra inndatastrømmen og konverter dem. Siden vi vet nøyaktig hvilken type sendte data, vil vi enten opprette en
String
fra
byte
eller støpt
Gjenstand
til
String
uten å sjekke, avhengig av strømmen som brukes.
-
Datastrømmer
Siden lengden ble sendt først og byte etterpå, må lesingen gjøres i samme rekkefølge. Hvis lengden er null, er det ingenting å lese. Objektet deserialiseres når byte konverteres tilbake til en forekomst, i dette tilfellet av
String
importer java.io. DataInputStream; importer java.io. DataOutputStream; importer java.net. InetAddress; importer java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) kaster Unntak {String host = "localhost"; int port = 10430; ServerSocket -server = ny ServerSocket (port, 50, InetAddress.getByName (vert)); System.out.println ("Server startet."); Socket -klient = ny Socket (vert, port); System.out.println ("Kobler til server …"); Socket -tilkobling = server.accept (); System.out.println ("Tilkobling etablert."); 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 ("Kommunikasjon er klar."); byte messageOut = "Hello World".getBytes (); clientOut.writeInt (messageOut.length); clientOut.write (messageOut); clientOut.flush (); System.out.println ("Melding sendt til server:" + ny streng (meldingOut)); int length = serverIn.readInt (); if (lengde> 0) {byte meldingIn = ny byte [lengde]; serverIn.readFully (messageIn, 0, messageIn.length); }}}
-
Objektstrømmer
importer java.io. ObjectInputStream; importer java.io. ObjectOutputStream; importer java.net. InetAddress; importer java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) kaster Unntak {String host = "localhost"; int port = 10430; ServerSocket -server = ny ServerSocket (port, 50, InetAddress.getByName (vert)); System.out.println ("Server startet."); Socket -klient = ny Socket (vert, port); System.out.println ("Kobler til server …"); Socket -tilkobling = server.accept (); System.out.println ("Tilkobling etablert."); ObjectOutputStream clientOut = ny ObjectOutputStream (client.getOutputStream ()); ObjectOutputStream serverOut = ny ObjectOutputStream (connection.getOutputStream ()); ObjectInputStream clientIn = nytt ObjectInputStream (client.getInputStream ()); ObjectInputStream serverIn = nytt ObjectInputStream (connection.getInputStream ()); System.out.println ("Kommunikasjon er klar."); String messageOut = "Hei verden"; clientOut.writeObject (messageOut); clientOut.flush (); System.out.println ("Melding sendt til server:" + meldingOut); String messageIn = (String) serverIn.readObject (); }}
Trinn 16. Logg lest melding
For loggformål, skriv ut til konsollen at meldingen er mottatt og skriv ut innholdet.
-
Datastrømmer
importer java.io. DataInputStream; importer java.io. DataOutputStream; importer java.net. InetAddress; importer java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) kaster Unntak {String host = "localhost"; int port = 10430; ServerSocket -server = ny ServerSocket (port, 50, InetAddress.getByName (vert)); System.out.println ("Server startet."); Socket -klient = ny Socket (vert, port); System.out.println ("Kobler til server …"); Socket -tilkobling = server.accept (); System.out.println ("Tilkobling etablert."); 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 ("Kommunikasjon er klar."); byte messageOut = "Hello World".getBytes (); clientOut.writeInt (messageOut.length); clientOut.write (messageOut); clientOut.flush (); System.out.println ("Melding sendt til server:" + ny streng (meldingOut)); int length = serverIn.readInt (); if (lengde> 0) {byte meldingIn = ny byte [lengde]; serverIn.readFully (messageIn, 0, messageIn.length); System.out.println ("Melding mottatt fra klient:" + ny streng (meldingIn)); }}}
-
Objektstrømmer
importer java.io. ObjectInputStream; importer java.io. ObjectOutputStream; importer java.net. InetAddress; importer java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) kaster Unntak {String host = "localhost"; int port = 10430; ServerSocket -server = ny ServerSocket (port, 50, InetAddress.getByName (vert)); System.out.println ("Server startet."); Socket -klient = ny Socket (vert, port); System.out.println ("Kobler til server …"); Socket -tilkobling = server.accept (); System.out.println ("Tilkobling etablert."); ObjectOutputStream clientOut = ny ObjectOutputStream (client.getOutputStream ()); ObjectOutputStream serverOut = ny ObjectOutputStream (connection.getOutputStream ()); ObjectInputStream clientIn = nytt ObjectInputStream (client.getInputStream ()); ObjectInputStream serverIn = nytt ObjectInputStream (connection.getInputStream ()); System.out.println ("Kommunikasjon er klar."); String messageOut = "Hei verden"; clientOut.writeObject (messageOut); clientOut.flush (); System.out.println ("Melding sendt til server:" + meldingOut); String messageIn = (String) serverIn.readObject (); System.out.println ("Melding mottatt fra klient:" + meldingIn); }}
Trinn 17. Koble fra tilkoblingene
Tilkoblingen kobles fra når en part stenger strømmen. I Java, ved å lukke utstrømmen, blir også tilhørende sokkel og inngangsstrøm lukket. Når en part i den andre enden finner ut at tilkoblingen er død, må den også lukke utgangsstrømmen for å forhindre minnelekkasjer.
// kode utelatt import java.net. InetAddress; importer java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) kaster Unntak {String host = "localhost"; int port = 10430; ServerSocket -server = ny ServerSocket (port, 50, InetAddress.getByName (vert)); System.out.println ("Server startet."); Socket -klient = ny Socket (vert, port); System.out.println ("Kobler til server …"); Socket -tilkobling = server.accept (); System.out.println ("Tilkobling etablert."); // kode utelatt System.out.println ("Kommunikasjon er klar."); // kode utelatt clientOut.close (); serverOut.close (); }}
Trinn 18. Loggfrakobling
For loggingsformål har tilkoblingen for utskrift til konsollen blitt koblet fra.
// kode utelatt import java.net. InetAddress; importer java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) kaster Unntak {String host = "localhost"; int port = 10430; ServerSocket -server = ny ServerSocket (port, 50, InetAddress.getByName (vert)); System.out.println ("Server startet."); Socket -klient = ny Socket (vert, port); System.out.println ("Kobler til server …"); Socket -tilkobling = server.accept (); System.out.println ("Tilkobling etablert."); // kode utelatt System.out.println ("Kommunikasjon er klar."); // kode utelatt clientOut.close (); serverOut.close (); System.out.println ("Tilkoblinger stengt."); }}
Trinn 19. Avslutt serveren
Tilkoblinger er frakoblet, men serveren er fremdeles i gang. Som
ServerSocket
er ikke knyttet til noen strøm, må den eksplisitt lukkes ved å ringe
Lukk()
metode.
// kode utelatt import java.net. InetAddress; importer java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) kaster Unntak {String host = "localhost"; int port = 10430; ServerSocket -server = ny ServerSocket (port, 50, InetAddress.getByName (vert)); System.out.println ("Server startet."); Socket -klient = ny Socket (vert, port); System.out.println ("Kobler til server …"); Socket -tilkobling = server.accept (); System.out.println ("Tilkobling etablert."); // kode utelatt System.out.println ("Kommunikasjon er klar."); // kode utelatt clientOut.close (); serverOut.close (); System.out.println ("Tilkoblinger stengt."); server.close (); }}
Trinn 20. Avslutning av loggserver
For logging er utskriften til konsollserveren avsluttet.
// kode utelatt import java.net. InetAddress; importer java.net. ServerSocket; import java.net. Socket; public class NetworkAppExample {public static void main (String args) kaster Unntak {String host = "localhost"; int port = 10430; ServerSocket -server = ny ServerSocket (port, 50, InetAddress.getByName (vert)); System.out.println ("Server startet."); Socket -klient = ny Socket (vert, port); System.out.println ("Kobler til server …"); Socket -tilkobling = server.accept (); System.out.println ("Tilkobling etablert."); // kode utelatt System.out.println ("Kommunikasjon er klar."); // kode utelatt clientOut.close (); serverOut.close (); System.out.println ("Tilkoblinger stengt."); server.close (); System.out.println ("Server avsluttet."); }}
Trinn 21. Kompiler og kjør
Logging gjorde det mulig for oss å vite om programmet var vellykket eller ikke. Forventet produksjon:
Serveren startet. Kobler til serveren … Tilkoblingen er opprettet. Kommunikasjon er klar. Melding sendt til server: Hello World Melding mottatt fra klient: Hello World Connections stengt. Serveren ble avsluttet.
Hvis utgangen din ikke er som den ovenfor, noe som neppe kommer til å skje, er det noen få løsninger:
-
Hvis utgangen stopper på linjen
Forbindelse opprettet.
og objektstrømmer brukes, skyll hver
ObjectOutputStream
- umiddelbart etter initialisering fordi overskrifter av en eller annen grunn ikke ble sendt.
-
Hvis utskriften skrives ut
java.net. BindException: Adresse som allerede er i bruk
- velg et annet portnummer fordi det angitte allerede er brukt.
Tips
- Koble til en server på et annet nettverk gjøres ved å koble til den eksterne IP -adressen til en enhet som kjører serveren som har en videresendt port.
- Koble til en server på samme nettverk gjøres ved enten å koble til den private IP -adressen til en enhet som kjører serveren eller videresende en port og koble til den eksterne IP -adressen til enheten.
- Det er programvare, for eksempel Hamachi, som tillater tilkobling til serveren på et annet nettverk uten å videresende en port, men det krever installasjon av programvaren på begge enhetene.
Eksempler
Nettverksprogrammer som bruker blokkerende inngang/utgang må bruke tråder. Følgende eksempler viser en minimalistisk server- og klientimplementering med tråder. Nettverkskoden er i hovedsak den samme som i artikkelen bortsett fra at noen utdrag ble synkronisert, flyttet til tråder og unntak håndteres.
Server.java
importer java.io. IOException; importer java.net. InetAddress; importer java.net. ServerSocket; importer java.net. SocketException; import java.net. UnknownHostException; importer java.util. ArrayList; import java.util. Collections; import java.util. List; /*** Klassen {@code Server} representerer et serverslutpunkt i et nettverk. {@code Server} en gang bundet til en bestemt IP * -adresse og port, oppretter forbindelser med klienter og kan kommunisere med dem eller koble dem fra. *
* Denne klassen er trådsikker. * * @versjon 1.0 * @see Client * @see Connection */ public class Server implementerer Runnable {private ServerSocket server; privat liste
tilkoblinger; privat tråd Tråd; private final Object connectionsLock = new Object (); /** * Konstruerer en {@code Server} som samhandler med klienter på det angitte vertsnavnet og porten med den angitte * forespurte maksimal lengden på en kø med innkommende klienter. * * @param -vert Vertsadresse som skal brukes. * @param -port Portnummer som skal brukes. * @param backlog Forespurt maksimal lengde på køen til innkommende klienter. * @throws NetworkException Hvis det oppstår feil under oppstart av 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 ("Vertsnavn kunne ikke løses:" + vert, e); } catch (IllegalArgumentException e) {throw new NetworkException ("Portnummer må være mellom 0 og 65535 (inkludert):" + port); } catch (IOException e) {throw new NetworkException ("Serveren kunne ikke startes.", e); } tilkoblinger = Collections.synchronizedList (ny ArrayList ()); tråd = ny Tråd (dette); thread.start (); } /*** Konstruerer en {@code Server} som samhandler med klienter på det angitte vertsnavnet og porten. * * @param vert Vertsadresse som skal bindes. * @param -port Portnummer som skal bindes. * @throws NetworkException Hvis det oppstår feil under oppstart av en server. */ public Server (String host, int port) kaster NetworkException {this (host, port, 50); } /*** Lytter etter, godtar og registrerer innkommende tilkoblinger fra klienter. */ @Override public void run () {while (! Server.isClosed ()) {try {connections.add (new Connection (server.accept ())); } catch (SocketException e) {if (! e.getMessage (). equals ("Socket closed")) {e.printStackTrace (); }} catch (NetworkException | IOException e) {e.printStackTrace (); }}} /*** Sender data til alle registrerte klienter. * * @paramdata Data som skal sendes. * @throws IllegalStateException Hvis du prøver å skrive data når serveren er frakoblet. * @throws IllegalArgumentException Hvis data som skal sendes er null. */ public void broadcast (Object data) {if (server.isClosed ()) {throw new IllegalStateException ("Data ikke sendt, serveren er frakoblet."); } if (data == null) {throw new IllegalArgumentException ("null data"); } synkronisert (connectionsLock) {for (Connection connection: connections) {try {connection.send (data); System.out.println ("Data sendt til klienten."); } fangst (NetworkException e) {e.printStackTrace (); }}}}} /*** Sender en frakoblingsmelding og kobler fra spesifisert klient. * * @param tilkobling Klient for å koble fra. * @throws NetworkException Hvis det oppstår feil under avslutning av tilkoblingen. */ public void disconnect (Connection connection) kaster NetworkException {if (connections.remove (tilkobling)) {connection.close (); }} /*** Sender en frakoblingsmelding til alle klienter, kobler dem fra og avslutter serveren. */ public void close () kaster NetworkException {synchronized (connectionsLock) {for (Connection connection: connections) {try {connection.close (); } fangst (NetworkException e) {e.printStackTrace (); }}} connections.clear (); prøv {server.close (); } catch (IOException e) {throw new NetworkException ("Feil ved avslutning av server."); } endelig {thread.interrupt (); }} /*** Returnerer om serveren er tilkoblet eller ikke. * * @return Sann hvis serveren er online. Falt, ellers. */ public boolean isOnline () {return! server.isClosed (); } /*** Returnerer en rekke registrerte klienter. */ public Connection getConnections () {synchronized (connectionsLock) {return connections.toArray (new Connection [connections.size ()]); }}}
Client.java
importer java.io. IOException; import java.net. Socket; import java.net. UnknownHostException; /*** Klassen {@code Client} representerer et klientslutpunkt i et nettverk. {@code Client}, når den først er koblet til en bestemt * server, kan garantert bare kommunisere med serveren. Hvorvidt andre klienter mottar data * eller ikke, avhenger av serverimplementeringen. *
* Denne klassen er trådsikker. * * @versjon 1.0 * @see Server * @see Connection */ public class Client {private Connection connection; /*** Konstruerer en {@code Client} koblet til serveren på den angitte verten og porten. * * @param vert Vertsadresse som skal bindes. * @param -port Portnummer som skal bindes. * @throws NetworkException Hvis det oppstår feil under oppstart av en server. */ public Client (String host, int port) kaster NetworkException {try {connection = new Connection (new Socket (host, port)); } catch (UnknownHostException e) {throw new NetworkException ("Vertsnavn kunne ikke løses:" + vert, e); } catch (IllegalArgumentException e) {throw new NetworkException ("Portnummer må være mellom 0 og 65535 (inkludert):" + port); } catch (IOException e) {throw new NetworkException ("Serveren kunne ikke startes.", e); }} /*** Sender data til den andre parten. * * @paramdata Data som skal sendes. * @throws NetworkException Hvis skrive til utdatastrøm mislykkes. * @throws IllegalStateException Hvis du prøver å skrive data når tilkoblingen stenges. * @throws IllegalArgumentException Hvis data som skal sendes er null. * @throws UnsupportedOperationException Hvis du prøver å sende datatype som ikke støttes. */ public void send (Object data) kaster NetworkException {connection.send (data); } /*** Sender en frakoblingsmelding til og avslutter forbindelsen til serveren. */ public void close () kaster NetworkException {connection.close (); } /*** Returnerer om klienten er koblet til serveren eller ikke. * * @return True hvis klienten er tilkoblet. Falt, ellers. */ public boolean isOnline () {returforbindelse.isConnected (); } /*** Returnerer {@link Connection} -forekomsten til klienten. */ public Connection getConnection () {returforbindelse; }}
Tilkobling. Java
importer java.io. DataInputStream; importer java.io. DataOutputStream; importer java.io. IOException; import java.net. Socket; importer java.net. SocketException; /** * Klassen {@code Connection} representerer enten en tilkobling fra server til klient eller et sluttpunkt for klienten i et nettverk * {@code Connection}, når den er tilkoblet, kan utveksle data med andre parter eller parter, avhengig av på en server * implementering. *
* Denne klassen er trådsikker. * * @versjon 1.0 * @see Server * @see Client */ public class Tilkobling implementerer Runnable {private Socket socket; private DataOutputStream ut; private DataInputStream i; privat tråd Tråd; private final Object writeLock = new Object (); private final Object readLock = new Object (); /*** Konstruerer {@code Connection} ved å bruke strømmer fra en spesifisert {@link Socket}. * * @param socket Socket for å hente bekkene fra.*/ public Connection (Socket socket) kaster NetworkException {if (socket == null) {throw new IllegalArgumentException ("null socket"); } this.socket = socket; prøv {out = new DataOutputStream (socket.getOutputStream ()); } catch (IOException e) {throw new NetworkException ("Kan ikke få tilgang til utdatastrøm.", e); } prøv {in = new DataInputStream (socket.getInputStream ()); } catch (IOException e) {throw new NetworkException ("Kunne ikke få tilgang til inndatastrøm.", e); } tråd = ny tråd (dette); thread.start (); } /*** Leser meldinger mens forbindelsen til den andre parten er i live. */ @Override public void run () {while (! Socket.isClosed ()) {try {int identifier; byte byte; synkronisert (readLock) {identifier = in.readInt (); int length = in.readInt (); hvis (lengde> 0) {byte = ny byte [lengde]; in.readFully (byte, 0, bytes.length); } annet {fortsette; }} switch (identifier) {case Identifier. INTERNAL: String command = new String (bytes); if (command.equals ("koble fra")) {if (! socket.isClosed ()) {System.out.println ("Frakoblingspakke mottatt."); prøv {close (); } catch (NetworkException e) {return; } } } gå i stykker; case Identifier. TEXT: System.out.println ("Melding mottatt:" + ny streng (byte)); gå i stykker; standard: System.out.println ("Ukjente data mottatt."); }} catch (SocketException e) {if (! e.getMessage (). equals ("Socket closed")) {e.printStackTrace (); }} catch (IOException e) {e.printStackTrace (); }}}} /*** Sender data til den andre parten. * * @paramdata Data som skal sendes. * @throws NetworkException Hvis skrive til utdatastrøm mislykkes. * @throws IllegalStateException Hvis du prøver å skrive data når tilkoblingen stenges. * @throws IllegalArgumentException Hvis data som skal sendes er null. * @throws UnsupportedOperationException Hvis du prøver å sende datatype som ikke støttes. */ public void send (Object data) kaster NetworkException {if (socket.isClosed ()) {throw new IllegalStateException ("Data ikke sendt, tilkoblingen er stengt."); } if (data == null) {throw new IllegalArgumentException ("null data"); } int -identifikator; byte byte; if (data instanceof String) {identifier = Identifier. TEXT; byte = ((String) data).getBytes (); } else {throw new UnsupportedOperationException ("Datatype som ikke støttes:" + data.getClass ()); } prøv {synchronized (writeLock) {out.writeInt (identifier); out.writeInt (bytes.length); out.write (byte); out.flush (); }} catch (IOException e) {throw new NetworkException ("Data kunne ikke sendes.", e); }} /*** Sender en frakoblingsmelding til og avslutter forbindelsen med den andre parten. */ public void close () kaster NetworkException {if (socket.isClosed ()) {throw new IllegalStateException ("Tilkoblingen er allerede stengt."); } prøv {byte melding = "koble fra".getBytes (); synkronisert (writeLock) {out.writeInt (Identifier. INTERNAL); out.writeInt (melding.lengde); out.write (melding); out.flush (); }} catch (IOException e) {System.out.println ("Meldingen om frakobling kunne ikke sendes."); } Prøv {synchronized (writeLock) {out.close (); }} catch (IOException e) {throw new NetworkException ("Feil ved avslutning av tilkobling.", e); } endelig {thread.interrupt (); }} /*** Returnerer om forbindelsen til den andre parten er i live eller ikke. * * @return Sann hvis tilkoblingen er i live. Falt, ellers. */ public boolean isConnected () {return! socket.isClosed (); }}
Identifier.java
/** * Klassen {@code Identifier} inneholder konstanter som brukes av {@link Connection} for å serialisere og deserialisere dataene * som sendes over nettverket. * * @versjon 1.0 * @see Connection * / public final class Identifier { / ** * Identifier for interne meldinger. */ public static final int INTERNAL = 1; /*** Identifikator for tekstmeldinger. */ public static final int TEKST = 2; }
NetworkException.java
/*** Klassen {@code NetworkException} indikerer en feil relatert til nettverket. * / public class NetworkException utvider unntaket { / *** Konstruerer en {@code NetworkException} med {@code null} som melding. * / public NetworkException () {} / *** Konstruerer en {@code NetworkException} med den angitte meldingen. * * @paramelding En melding for å beskrive feil. */ public NetworkException (String melding) {super (melding); } /*** Konstruerer en {@code NetworkException} med den angitte meldingen og årsaken. * * @paramelding En melding for å beskrive feil. * @param årsak En årsak til feil. */ public NetworkException (String -melding, årsak som kan kastes) {super (melding, årsak); } /*** Konstruerer en {@code NetworkException} med den angitte årsaken. * * @param årsak En årsak til feil. */ public NetworkException (årsak som kan kastes) {super (årsak); }}
UsageExample.java
/*** Klassen {@code UsageExample} viser bruken av {@link Server} og {@link Client}. Disse eksemplene bruker * {@link Thread#sleep (long)} for å sikre at hvert segment blir utført fordi hurtig start og lukking fører til at noen * segmenter ikke kjøres. * * @versjon 1.0 * @see Server * @see Client */ public class UsageExample {public static void main (String args) kaster Unntak {String host = "localhost"; int port = 10430; Server server = ny Server (vert, port); Klientklient = ny klient (vert, port); Tråd. Sover (100L); client.send ("Hei."); server.broadcast ("Hei, fyr!"); Tråd. Sover (100L); server.disconnect (server.getConnections () [0]); // eller client.close () for å koble fra server.close () på klientsiden; }}