Een netwerktoepassing maken in Java (met afbeeldingen)

Inhoudsopgave:

Een netwerktoepassing maken in Java (met afbeeldingen)
Een netwerktoepassing maken in Java (met afbeeldingen)

Video: Een netwerktoepassing maken in Java (met afbeeldingen)

Video: Een netwerktoepassing maken in Java (met afbeeldingen)
Video: How to Take Screenshot in Android 13 – Make Screenshot 2024, Mei
Anonim

Het schrijven van code die op een bepaald apparaat wordt uitgevoerd, geeft veel voldoening. Maar het schrijven van code die wordt uitgevoerd op verschillende apparaten die met elkaar communiceren, is gewoon levensbevestigend. Dit artikel leert u hoe u verbinding kunt maken en berichten kunt uitwisselen via een netwerk met behulp van het Transmission Control Protocol (TCP).

In dit artikel ga je een applicatie opzetten die je computer met zichzelf verbindt en, in wezen, het gek maakt - tegen zichzelf praat. Je leert ook het verschil tussen de twee meest gebruikte streams voor netwerken in Java en hoe ze werken.

Gegevens- en objectstromen

Voordat we in de code duiken, moet het verschil tussen de twee stromen die in het artikel worden gebruikt, worden onderscheiden.

Gegevensstromen

Datastromen verwerken primitieve datatypes en strings. Gegevens die via gegevensstromen worden verzonden, moeten handmatig worden geserialiseerd en gedeserialiseerd, wat het moeilijker maakt om complexe gegevens over te dragen. Maar datastromen kunnen communiceren met servers en clients die in andere talen dan Java zijn geschreven. Ruwe stromen zijn in dat opzicht vergelijkbaar met gegevensstromen, maar gegevensstromen zorgen ervoor dat de gegevens op een platformonafhankelijke manier worden geformatteerd, wat gunstig is omdat beide partijen verzonden gegevens kunnen lezen.

Objectstromen

Objectstromen verwerken primitieve gegevenstypen en objecten die worden geïmplementeerd

serialiseerbaar

koppel. Gegevens die via objectstromen worden verzonden, worden automatisch geserialiseerd en gedeserialiseerd, wat het gemakkelijker maakt om complexe gegevens over te dragen. Objectstromen kunnen echter alleen communiceren met servers en clients die in Java zijn geschreven. Ook,

ObjectUitvoerStream

bij initialisatie, stuurt een header naar de

InvoerStream

van de andere partij die, bij initialisatie, de uitvoering blokkeert totdat de header is ontvangen.

Stappen

Een netwerktoepassing maken in Java Step1
Een netwerktoepassing maken in Java Step1

Stap 1. Maak een klas aan

Maak een klas aan en noem deze zoals je wilt. In dit artikel wordt het genoemd

NetwerkAppVoorbeeld

openbare klasse NetworkAppExample { }

Een netwerktoepassing maken in Java Step2
Een netwerktoepassing maken in Java Step2

Stap 2. Maak een hoofdmethode aan

Maak een hoofdmethode en declareer dat deze uitzonderingen van kan veroorzaken

Uitzondering

type en elke subklasse ervan - alle uitzonderingen. Dit wordt als een slechte gewoonte beschouwd, maar is acceptabel voor barebone-voorbeelden.

openbare klasse NetworkAppExample { public static void main (String args) gooit Exception {} }

Een netwerktoepassing maken in Java Step3
Een netwerktoepassing maken in Java Step3

Stap 3. Declareer het serveradres

In dit voorbeeld wordt een lokaal hostadres en een willekeurig poortnummer gebruikt. Het poortnummer moet tussen 0 en 65535 (inclusief) liggen. De te vermijden poortnummers variëren echter van 0 tot 1023 (inclusief) omdat het gereserveerde systeempoorten zijn.

public class NetworkAppExample { public static void main (String args) gooit Exception { String host = "localhost"; int-poort = 10430; } }

Een netwerktoepassing maken in Java Step4
Een netwerktoepassing maken in Java Step4

Stap 4. Maak een server aan

Server is gebonden aan het adres en de poort en luistert naar inkomende verbindingen. op Java,

ServerSocket

staat voor het eindpunt aan de serverzijde en de functie ervan is het accepteren van nieuwe verbindingen.

ServerSocket

heeft geen streams voor het lezen en verzenden van gegevens omdat het geen verbinding tussen een server en een client vertegenwoordigt.

import java.net. InetAddress; java.net. ServerSocket importeren; public class NetworkAppExample { public static void main (String args) gooit Exception { String host = "localhost"; int-poort = 10430; ServerSocket-server = nieuwe ServerSocket(poort, 50, InetAddress.getByName(host)); } }

Een netwerktoepassing maken in Java Step5
Een netwerktoepassing maken in Java Step5

Stap 5. Start van de logserver

Druk voor logboekdoeleinden af naar de console die server is gestart.

import java.net. InetAddress; java.net. ServerSocket importeren; public class NetworkAppExample { public static void main (String args) gooit Exception { String host = "localhost"; int-poort = 10430; ServerSocket-server = nieuwe ServerSocket(poort, 50, InetAddress.getByName(host)); System.out.println("Server gestart."); } }

Een netwerktoepassing maken in Java Step6
Een netwerktoepassing maken in Java Step6

Stap 6. Maak een klant aan

Client is gebonden aan het adres en de poort van een server en luistert naar pakketten (berichten) nadat de verbinding tot stand is gebracht. op Java,

Stopcontact

vertegenwoordigt ofwel een eindpunt aan de clientzijde dat is verbonden met de server of een verbinding (van de server) naar de client en wordt gebruikt om te communiceren met de partij aan de andere kant.

import java.net. InetAddress; java.net. ServerSocket importeren; import java.net. Socket; public class NetworkAppExample { public static void main (String args) gooit Exception { String host = "localhost"; int-poort = 10430; ServerSocket-server = nieuwe ServerSocket(poort, 50, InetAddress.getByName(host)); System.out.println("Server gestart."); Socket-client = nieuwe Socket (host, poort); } }

Een netwerktoepassing maken in Java Step7
Een netwerktoepassing maken in Java Step7

Stap 7. Log verbindingspoging

Druk voor logboekdoeleinden af naar de console die verbinding is geprobeerd.

import java.net. InetAddress; java.net. ServerSocket importeren; import java.net. Socket; public class NetworkAppExample { public static void main (String args) gooit Exception { String host = "localhost"; int-poort = 10430; ServerSocket-server = nieuwe ServerSocket(poort, 50, InetAddress.getByName(host)); System.out.println("Server gestart."); Socket-client = nieuwe Socket (host, poort); System.out.println("Verbinding maken met server…"); } }

Een netwerktoepassing maken in Java Step8
Een netwerktoepassing maken in Java Step8

Stap 8. Maak verbinding

Clients zullen nooit verbinding maken tenzij de server luistert naar en accepteert, met andere woorden, verbindingen tot stand brengt. In Java worden verbindingen tot stand gebracht met

aanvaarden()

methode van

ServerSocket

klas. De methode blokkeert de uitvoering totdat een client verbinding maakt.

import java.net. InetAddress; java.net. ServerSocket importeren; import java.net. Socket; public class NetworkAppExample { public static void main (String args) gooit Exception { String host = "localhost"; int-poort = 10430; ServerSocket-server = nieuwe ServerSocket(poort, 50, InetAddress.getByName(host)); System.out.println("Server gestart."); Socket-client = nieuwe Socket (host, poort); System.out.println("Verbinding maken met server…"); Socketverbinding = server.accept(); } }

Een netwerktoepassing maken in Java Step9
Een netwerktoepassing maken in Java Step9

Stap 9. Log de tot stand gebrachte verbinding in

Voor logboekdoeleinden drukt u naar de console af dat de verbinding tussen server en client tot stand is gebracht.

import java.net. InetAddress; java.net. ServerSocket importeren; import java.net. Socket; public class NetworkAppExample { public static void main (String args) gooit Exception { String host = "localhost"; int-poort = 10430; ServerSocket-server = nieuwe ServerSocket(poort, 50, InetAddress.getByName(host)); System.out.println("Server gestart."); Socket-client = nieuwe Socket (host, poort); System.out.println("Verbinding maken met server…"); Socketverbinding = server.accept(); System.out.println("Verbinding tot stand gebracht."); } }

Een netwerktoepassing maken in Java Step10
Een netwerktoepassing maken in Java Step10

Stap 10. Bereid communicatiestromen voor

Communicatie vindt plaats via streams en in deze toepassing moeten onbewerkte streams van (verbinding van) server (naar client) en client worden geketend aan data- of objectstreams. Onthoud dat beide partijen hetzelfde streamtype moeten gebruiken.

  • Gegevensstromen

    import java.io. DataInputStream; import java.io. DataOutputStream; import java.net. InetAddress; java.net. ServerSocket importeren; import java.net. Socket; public class NetworkAppExample { public static void main (String args) gooit Exception { String host = "localhost"; int-poort = 10430; ServerSocket-server = nieuwe ServerSocket(poort, 50, InetAddress.getByName(host)); System.out.println("Server gestart."); Socket-client = nieuwe Socket (host, poort); System.out.println("Verbinding maken met server…"); Socketverbinding = server.accept(); System.out.println("Verbinding tot stand gebracht."); DataOutputStream clientOut = nieuwe DataOutputStream(client.getOutputStream()); DataInputStream clientIn = nieuwe DataInputStream(client.getInputStream()); DataOutputStream serverOut = nieuwe DataOutputStream(connection.getOutputStream()); DataInputStream serverIn = nieuwe DataInputStream(verbinding.getInputStream()); } }

  • Objectstromen

    Wanneer meerdere objectstromen worden gebruikt, moeten invoerstromen in dezelfde volgorde worden geïnitialiseerd als uitvoerstromen omdat:

    ObjectOutputStream

    stuurt een header naar de andere partij en

    ObjectInputStream

    blokkeert de uitvoering totdat de header wordt gelezen.

    import java.io. ObjectInputStream; java.io. ObjectOutputStream importeren; import java.net. InetAddress; java.net. ServerSocket importeren; import java.net. Socket; public class NetworkAppExample { public static void main (String args) gooit Exception { String host = "localhost"; int-poort = 10430; ServerSocket-server = nieuwe ServerSocket(poort, 50, InetAddress.getByName(host)); System.out.println("Server gestart."); Socket-client = nieuwe Socket (host, poort); System.out.println("Verbinding maken met server…"); Socketverbinding = server.accept(); System.out.println("Verbinding tot stand gebracht."); ObjectOutputStream clientOut = nieuwe ObjectOutputStream(client.getOutputStream()); ObjectOutputStream serverOut = nieuwe ObjectOutputStream(connection.getOutputStream()); ObjectInputStream clientIn = nieuwe ObjectInputStream(client.getInputStream()); ObjectInputStream serverIn = nieuwe ObjectInputStream(verbinding.getInputStream()); } }

    Volgorde zoals gespecificeerd in de bovenstaande code is misschien gemakkelijker te onthouden - initialiseer eerst de uitvoerstromen en vervolgens de invoerstromen in dezelfde volgorde. Een andere volgorde voor het initialiseren van objectstromen is echter de volgende:

    ObjectOutputStream clientOut = nieuwe ObjectOutputStream(client.getOutputStream()); ObjectInputStream serverIn = nieuwe ObjectInputStream(verbinding.getInputStream()); ObjectOutputStream serverOut = nieuwe ObjectOutputStream(connection.getOutputStream()); ObjectInputStream clientIn = nieuwe ObjectInputStream(client.getInputStream());

Een netwerktoepassing maken in Java Step11
Een netwerktoepassing maken in Java Step11

Stap 11. Log in dat de communicatie gereed is

Druk voor logboekdoeleinden af naar de console dat de communicatie gereed is.

// code weggelaten import java.net. InetAddress; java.net. ServerSocket importeren; import java.net. Socket; public class NetworkAppExample { public static void main (String args) gooit Exception { String host = "localhost"; int-poort = 10430; ServerSocket-server = nieuwe ServerSocket(poort, 50, InetAddress.getByName(host)); System.out.println("Server gestart."); Socket-client = nieuwe Socket (host, poort); System.out.println("Verbinding maken met server…"); Socketverbinding = server.accept(); System.out.println("Verbinding tot stand gebracht."); // code weggelaten System.out.println ("Communicatie is gereed."); } }

Een netwerktoepassing maken in Java Step12
Een netwerktoepassing maken in Java Step12

Stap 12. Maak een bericht aan

In deze toepassing,

Hallo Wereld

tekst wordt naar de server verzonden als

byte

of

Snaar

. Declareer een variabele van het type dat afhangt van de gebruikte stream. Gebruik maken van

byte

voor datastromen en

Snaar

voor objectstromen.

  • Gegevensstromen

    Met behulp van datastromen wordt serialisatie gedaan door objecten om te zetten in primitieve datatypes of a

    Snaar

    . In dit geval,

    Snaar

    wordt geconverteerd naar

    byte

    in plaats van geschreven met behulp van

    schrijfBytes()

    methode om te laten zien hoe het zou zijn met andere objecten, zoals afbeeldingen of andere bestanden.

    import java.io. DataInputStream; import java.io. DataOutputStream; import java.net. InetAddress; java.net. ServerSocket importeren; import java.net. Socket; public class NetworkAppExample { public static void main (String args) gooit Exception { String host = "localhost"; int-poort = 10430; ServerSocket-server = nieuwe ServerSocket(poort, 50, InetAddress.getByName(host)); System.out.println("Server gestart."); Socket-client = nieuwe Socket (host, poort); System.out.println("Verbinding maken met server…"); Socketverbinding = server.accept(); System.out.println("Verbinding tot stand gebracht."); DataOutputStream clientOut = nieuwe DataOutputStream(client.getOutputStream()); DataInputStream clientIn = nieuwe DataInputStream(client.getInputStream()); DataOutputStream serverOut = nieuwe DataOutputStream(connection.getOutputStream()); DataInputStream serverIn = nieuwe DataInputStream(verbinding.getInputStream()); System.out.println("Communicatie is gereed."); byte messageOut = "Hallo wereld".getBytes(); } }

  • Objectstromen

    import java.io. ObjectInputStream; java.io. ObjectOutputStream importeren; import java.net. InetAddress; java.net. ServerSocket importeren; import java.net. Socket; public class NetworkAppExample { public static void main (String args) gooit Exception { String host = "localhost"; int-poort = 10430; ServerSocket-server = nieuwe ServerSocket(poort, 50, InetAddress.getByName(host)); System.out.println("Server gestart."); Socket-client = nieuwe Socket (host, poort); System.out.println("Verbinding maken met server…"); Socketverbinding = server.accept(); System.out.println("Verbinding tot stand gebracht."); ObjectOutputStream clientOut = nieuwe ObjectOutputStream(client.getOutputStream()); ObjectOutputStream serverOut = nieuwe ObjectOutputStream(connection.getOutputStream()); ObjectInputStream clientIn = nieuwe ObjectInputStream(client.getInputStream()); ObjectInputStream serverIn = nieuwe ObjectInputStream(verbinding.getInputStream()); System.out.println("Communicatie is gereed."); String messageOut = "Hallo wereld"; } }

Een netwerktoepassing maken in Java Step13
Een netwerktoepassing maken in Java Step13

Stap 13. Verstuur het bericht

Schrijf gegevens naar de uitvoerstroom en spoel de stroom om ervoor te zorgen dat de gegevens volledig zijn geschreven.

  • Gegevensstromen

    De lengte van een bericht moet eerst worden verzonden, zodat de andere partij weet hoeveel bytes het moet lezen. Nadat de lengte is verzonden als een primitief geheel getal, kunnen bytes worden verzonden.

    import java.io. DataInputStream; import java.io. DataOutputStream; import java.net. InetAddress; java.net. ServerSocket importeren; import java.net. Socket; public class NetworkAppExample { public static void main (String args) gooit Exception { String host = "localhost"; int-poort = 10430; ServerSocket-server = nieuwe ServerSocket(poort, 50, InetAddress.getByName(host)); System.out.println("Server gestart."); Socket-client = nieuwe Socket (host, poort); System.out.println("Verbinding maken met server…"); Socketverbinding = server.accept(); System.out.println("Verbinding tot stand gebracht."); DataOutputStream clientOut = nieuwe DataOutputStream(client.getOutputStream()); DataInputStream clientIn = nieuwe DataInputStream(client.getInputStream()); DataOutputStream serverOut = nieuwe DataOutputStream(connection.getOutputStream()); DataInputStream serverIn = nieuwe DataInputStream(verbinding.getInputStream()); System.out.println("Communicatie is gereed."); byte messageOut = "Hallo wereld".getBytes(); clientOut.writeInt(messageOut.length); clientOut.write (berichtUit); clientOut.flush(); } }

  • Objectstromen

    import java.io. ObjectInputStream; import java.io. ObjectOutputStream; import java.net. InetAddress; java.net. ServerSocket importeren; import java.net. Socket; public class NetworkAppExample { public static void main (String args) gooit Exception { String host = "localhost"; int-poort = 10430; ServerSocket-server = nieuwe ServerSocket(poort, 50, InetAddress.getByName(host)); System.out.println("Server gestart."); Socket-client = nieuwe Socket (host, poort); System.out.println("Verbinding maken met server…"); Socketverbinding = server.accept(); System.out.println("Verbinding tot stand gebracht."); ObjectOutputStream clientOut = nieuwe ObjectOutputStream(client.getOutputStream()); ObjectOutputStream serverOut = nieuwe ObjectOutputStream(connection.getOutputStream()); ObjectInputStream clientIn = nieuwe ObjectInputStream(client.getInputStream()); ObjectInputStream serverIn = nieuwe ObjectInputStream(verbinding.getInputStream()); System.out.println("Communicatie is gereed."); String messageOut = "Hallo wereld"; clientOut.writeObject(berichtUit); clientOut.flush(); } }

Een netwerktoepassing maken in Java Step14
Een netwerktoepassing maken in Java Step14

Stap 14. Log verzonden bericht

Druk voor logboekdoeleinden af naar de console dat het bericht is verzonden.

  • Gegevensstromen

    import java.io. DataInputStream; import java.io. DataOutputStream; import java.net. InetAddress; java.net. ServerSocket importeren; import java.net. Socket; public class NetworkAppExample { public static void main (String args) gooit Exception { String host = "localhost"; int-poort = 10430; ServerSocket-server = nieuwe ServerSocket(poort, 50, InetAddress.getByName(host)); System.out.println("Server gestart."); Socket-client = nieuwe Socket (host, poort); System.out.println("Verbinding maken met server…"); Socketverbinding = server.accept(); System.out.println("Verbinding tot stand gebracht."); DataOutputStream clientOut = nieuwe DataOutputStream(client.getOutputStream()); DataInputStream clientIn = nieuwe DataInputStream(client.getInputStream()); DataOutputStream serverOut = nieuwe DataOutputStream(connection.getOutputStream()); DataInputStream serverIn = nieuwe DataInputStream(verbinding.getInputStream()); System.out.println("Communicatie is gereed."); byte messageOut = "Hallo wereld".getBytes(); clientOut.writeInt(messageOut.length); clientOut.write (berichtUit); clientOut.flush(); System.out.println("Bericht verzonden naar server: " + new String(messageOut)); } }

  • Objectstromen

    import java.io. ObjectInputStream; import java.io. ObjectOutputStream; import java.net. InetAddress; java.net. ServerSocket importeren; import java.net. Socket; public class NetworkAppExample { public static void main (String args) gooit Exception { String host = "localhost"; int-poort = 10430; ServerSocket-server = nieuwe ServerSocket(poort, 50, InetAddress.getByName(host)); System.out.println("Server gestart."); Socket-client = nieuwe Socket (host, poort); System.out.println("Verbinding maken met server…"); Socketverbinding = server.accept(); System.out.println("Verbinding tot stand gebracht."); ObjectOutputStream clientOut = nieuwe ObjectOutputStream(client.getOutputStream()); ObjectOutputStream serverOut = nieuwe ObjectOutputStream(connection.getOutputStream()); ObjectInputStream clientIn = nieuwe ObjectInputStream(client.getInputStream()); ObjectInputStream serverIn = nieuwe ObjectInputStream(verbinding.getInputStream()); System.out.println("Communicatie is gereed."); String messageOut = "Hallo wereld"; clientOut.writeObject(berichtUit); clientOut.flush(); System.out.println("Bericht verzonden naar server: " + messageOut); } }

Een netwerktoepassing maken in Java Step15
Een netwerktoepassing maken in Java Step15

Stap 15. Lees het bericht

Gegevens uit de invoerstroom lezen en converteren. Aangezien we precies het type verzonden gegevens weten, zullen we ofwel een

Snaar

van

byte

of cast

Object

tot

Snaar

zonder te controleren, afhankelijk van de gebruikte stream.

  • Gegevensstromen

    Omdat de lengte eerst werd verzonden en daarna de bytes, moet het lezen in dezelfde volgorde worden gedaan. Als de lengte nul is, is er niets te lezen. Object wordt gedeserialiseerd wanneer bytes weer worden geconverteerd naar een instantie, in dit geval van

    Snaar

    import java.io. DataInputStream; import java.io. DataOutputStream; import java.net. InetAddress; java.net. ServerSocket importeren; import java.net. Socket; public class NetworkAppExample { public static void main (String args) gooit Exception { String host = "localhost"; int-poort = 10430; ServerSocket-server = nieuwe ServerSocket(poort, 50, InetAddress.getByName(host)); System.out.println("Server gestart."); Socket-client = nieuwe Socket (host, poort); System.out.println("Verbinding maken met server…"); Socketverbinding = server.accept(); System.out.println("Verbinding tot stand gebracht."); DataOutputStream clientOut = nieuwe DataOutputStream(client.getOutputStream()); DataInputStream clientIn = nieuwe DataInputStream(client.getInputStream()); DataOutputStream serverOut = nieuwe DataOutputStream(connection.getOutputStream()); DataInputStream serverIn = nieuwe DataInputStream(verbinding.getInputStream()); System.out.println("Communicatie is gereed."); byte messageOut = "Hallo wereld".getBytes(); clientOut.writeInt(messageOut.length); clientOut.write (berichtUit); clientOut.flush(); System.out.println("Bericht verzonden naar server: " + new String(messageOut)); int lengte = serverIn.readInt(); if (lengte > 0) { byte messageIn = nieuwe byte[lengte]; serverIn.readFully(messageIn, 0, messageIn.length); } } }

  • Objectstromen

    import java.io. ObjectInputStream; import java.io. ObjectOutputStream; import java.net. InetAddress; java.net. ServerSocket importeren; import java.net. Socket; public class NetworkAppExample { public static void main (String args) gooit Exception { String host = "localhost"; int-poort = 10430; ServerSocket-server = nieuwe ServerSocket(poort, 50, InetAddress.getByName(host)); System.out.println("Server gestart."); Socket-client = nieuwe Socket (host, poort); System.out.println("Verbinding maken met server…"); Socketverbinding = server.accept(); System.out.println("Verbinding tot stand gebracht."); ObjectOutputStream clientOut = nieuwe ObjectOutputStream(client.getOutputStream()); ObjectOutputStream serverOut = nieuwe ObjectOutputStream(connection.getOutputStream()); ObjectInputStream clientIn = nieuwe ObjectInputStream(client.getInputStream()); ObjectInputStream serverIn = nieuwe ObjectInputStream(verbinding.getInputStream()); System.out.println("Communicatie is gereed."); String messageOut = "Hallo wereld"; clientOut.writeObject(berichtUit); clientOut.flush(); System.out.println("Bericht verzonden naar server: " + messageOut); String messageIn = (String) serverIn.readObject(); } }

Een netwerktoepassing maken in Java Step16
Een netwerktoepassing maken in Java Step16

Stap 16. Log gelezen bericht

Druk voor logboekdoeleinden af naar de console dat het bericht is ontvangen en druk de inhoud ervan af.

  • Gegevensstromen

    import java.io. DataInputStream; import java.io. DataOutputStream; import java.net. InetAddress; java.net. ServerSocket importeren; import java.net. Socket; public class NetworkAppExample { public static void main (String args) gooit Exception { String host = "localhost"; int-poort = 10430; ServerSocket-server = nieuwe ServerSocket(poort, 50, InetAddress.getByName(host)); System.out.println("Server gestart."); Socket-client = nieuwe Socket (host, poort); System.out.println("Verbinding maken met server…"); Socketverbinding = server.accept(); System.out.println("Verbinding tot stand gebracht."); DataOutputStream clientOut = nieuwe DataOutputStream(client.getOutputStream()); DataInputStream clientIn = nieuwe DataInputStream(client.getInputStream()); DataOutputStream serverOut = nieuwe DataOutputStream(connection.getOutputStream()); DataInputStream serverIn = nieuwe DataInputStream(verbinding.getInputStream()); System.out.println("Communicatie is gereed."); byte messageOut = "Hallo wereld".getBytes(); clientOut.writeInt(messageOut.length); clientOut.write (berichtUit); clientOut.flush(); System.out.println("Bericht verzonden naar server: " + new String(messageOut)); int lengte = serverIn.readInt(); if (lengte > 0) { byte messageIn = nieuwe byte[lengte]; serverIn.readFully(messageIn, 0, messageIn.length); System.out.println("Bericht ontvangen van klant: " + new String(messageIn)); } } }

  • Objectstromen

    import java.io. ObjectInputStream; import java.io. ObjectOutputStream; import java.net. InetAddress; java.net. ServerSocket importeren; import java.net. Socket; public class NetworkAppExample { public static void main (String args) gooit Exception { String host = "localhost"; int-poort = 10430; ServerSocket-server = nieuwe ServerSocket(poort, 50, InetAddress.getByName(host)); System.out.println("Server gestart."); Socket-client = nieuwe Socket (host, poort); System.out.println("Verbinding maken met server…"); Socketverbinding = server.accept(); System.out.println("Verbinding tot stand gebracht."); ObjectOutputStream clientOut = nieuwe ObjectOutputStream(client.getOutputStream()); ObjectOutputStream serverOut = nieuwe ObjectOutputStream(connection.getOutputStream()); ObjectInputStream clientIn = nieuwe ObjectInputStream(client.getInputStream()); ObjectInputStream serverIn = nieuwe ObjectInputStream(verbinding.getInputStream()); System.out.println("Communicatie is gereed."); String messageOut = "Hallo wereld"; clientOut.writeObject(berichtUit); clientOut.flush(); System.out.println("Bericht verzonden naar server: " + messageOut); String messageIn = (String) serverIn.readObject(); System.out.println("Bericht ontvangen van cliënt: " + messageIn); } }

Een netwerktoepassing maken in Java Step17
Een netwerktoepassing maken in Java Step17

Stap 17. Koppel verbindingen los

De verbinding wordt verbroken wanneer een partij zijn streams afsluit. In Java worden door de uitvoerstroom te sluiten, ook de bijbehorende socket en invoerstroom gesloten. Zodra een partij aan de andere kant ontdekt dat de verbinding is verbroken, moet deze ook de uitvoerstroom sluiten om geheugenlekken te voorkomen.

// code weggelaten import java.net. InetAddress; java.net. ServerSocket importeren; import java.net. Socket; public class NetworkAppExample { public static void main (String args) gooit Exception { String host = "localhost"; int-poort = 10430; ServerSocket-server = nieuwe ServerSocket(poort, 50, InetAddress.getByName(host)); System.out.println("Server gestart."); Socket-client = nieuwe Socket (host, poort); System.out.println("Verbinding maken met server…"); Socketverbinding = server.accept(); System.out.println("Verbinding tot stand gebracht."); // code weggelaten System.out.println ("Communicatie is gereed."); // code weggelaten clientOut.close(); serverOut.close(); } }

Een netwerktoepassing maken in Java Step18 V2
Een netwerktoepassing maken in Java Step18 V2

Stap 18. Log loskoppeling

Voor logboekdoeleinden zijn de verbindingen naar de console verbroken.

// code weggelaten import java.net. InetAddress; java.net. ServerSocket importeren; import java.net. Socket; public class NetworkAppExample { public static void main (String args) gooit Exception { String host = "localhost"; int-poort = 10430; ServerSocket-server = nieuwe ServerSocket(poort, 50, InetAddress.getByName(host)); System.out.println("Server gestart."); Socket-client = nieuwe Socket (host, poort); System.out.println("Verbinding maken met server…"); Socketverbinding = server.accept(); System.out.println("Verbinding tot stand gebracht."); // code weggelaten System.out.println ("Communicatie is gereed."); // code weggelaten clientOut.close(); serverOut.close(); System.out.println("Verbindingen gesloten."); } }

Een netwerktoepassing maken in Java Step19
Een netwerktoepassing maken in Java Step19

Stap 19. Beëindig de server

Verbindingen zijn verbroken, maar de server is nog steeds actief. Als

ServerSocket

is niet gekoppeld aan een stream, het moet expliciet worden gesloten door te bellen

dichtbij()

methode.

// code weggelaten import java.net. InetAddress; java.net. ServerSocket importeren; import java.net. Socket; public class NetworkAppExample { public static void main (String args) gooit Exception { String host = "localhost"; int-poort = 10430; ServerSocket-server = nieuwe ServerSocket(poort, 50, InetAddress.getByName(host)); System.out.println("Server gestart."); Socket-client = nieuwe Socket (host, poort); System.out.println("Verbinding maken met server…"); Socketverbinding = server.accept(); System.out.println("Verbinding tot stand gebracht."); // code weggelaten System.out.println ("Communicatie is gereed."); // code weggelaten clientOut.close(); serverOut.close(); System.out.println("Verbindingen gesloten."); server.sluiten(); } }

Een netwerktoepassing maken in Java Step20
Een netwerktoepassing maken in Java Step20

Stap 20. Beëindiging van de logserver

Voor logboekdoeleinden is het afdrukken naar de consoleserver beëindigd.

// code weggelaten import java.net. InetAddress; java.net. ServerSocket importeren; import java.net. Socket; public class NetworkAppExample { public static void main (String args) gooit Exception { String host = "localhost"; int-poort = 10430; ServerSocket-server = nieuwe ServerSocket(poort, 50, InetAddress.getByName(host)); System.out.println("Server gestart."); Socket-client = nieuwe Socket (host, poort); System.out.println("Verbinding maken met server…"); Socketverbinding = server.accept(); System.out.println("Verbinding tot stand gebracht."); // code weggelaten System.out.println ("Communicatie is gereed."); // code weggelaten clientOut.close(); serverOut.close(); System.out.println("Verbindingen gesloten."); server.sluiten(); System.out.println("Server beëindigd."); } }

Een netwerktoepassing maken in Java Step21
Een netwerktoepassing maken in Java Step21

Stap 21. Compileren en uitvoeren

Door te loggen konden we weten of de aanvraag succesvol was of niet. Verwachte resultaten:

Server gestart. Verbinding maken met server… Verbinding tot stand gebracht. Communicatie is klaar. Bericht verzonden naar server: Hello World Bericht ontvangen van client: Hello World Connections gesloten. Server beëindigd.

Als uw uitvoer niet is zoals hierboven, wat waarschijnlijk niet zal gebeuren, zijn er een paar oplossingen:

  • Als de uitvoer stopt bij de lijn

    Verbinding gemaakt.

    en objectstromen worden gebruikt, spoel ze elk door

    ObjectOutputStream

  • onmiddellijk na initialisatie omdat headers om de een of andere reden niet werden verzonden.
  • Als de uitvoer wordt afgedrukt

    java.net. BindException: Adres al in gebruik

  • kies een ander poortnummer omdat het opgegeven poortnummer al in gebruik is.

Tips

  • Verbinding maken met een server op een ander netwerk wordt gedaan door verbinding te maken met het externe IP-adres van een apparaat waarop de server wordt uitgevoerd met een doorgestuurde poort.
  • Verbinding maken met een server op hetzelfde netwerk wordt gedaan door ofwel verbinding te maken met het privé IP-adres van een apparaat waarop de server draait, of door een poort door te sturen en verbinding te maken met het externe IP-adres van het apparaat.
  • Er is software, zoals Hamachi, waarmee verbinding kan worden gemaakt met de server op een ander netwerk zonder een poort door te sturen, maar hiervoor moet de software op beide apparaten worden geïnstalleerd.

Voorbeelden

Netwerktoepassingen die invoer/uitvoer blokkeren, moeten threads gebruiken. De volgende voorbeelden tonen een minimalistische server- en clientimplementatie met threads. De netwerkcode is in wezen hetzelfde als in het artikel, behalve dat sommige fragmenten zijn gesynchroniseerd, naar threads zijn verplaatst en uitzonderingen worden afgehandeld.

Server.java

import java.io. IOException; import java.net. InetAddress; java.net. ServerSocket importeren; import java.net. SocketException; import java.net. UnknownHostException; java.util. ArrayList importeren; java.util. Collecties importeren; import java.util. Lijst; /** * De klasse {@code Server} vertegenwoordigt een servereindpunt in een netwerk. {@code Server} eenmaal gebonden aan een bepaald IP*-adres en poort, maakt verbindingen met clients en kan met hen communiceren of de verbinding verbreken. *

* Deze klasse is threadsafe. * * @versie 1.0 * @see Client * @see Connection */ public class Server implementeert Runnable { private ServerSocket-server; privé lijst verbindingen; privé Thread-thread; privé definitief Object verbindingenLock = new Object(); /** * Creëert een {@code Server} die communiceert met clients op de opgegeven hostnaam en poort met de opgegeven * gevraagde maximale lengte van een wachtrij van inkomende clients. * * @param host Hostadres dat moet worden gebruikt. * @param port Poortnummer dat moet worden gebruikt. * @param backlog Gevraagde maximale lengte van de wachtrij van inkomende clients. * @throws NetworkException Als er een fout optreedt tijdens het starten van een server. */ public Server (String host, int port, int backlog) gooit NetworkException {try {server = new ServerSocket(port, backlog, InetAddress.getByName(host)); } catch (UnknownHostException e) { throw new NetworkException("Hostnaam kon niet worden opgelost: " + host, e); } catch (IllegalArgumentException e) { throw new NetworkException("Poortnummer moet tussen 0 en 65535 liggen (inclusief): " + poort); } catch (IOException e) { throw new NetworkException ("Server kan niet worden gestart.", e); } verbindingen = Collections.synchronizedList(nieuwe ArrayList()); thread = nieuwe thread (dit); draad.start(); } /** * Creëert een {@code Server} die communiceert met clients op de opgegeven hostnaam en poort. * * @param host Hostadres om te binden. * @param port Poortnummer om te binden. * @throws NetworkException Als er fouten optreden bij het starten van een server. */ public Server (String host, int port) gooit NetworkException { this(host, port, 50); } /** * Luistert naar, accepteert en registreert inkomende verbindingen van clients. */ @Override public void run() { while (!server.isClosed()) { probeer {connections.add(new Connection(server.accept())); } catch (SocketException e) { if (!e.getMessage().equals("Socket gesloten")) { e.printStackTrace(); } } catch (NetworkException | IOException e) { e.printStackTrace(); } } } /** * Verzendt gegevens naar alle geregistreerde klanten. * * @param data Gegevens om te verzenden. * @throws IllegalStateException Als er wordt geprobeerd gegevens te schrijven terwijl de server offline is. * @throws IllegalArgumentException Als de te verzenden gegevens null zijn. */ public void broadcast (Object data) { if (server.isClosed()) { throw new IllegalStateException ("Gegevens niet verzonden, server is offline."); } if (data == null) { gooi nieuwe IllegalArgumentException ("null data"); } gesynchroniseerd (connectionsLock) { for (Verbindingsverbinding: verbindingen) { probeer {connection.send(data); System.out.println("Gegevens zijn succesvol naar de klant verzonden."); } catch (NetworkException e) { e.printStackTrace(); } } } } /** * Verzendt een bericht voor het verbreken van de verbinding en verbreekt de verbinding met de opgegeven client. * * @param verbinding Client om te verbreken. * @throws NetworkException Als er een fout optreedt bij het sluiten van de verbinding. */ public void disconnect (verbindingsverbinding) genereert NetworkException { if (connections.remove(connection)) { connection.close(); } } /** * Verzendt een bericht voor het verbreken van de verbinding naar alle clients, verbreekt de verbinding en beëindigt de server. */ public void close() gooit NetworkException {gesynchroniseerd (connectionsLock) { for (Verbindingsverbinding: verbindingen) {probeer {connection.close(); } catch (NetworkException e) { e.printStackTrace(); } } } verbindingen.clear(); probeer {server.close(); } catch (IOException e) { throw new NetworkException ("Fout bij het sluiten van de server."); } eindelijk { thread.interrupt(); } } /** * Geeft als resultaat of de server al dan niet online is. * * @return Waar als de server online is. Vals, anders. */ public boolean isOnline() { return !server.isClosed(); } /** * Retourneert een array van geregistreerde clients. */ public Connection getConnections() {synchronized (connectionsLock) {return verbindingen.toArray(nieuwe verbinding[connections.size()]); } } }

Client.java

import java.io. IOException; import java.net. Socket; import java.net. UnknownHostException; /** * De klasse {@code Client} vertegenwoordigt een client-eindpunt in een netwerk. {@code Client}, eenmaal verbonden met een bepaalde * server, kan gegarandeerd alleen communiceren met de server. Of andere clients de gegevens * ontvangen, hangt af van de serverimplementatie. *

* Deze klasse is threadsafe. * * @versie 1.0 * @see Server * @see Connection */ public class Client { private Connection connection; /** * Creëert een {@code Client} die is verbonden met de server op de opgegeven host en poort. * * @param host Hostadres om te binden. * @param port Poortnummer om te binden. * @throws NetworkException Als er een fout optreedt tijdens het starten van een server. */ public Client (String host, int port) gooit NetworkException {try { connection = new Connection (new Socket(host, port)); } catch (UnknownHostException e) { throw new NetworkException("Hostnaam kon niet worden opgelost: " + host, e); } catch (IllegalArgumentException e) { throw new NetworkException("Poortnummer moet tussen 0 en 65535 (inclusief): " + poort); } catch (IOException e) { throw new NetworkException ("Server kan niet worden gestart.", e); } } /** * Verzendt gegevens naar de andere partij. * * @param data Gegevens om te verzenden. * @throws NetworkException Als het schrijven naar de uitvoerstroom mislukt. * @throws IllegalStateException Als er wordt geprobeerd gegevens te schrijven terwijl de verbinding is verbroken. * @throws IllegalArgumentException Als de te verzenden gegevens null zijn. * @throws UnsupportedOperationException Als wordt geprobeerd een niet-ondersteund gegevenstype te verzenden. */ public void send (Object data) genereert NetworkException { connection.send(data); } /** * Verzendt een verbreekbericht naar en verbreekt de verbinding met de server. */ public void close() gooit NetworkException { connection.close(); } /** * Geeft terug of de client al dan niet is verbonden met de server. * * @return Waar als de client is verbonden. Vals, anders. */ public boolean isOnline() { return connection.isConnected(); } /** * Retourneert de {@link Connection}-instantie van de client. */ public Connection getConnection() { retourverbinding; } }

Verbinding.java

import java.io. DataInputStream; import java.io. DataOutputStream; import java.io. IOException; import java.net. Socket; import java.net. SocketException; /** * De klasse {@code Connection} vertegenwoordigt ofwel een verbinding van server naar client of een client-eindpunt in een netwerk * {@code Connection} kan, eenmaal verbonden, gegevens uitwisselen met andere partij of partijen, afhankelijk van op een server * implementatie. *

* Deze klasse is threadsafe. * * @versie 1.0 * @see Server * @see Client */ public class Verbinding implementeert Runnable { private Socket socket; privé DataOutputStream uit; privé DataInputStream in; privé Thread-thread; privé definitief Object writeLock = new Object(); privé definitief Object readLock = nieuw object (); /** * Construeert {@code Connection} met behulp van streams van een gespecificeerde {@link Socket}. * * @param socket Socket om de streams op te halen.*/ public Connection (socket socket) gooit NetworkException {if (socket == null) { throw new IllegalArgumentException ("null socket"); } dit.socket = socket; probeer {out = nieuwe DataOutputStream(socket.getOutputStream()); } catch (IOException e) { throw new NetworkException ("Kon geen toegang krijgen tot uitvoerstroom.", e); } probeer { in = nieuwe DataInputStream(socket.getInputStream()); } catch (IOException e) { throw new NetworkException ("Kon geen toegang krijgen tot invoerstroom.", e); } draad = nieuwe draad (dit); draad.start(); } /** * Leest berichten terwijl de verbinding met de andere partij actief is. */ @Override public void run() { while (!socket.isClosed()) { try { int identifier; byte bytes; gesynchroniseerd (readLock) { identifier = in.readInt(); int lengte = in.readInt(); if (lengte > 0) { bytes = nieuwe byte [lengte]; in.readFully(bytes, 0, bytes.length); } anders { ga verder; } } switch (identifier) { case Identifier. INTERNAL: String command = new String (bytes); if (command.equals("disconnect")) { if (!socket.isClosed()) { System.out.println("Verbindingspakket ontvangen."); probeer { sluiten(); } catch (NetworkException e) { return; } } } pauze; case Identifier. TEXT: System.out.println ("Bericht ontvangen: " + nieuwe String (bytes)); pauze; standaard: System.out.println("Onbekende gegevens ontvangen."); } } catch (SocketException e) { if (!e.getMessage().equals("Socket gesloten")) { e.printStackTrace(); } } catch (IOException e) { e.printStackTrace(); } } } /** * Verzendt gegevens naar de andere partij. * * @param data Gegevens om te verzenden. * @throws NetworkException Als het schrijven naar de uitvoerstroom mislukt. * @throws IllegalStateException Als er wordt geprobeerd gegevens te schrijven terwijl de verbinding is verbroken. * @throws IllegalArgumentException Als de te verzenden gegevens null zijn. * @throws UnsupportedOperationException Als wordt geprobeerd een niet-ondersteund gegevenstype te verzenden. */ public void send (Object data) gooit NetworkException { if (socket.isClosed()) { throw new IllegalStateException ("Gegevens niet verzonden, verbinding is gesloten."); } if (data == null) { gooi nieuwe IllegalArgumentException ("null data"); } int identifier; byte bytes; if (gegevensinstantie van String) { identifier = Identifier. TEXT; bytes = ((String) data).getBytes(); } else { throw new UnsupportedOperationException("Niet-ondersteund gegevenstype: " + data.getClass()); } probeer { gesynchroniseerd (writeLock) { out.writeInt(identifier); out.writeInt(bytes.lengte); uit.schrijven(bytes); uit.flush(); } } catch (IOException e) { throw new NetworkException ("Gegevens konden niet worden verzonden.", e); } } /** * Verzendt een verbreekbericht naar en verbreekt de verbinding met de andere partij. */ public void close() gooit NetworkException { if (socket.isClosed()) { throw new IllegalStateException ("Verbinding is al gesloten."); } probeer { byte message = "disconnect".getBytes(); gesynchroniseerd (writeLock) { out.writeInt(Identifier. INTERNAL); out.writeInt(bericht.lengte); out.write(bericht); uit.flush(); } } catch (IOException e) { System.out.println("Verbindingsbericht kon niet worden verzonden."); } probeer { gesynchroniseerd (writeLock) { out.close(); } } catch (IOException e) { throw new NetworkException ("Fout bij het sluiten van de verbinding.", e); } eindelijk { thread.interrupt(); } } /** * Geeft terug of de verbinding met de andere partij actief is. * * @return Waar als de verbinding actief is. Vals, anders. */ public boolean isConnected() { return! socket.isClosed(); } }

ID.java

/** * De klasse {@code Identifier} bevat constanten die worden gebruikt door {@link Connection} voor het serialiseren en deserialiseren van de gegevens * die via het netwerk worden verzonden. * * @versie 1.0 * @see Verbinding */ public final class Identifier { /** * Identifier voor interne berichten. */ openbare statische finale int INTERN = 1; /** * Identificatiecode voor tekstberichten. */ openbare statische finale int TEXT = 2; }

Netwerkuitzondering.java

/** * De klasse {@code NetworkException} geeft een netwerkfout aan. */ public class NetworkException breidt Exception uit { /** * Stelt een {@code NetworkException} samen met {@code null} als zijn bericht. */ public NetworkException() { } /** * Stelt een {@code NetworkException} samen met het opgegeven bericht. * * @param bericht Een bericht om de fout te beschrijven. */ public NetworkException (String-bericht) { super (bericht); } /** * Stelt een {@code NetworkException} samen met het opgegeven bericht en de oorzaak. * * @param bericht Een bericht om de fout te beschrijven. * @param oorzaak Een oorzaak van een fout. */ public NetworkException (String-bericht, weggooibare oorzaak) { super (bericht, oorzaak); } /** * Creëert een {@code NetworkException} met de opgegeven oorzaak. * * @param oorzaak Een oorzaak van een fout. */ public NetworkException (Gooibare oorzaak) { super (oorzaak); } }

UsageExample.java

/** * De klasse {@code UsageExample} toont het gebruik van {@link Server} en {@link Client}. Dit voorbeeld gebruikt * {@link Thread#sleep(long)} om ervoor te zorgen dat elk segment wordt uitgevoerd, omdat snel starten en sluiten ervoor zorgt dat sommige * segmenten niet worden uitgevoerd. * * @versie 1.0 * @see Server * @see Client */ public class UsageExample { public static void main (String args) throws Exception { String host = "localhost"; int-poort = 10430; Serverserver = nieuwe server(host, poort); Client client = nieuwe Client (host, poort); Draad.slaap (100L); client.send("Hallo."); server.broadcast("Hé, kerel!"); Draad.slaap (100L); server.disconnect(server.getConnections()[0]); // of client.close() om de verbinding met client-side server.close() te verbreken; } }

Aanbevolen: