So erstellen Sie eine Netzwerkanwendung in Java (mit Bildern)

Inhaltsverzeichnis:

So erstellen Sie eine Netzwerkanwendung in Java (mit Bildern)
So erstellen Sie eine Netzwerkanwendung in Java (mit Bildern)

Video: So erstellen Sie eine Netzwerkanwendung in Java (mit Bildern)

Video: So erstellen Sie eine Netzwerkanwendung in Java (mit Bildern)
Video: Samsung - Bildschirmaufnahme 2024, Kann
Anonim

Das Schreiben von Code, der auf einem bestimmten Gerät ausgeführt wird, ist sehr zufriedenstellend. Aber das Schreiben von Code, der auf mehreren Geräten ausgeführt wird, die miteinander kommunizieren, ist einfach lebensbejahend. In diesem Artikel erfahren Sie, wie Sie mit dem Transmission Control Protocol (TCP) Nachrichten über ein Netzwerk verbinden und austauschen.

In diesem Artikel richten Sie eine Anwendung ein, die Ihren Computer mit sich selbst verbindet und ihn im Wesentlichen verrückt macht - mit sich selbst sprechen. Sie lernen auch den Unterschied zwischen den beiden am häufigsten verwendeten Streams für die Vernetzung in Java und ihre Funktionsweise kennen.

Daten- und Objektströme

Bevor Sie in den Code eintauchen, muss der Unterschied zwischen den beiden im Artikel verwendeten Streams unterschieden werden.

Datenströme

Datenströme verarbeiten primitive Datentypen und Strings. Über Datenströme gesendete Daten müssen manuell serialisiert und deserialisiert werden, was die Übertragung komplexer Daten erschwert. Datenströme können jedoch mit Servern und Clients kommunizieren, die in anderen Sprachen als Java geschrieben sind. Rohdatenströme ähneln in dieser Hinsicht Datenströmen, aber Datenströme stellen sicher, dass die Daten plattformunabhängig formatiert werden, was von Vorteil ist, da beide Parteien die gesendeten Daten lesen können.

Objektströme

Objektströme verarbeiten primitive Datentypen und Objekte, die implementieren

Serialisierbar

Schnittstelle. Über Objektströme gesendete Daten werden automatisch serialisiert und deserialisiert, was die Übertragung komplexer Daten erleichtert. Objektströme können jedoch nur mit in Java geschriebenen Servern und Clients kommunizieren. Ebenfalls,

ObjectOutputStream

sendet bei der Initialisierung einen Header an den

Eingabestrom

der anderen Partei, die bei der Initialisierung die Ausführung blockiert, bis der Header empfangen wird.

Schritte

Erstellen Sie eine Netzwerkanwendung in Java Step1
Erstellen Sie eine Netzwerkanwendung in Java Step1

Schritt 1. Erstellen Sie eine Klasse

Erstellen Sie eine Klasse und benennen Sie sie nach Belieben. In diesem Artikel wird es benannt

NetzwerkAppBeispiel

öffentliche Klasse NetworkAppExample { }

Erstellen Sie eine Netzwerkanwendung in Java Step2
Erstellen Sie eine Netzwerkanwendung in Java Step2

Schritt 2. Erstellen Sie eine Hauptmethode

Erstellen Sie eine Hauptmethode und deklarieren Sie, dass sie Ausnahmen von auslösen könnte

Ausnahme

Typ und jede Unterklasse davon - alle Ausnahmen. Dies gilt als schlechte Praxis, ist aber für Barebone-Beispiele akzeptabel.

public class NetworkAppExample { public static void main(String args) wirft Ausnahme {}}

Erstellen Sie eine Netzwerkanwendung in Java Step3
Erstellen Sie eine Netzwerkanwendung in Java Step3

Schritt 3. Deklarieren Sie die Serveradresse

In diesem Beispiel wird die lokale Hostadresse und eine beliebige Portnummer verwendet. Die Portnummer muss im Bereich von 0 bis 65535 (einschließlich) liegen. Zu vermeidende Portnummern reichen jedoch von 0 bis 1023 (einschließlich), da es sich um reservierte Systemports handelt.

public class NetworkAppExample { public static void main(String args) wirft Ausnahme { String host = "localhost"; int-Port = 10430; } }

Erstellen Sie eine Netzwerkanwendung in Java Step4
Erstellen Sie eine Netzwerkanwendung in Java Step4

Schritt 4. Erstellen Sie einen Server

Server ist an Adresse und Port gebunden und wartet auf eingehende Verbindungen. Auf Java,

ServerSocket

stellt den serverseitigen Endpunkt dar und seine Funktion akzeptiert neue Verbindungen.

ServerSocket

hat keine Streams zum Lesen und Senden von Daten, da es keine Verbindung zwischen einem Server und einem Client darstellt.

java.net. InetAddress importieren; java.net. ServerSocket importieren; public class NetworkAppExample { public static void main(String args) wirft Ausnahme { String host = "localhost"; int-Port = 10430; ServerSocket-Server = neuer ServerSocket(Port, 50, InetAddress.getByName(Host)); } }

Erstellen Sie eine Netzwerkanwendung in Java Step5
Erstellen Sie eine Netzwerkanwendung in Java Step5

Schritt 5. Serverbeginn protokollieren

Drucken Sie zu Protokollierungszwecken an die Konsole, dass der Server gestartet wurde.

java.net. InetAddress importieren; java.net. ServerSocket importieren; public class NetworkAppExample { public static void main(String args) wirft Ausnahme { String host = "localhost"; int-Port = 10430; ServerSocket-Server = neuer ServerSocket(Port, 50, InetAddress.getByName(Host)); System.out.println("Server gestartet."); } }

Erstellen Sie eine Netzwerkanwendung in Java Step6
Erstellen Sie eine Netzwerkanwendung in Java Step6

Schritt 6. Erstellen Sie einen Kunden

Der Client ist an die Adresse und den Port eines Servers gebunden und wartet nach dem Verbindungsaufbau auf Pakete (Nachrichten). Auf Java,

Steckdose

stellt entweder einen clientseitigen Endpunkt dar, der mit dem Server verbunden ist, oder eine Verbindung (vom Server) zum Client und wird verwendet, um mit dem Teilnehmer am anderen Ende zu kommunizieren.

java.net. InetAddress importieren; java.net. ServerSocket importieren; java.net. Socket importieren; public class NetworkAppExample { public static void main(String args) wirft Ausnahme { String host = "localhost"; int-Port = 10430; ServerSocket-Server = neuer ServerSocket(Port, 50, InetAddress.getByName(Host)); System.out.println("Server gestartet."); Socket-Client = neuer Socket (Host, Port); } }

Erstellen Sie eine Netzwerkanwendung in Java Step7
Erstellen Sie eine Netzwerkanwendung in Java Step7

Schritt 7. Verbindungsversuch protokollieren

Drucken Sie zu Protokollierungszwecken an die Konsole, dass eine Verbindung versucht wurde.

java.net. InetAddress importieren; java.net. ServerSocket importieren; java.net. Socket importieren; public class NetworkAppExample { public static void main(String args) wirft Ausnahme { String host = "localhost"; int-Port = 10430; ServerSocket-Server = neuer ServerSocket(Port, 50, InetAddress.getByName(Host)); System.out.println("Server gestartet."); Socket-Client = neuer Socket (Host, Port); System.out.println("Verbindung zum Server…"); } }

Erstellen Sie eine Netzwerkanwendung in Java Step8
Erstellen Sie eine Netzwerkanwendung in Java Step8

Schritt 8. Verbindung herstellen

Clients werden nie eine Verbindung herstellen, es sei denn, der Server lauscht und akzeptiert, d. h. stellt Verbindungen her. In Java werden Verbindungen hergestellt mit

annehmen()

Methode von

ServerSocket

Klasse. Die Methode blockiert die Ausführung, bis ein Client eine Verbindung herstellt.

java.net. InetAddress importieren; java.net. ServerSocket importieren; java.net. Socket importieren; public class NetworkAppExample { public static void main(String args) wirft Ausnahme { String host = "localhost"; int-Port = 10430; ServerSocket-Server = neuer ServerSocket(Port, 50, InetAddress.getByName(Host)); System.out.println("Server gestartet."); Socket-Client = neuer Socket (Host, Port); System.out.println("Verbindung zum Server…"); Socket-Verbindung = server.accept(); } }

Erstellen Sie eine Netzwerkanwendung in Java Step9
Erstellen Sie eine Netzwerkanwendung in Java Step9

Schritt 9. Protokollieren Sie die hergestellte Verbindung

Drucken Sie zu Protokollierungszwecken an die Konsole, dass die Verbindung zwischen Server und Client hergestellt wurde.

java.net. InetAddress importieren; java.net. ServerSocket importieren; java.net. Socket importieren; public class NetworkAppExample { public static void main(String args) wirft Ausnahme { String host = "localhost"; int-Port = 10430; ServerSocket-Server = neuer ServerSocket(Port, 50, InetAddress.getByName(Host)); System.out.println("Server gestartet."); Socket-Client = neuer Socket (Host, Port); System.out.println("Verbindung zum Server…"); Socket-Verbindung = server.accept(); System.out.println("Verbindung hergestellt."); } }

Erstellen Sie eine Netzwerkanwendung in Java Step10
Erstellen Sie eine Netzwerkanwendung in Java Step10

Schritt 10. Bereiten Sie Kommunikationsströme vor

Die Kommunikation erfolgt über Streams, und in dieser Anwendung müssen Rohdatenströme von (Verbindung vom) Server (zum Client) und Client entweder mit Daten- oder Objektströmen verkettet werden. Denken Sie daran, dass beide Parteien denselben Streamtyp verwenden müssen.

  • Datenströme

    import java.io. DataInputStream; import java.io. DataOutputStream; java.net. InetAddress importieren; java.net. ServerSocket importieren; java.net. Socket importieren; public class NetworkAppExample { public static void main(String args) wirft Ausnahme { String host = "localhost"; int-Port = 10430; ServerSocket-Server = neuer ServerSocket(Port, 50, InetAddress.getByName(Host)); System.out.println("Server gestartet."); Socket-Client = neuer Socket (Host, Port); System.out.println("Verbindung zum Server…"); Socket-Verbindung = server.accept(); System.out.println("Verbindung hergestellt."); DataOutputStream clientOut = new DataOutputStream(client.getOutputStream()); DataInputStream clientIn = new DataInputStream(client.getInputStream()); DataOutputStream serverOut = new DataOutputStream(connection.getOutputStream()); DataInputStream serverIn = new DataInputStream(connection.getInputStream()); } }

  • Objektströme

    Wenn mehrere Objektströme verwendet werden, müssen die Eingabeströme in der gleichen Reihenfolge wie die Ausgabeströme initialisiert werden, da

    ObjectOutputStream

    sendet einen Header an die andere Partei und

    ObjectInputStream

    blockiert die Ausführung, bis der Header gelesen wird.

    import java.io. ObjectInputStream; import java.io. ObjectOutputStream; java.net. InetAddress importieren; java.net. ServerSocket importieren; java.net. Socket importieren; public class NetworkAppExample { public static void main(String args) wirft Ausnahme { String host = "localhost"; int-Port = 10430; ServerSocket-Server = neuer ServerSocket(Port, 50, InetAddress.getByName(Host)); System.out.println("Server gestartet."); Socket-Client = neuer Socket (Host, Port); System.out.println("Verbindung zum Server…"); Socket-Verbindung = server.accept(); System.out.println("Verbindung hergestellt."); ObjectOutputStream clientOut = new ObjectOutputStream(client.getOutputStream()); ObjectOutputStream serverOut = new ObjectOutputStream(connection.getOutputStream()); ObjectInputStream clientIn = new ObjectInputStream(client.getInputStream()); ObjectInputStream serverIn = new ObjectInputStream(connection.getInputStream()); } }

    Die im obigen Code angegebene Reihenfolge ist möglicherweise einfacher zu merken - initialisieren Sie zuerst die Ausgabestreams und dann die Eingabestreams in derselben Reihenfolge. Eine andere Reihenfolge für die Initialisierung von Objektströmen ist jedoch die folgende:

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

Erstellen Sie eine Netzwerkanwendung in Java Step11
Erstellen Sie eine Netzwerkanwendung in Java Step11

Schritt 11. Protokollieren Sie, dass die Kommunikation bereit ist

Drucken Sie zu Protokollierungszwecken an die Konsole, dass die Kommunikation bereit ist.

// Code weggelassen import java.net. InetAddress; java.net. ServerSocket importieren; java.net. Socket importieren; public class NetworkAppExample { public static void main(String args) wirft Ausnahme { String host = "localhost"; int-Port = 10430; ServerSocket-Server = neuer ServerSocket(Port, 50, InetAddress.getByName(Host)); System.out.println("Server gestartet."); Socket-Client = neuer Socket (Host, Port); System.out.println("Verbindung zum Server…"); Socket-Verbindung = server.accept(); System.out.println("Verbindung hergestellt."); // Code weggelassen System.out.println("Kommunikation ist bereit."); } }

Erstellen Sie eine Netzwerkanwendung in Java Step12
Erstellen Sie eine Netzwerkanwendung in Java Step12

Schritt 12. Erstellen Sie eine Nachricht

In dieser Anwendung

Hallo Welt

Text wird an den Server gesendet entweder als

Byte

oder

Zeichenfolge

. Deklarieren Sie eine Variable des Typs, der vom verwendeten Stream abhängt. Verwenden

Byte

für Datenströme und

Zeichenfolge

für Objektströme.

  • Datenströme

    Unter Verwendung von Datenströmen erfolgt die Serialisierung durch die Umwandlung von Objekten in primitive Datentypen oder a

    Zeichenfolge

    . In diesem Fall,

    Zeichenfolge

    wird umgewandelt in

    Byte

    statt geschrieben mit

    writeBytes()

    -Methode, um zu zeigen, wie dies mit anderen Objekten wie Bildern oder anderen Dateien geschehen würde.

    import java.io. DataInputStream; import java.io. DataOutputStream; java.net. InetAddress importieren; java.net. ServerSocket importieren; java.net. Socket importieren; public class NetworkAppExample { public static void main(String args) wirft Ausnahme { String host = "localhost"; int-Port = 10430; ServerSocket-Server = neuer ServerSocket(Port, 50, InetAddress.getByName(Host)); System.out.println("Server gestartet."); Socket-Client = neuer Socket (Host, Port); System.out.println("Verbindung zum Server…"); Socket-Verbindung = server.accept(); System.out.println("Verbindung hergestellt."); DataOutputStream clientOut = new DataOutputStream(client.getOutputStream()); DataInputStream clientIn = new DataInputStream(client.getInputStream()); DataOutputStream serverOut = new DataOutputStream(connection.getOutputStream()); DataInputStream serverIn = new DataInputStream(connection.getInputStream()); System.out.println("Kommunikation ist bereit."); byte messageOut = "Hallo Welt".getBytes(); } }

  • Objektströme

    import java.io. ObjectInputStream; import java.io. ObjectOutputStream; java.net. InetAddress importieren; java.net. ServerSocket importieren; java.net. Socket importieren; public class NetworkAppExample { public static void main(String args) wirft Ausnahme { String host = "localhost"; int-Port = 10430; ServerSocket-Server = neuer ServerSocket(Port, 50, InetAddress.getByName(Host)); System.out.println("Server gestartet."); Socket-Client = neuer Socket (Host, Port); System.out.println("Verbindung zum Server…"); Socket-Verbindung = server.accept(); System.out.println("Verbindung hergestellt."); ObjectOutputStream clientOut = new ObjectOutputStream(client.getOutputStream()); ObjectOutputStream serverOut = new ObjectOutputStream(connection.getOutputStream()); ObjectInputStream clientIn = new ObjectInputStream(client.getInputStream()); ObjectInputStream serverIn = new ObjectInputStream(connection.getInputStream()); System.out.println("Kommunikation ist bereit."); String messageOut = "Hallo Welt"; } }

Erstellen Sie eine Netzwerkanwendung in Java Step13
Erstellen Sie eine Netzwerkanwendung in Java Step13

Schritt 13. Senden Sie die Nachricht

Schreiben Sie Daten in den Ausgabestream und leeren Sie den Stream, um sicherzustellen, dass die Daten vollständig geschrieben wurden.

  • Datenströme

    Die Länge einer Nachricht muss zuerst gesendet werden, damit die andere Partei weiß, wie viele Bytes sie lesen muss. Nachdem die Länge als primitiver Integer-Typ gesendet wurde, können Bytes gesendet werden.

    import java.io. DataInputStream; import java.io. DataOutputStream; java.net. InetAddress importieren; java.net. ServerSocket importieren; java.net. Socket importieren; public class NetworkAppExample { public static void main(String args) wirft Ausnahme { String host = "localhost"; int-Port = 10430; ServerSocket-Server = neuer ServerSocket(Port, 50, InetAddress.getByName(Host)); System.out.println("Server gestartet."); Socket-Client = neuer Socket (Host, Port); System.out.println("Verbindung zum Server…"); Socket-Verbindung = server.accept(); System.out.println("Verbindung hergestellt."); DataOutputStream clientOut = new DataOutputStream(client.getOutputStream()); DataInputStream clientIn = new DataInputStream(client.getInputStream()); DataOutputStream serverOut = new DataOutputStream(connection.getOutputStream()); DataInputStream serverIn = new DataInputStream(connection.getInputStream()); System.out.println("Kommunikation ist bereit."); byte messageOut = "Hallo Welt".getBytes(); clientOut.writeInt(messageOut.length); clientOut.write (messageOut); clientOut.flush(); } }

  • Objektströme

    import java.io. ObjectInputStream; import java.io. ObjectOutputStream; java.net. InetAddress importieren; java.net. ServerSocket importieren; java.net. Socket importieren; public class NetworkAppExample { public static void main(String args) wirft Ausnahme { String host = "localhost"; int-Port = 10430; ServerSocket-Server = neuer ServerSocket(Port, 50, InetAddress.getByName(Host)); System.out.println("Server gestartet."); Socket-Client = neuer Socket (Host, Port); System.out.println("Verbindung zum Server…"); Socket-Verbindung = server.accept(); System.out.println("Verbindung hergestellt."); ObjectOutputStream clientOut = new ObjectOutputStream(client.getOutputStream()); ObjectOutputStream serverOut = new ObjectOutputStream(connection.getOutputStream()); ObjectInputStream clientIn = new ObjectInputStream(client.getInputStream()); ObjectInputStream serverIn = new ObjectInputStream(connection.getInputStream()); System.out.println("Kommunikation ist bereit."); String messageOut = "Hallo Welt"; clientOut.writeObject(messageOut); clientOut.flush(); } }

Erstellen Sie eine Netzwerkanwendung in Java Step14
Erstellen Sie eine Netzwerkanwendung in Java Step14

Schritt 14. Gesendete Nachricht protokollieren

Drucken Sie zu Protokollierungszwecken an die Konsole, dass die Nachricht gesendet wurde.

  • Datenströme

    import java.io. DataInputStream; import java.io. DataOutputStream; java.net. InetAddress importieren; java.net. ServerSocket importieren; java.net. Socket importieren; public class NetworkAppExample { public static void main(String args) wirft Ausnahme { String host = "localhost"; int-Port = 10430; ServerSocket-Server = neuer ServerSocket(Port, 50, InetAddress.getByName(Host)); System.out.println("Server gestartet."); Socket-Client = neuer Socket (Host, Port); System.out.println("Verbindung zum Server…"); Socket-Verbindung = server.accept(); System.out.println("Verbindung hergestellt."); DataOutputStream clientOut = new DataOutputStream(client.getOutputStream()); DataInputStream clientIn = new DataInputStream(client.getInputStream()); DataOutputStream serverOut = new DataOutputStream(connection.getOutputStream()); DataInputStream serverIn = new DataInputStream(connection.getInputStream()); System.out.println("Kommunikation ist bereit."); byte messageOut = "Hallo Welt".getBytes(); clientOut.writeInt(messageOut.length); clientOut.write (messageOut); clientOut.flush(); System.out.println("Nachricht an Server gesendet: " + new String(messageOut)); } }

  • Objektströme

    import java.io. ObjectInputStream; import java.io. ObjectOutputStream; java.net. InetAddress importieren; java.net. ServerSocket importieren; java.net. Socket importieren; public class NetworkAppExample { public static void main(String args) wirft Ausnahme { String host = "localhost"; int-Port = 10430; ServerSocket-Server = neuer ServerSocket(Port, 50, InetAddress.getByName(Host)); System.out.println("Server gestartet."); Socket-Client = neuer Socket (Host, Port); System.out.println("Verbindung zum Server…"); Socket-Verbindung = server.accept(); System.out.println("Verbindung hergestellt."); ObjectOutputStream clientOut = new ObjectOutputStream(client.getOutputStream()); ObjectOutputStream serverOut = new ObjectOutputStream(connection.getOutputStream()); ObjectInputStream clientIn = new ObjectInputStream(client.getInputStream()); ObjectInputStream serverIn = new ObjectInputStream(connection.getInputStream()); System.out.println("Kommunikation ist bereit."); String messageOut = "Hallo Welt"; clientOut.writeObject(messageOut); clientOut.flush(); System.out.println("Nachricht an Server gesendet: " + messageOut); } }

Erstellen Sie eine Netzwerkanwendung in Java Step15
Erstellen Sie eine Netzwerkanwendung in Java Step15

Schritt 15. Lesen Sie die Nachricht

Lesen Sie Daten aus dem Eingabestream und konvertieren Sie sie. Da wir die Art der gesendeten Daten genau kennen, erstellen wir entweder eine

Zeichenfolge

von

Byte

oder werfen

Objekt

zu

Zeichenfolge

ohne Prüfung, je nach verwendetem Stream.

  • Datenströme

    Da zuerst die Länge und danach die Bytes gesendet wurden, muss das Lesen in der gleichen Reihenfolge erfolgen. Falls length null ist, gibt es nichts zu lesen. Das Objekt wird deserialisiert, wenn Bytes zurück in eine Instanz konvertiert werden, in diesem Fall von

    Zeichenfolge

    import java.io. DataInputStream; import java.io. DataOutputStream; java.net. InetAddress importieren; java.net. ServerSocket importieren; java.net. Socket importieren; public class NetworkAppExample { public static void main(String args) wirft Ausnahme { String host = "localhost"; int-Port = 10430; ServerSocket-Server = neuer ServerSocket(Port, 50, InetAddress.getByName(Host)); System.out.println("Server gestartet."); Socket-Client = neuer Socket (Host, Port); System.out.println("Verbindung zum Server…"); Socket-Verbindung = server.accept(); System.out.println("Verbindung hergestellt."); DataOutputStream clientOut = new DataOutputStream(client.getOutputStream()); DataInputStream clientIn = new DataInputStream(client.getInputStream()); DataOutputStream serverOut = new DataOutputStream(connection.getOutputStream()); DataInputStream serverIn = new DataInputStream(connection.getInputStream()); System.out.println("Kommunikation ist bereit."); byte messageOut = "Hallo Welt".getBytes(); clientOut.writeInt(messageOut.length); clientOut.write (messageOut); clientOut.flush(); System.out.println("Nachricht an Server gesendet: " + new String(messageOut)); int-Länge = serverIn.readInt(); if (Länge > 0) { byte messageIn = new byte[length]; serverIn.readFully(messageIn, 0, messageIn.length); } } }

  • Objektströme

    import java.io. ObjectInputStream; import java.io. ObjectOutputStream; java.net. InetAddress importieren; java.net. ServerSocket importieren; java.net. Socket importieren; public class NetworkAppExample { public static void main(String args) wirft Ausnahme { String host = "localhost"; int-Port = 10430; ServerSocket-Server = neuer ServerSocket(Port, 50, InetAddress.getByName(Host)); System.out.println("Server gestartet."); Socket-Client = neuer Socket (Host, Port); System.out.println("Verbindung zum Server…"); Socket-Verbindung = server.accept(); System.out.println("Verbindung hergestellt."); ObjectOutputStream clientOut = new ObjectOutputStream(client.getOutputStream()); ObjectOutputStream serverOut = new ObjectOutputStream(connection.getOutputStream()); ObjectInputStream clientIn = new ObjectInputStream(client.getInputStream()); ObjectInputStream serverIn = new ObjectInputStream(connection.getInputStream()); System.out.println("Kommunikation ist bereit."); String messageOut = "Hallo Welt"; clientOut.writeObject(messageOut); clientOut.flush(); System.out.println("Nachricht an Server gesendet: " + messageOut); String messageIn = (String) serverIn.readObject(); } }

Erstellen Sie eine Netzwerkanwendung in Java Step16
Erstellen Sie eine Netzwerkanwendung in Java Step16

Schritt 16. Gelesene Nachricht protokollieren

Drucken Sie zu Protokollierungszwecken die empfangene Nachricht und ihren Inhalt auf der Konsole aus.

  • Datenströme

    import java.io. DataInputStream; import java.io. DataOutputStream; java.net. InetAddress importieren; java.net. ServerSocket importieren; java.net. Socket importieren; public class NetworkAppExample { public static void main(String args) wirft Ausnahme { String host = "localhost"; int-Port = 10430; ServerSocket-Server = neuer ServerSocket(Port, 50, InetAddress.getByName(Host)); System.out.println("Server gestartet."); Socket-Client = neuer Socket (Host, Port); System.out.println("Verbindung zum Server…"); Socket-Verbindung = server.accept(); System.out.println("Verbindung hergestellt."); DataOutputStream clientOut = new DataOutputStream(client.getOutputStream()); DataInputStream clientIn = new DataInputStream(client.getInputStream()); DataOutputStream serverOut = new DataOutputStream(connection.getOutputStream()); DataInputStream serverIn = new DataInputStream(connection.getInputStream()); System.out.println("Kommunikation ist bereit."); byte messageOut = "Hallo Welt".getBytes(); clientOut.writeInt(messageOut.length); clientOut.write (messageOut); clientOut.flush(); System.out.println("Nachricht an Server gesendet: " + new String(messageOut)); int-Länge = serverIn.readInt(); if (Länge > 0) { byte messageIn = new byte[length]; serverIn.readFully(messageIn, 0, messageIn.length); System.out.println("Nachricht vom Client empfangen: " + new String(messageIn)); } } }

  • Objektströme

    import java.io. ObjectInputStream; import java.io. ObjectOutputStream; java.net. InetAddress importieren; java.net. ServerSocket importieren; java.net. Socket importieren; public class NetworkAppExample { public static void main(String args) wirft Ausnahme { String host = "localhost"; int-Port = 10430; ServerSocket-Server = neuer ServerSocket(Port, 50, InetAddress.getByName(Host)); System.out.println("Server gestartet."); Socket-Client = neuer Socket (Host, Port); System.out.println("Verbindung zum Server…"); Socket-Verbindung = server.accept(); System.out.println("Verbindung hergestellt."); ObjectOutputStream clientOut = new ObjectOutputStream(client.getOutputStream()); ObjectOutputStream serverOut = new ObjectOutputStream(connection.getOutputStream()); ObjectInputStream clientIn = new ObjectInputStream(client.getInputStream()); ObjectInputStream serverIn = new ObjectInputStream(connection.getInputStream()); System.out.println("Kommunikation ist bereit."); String messageOut = "Hallo Welt"; clientOut.writeObject(messageOut); clientOut.flush(); System.out.println("Nachricht an Server gesendet: " + messageOut); String messageIn = (String) serverIn.readObject(); System.out.println("Nachricht vom Client empfangen: " + messageIn); } }

Erstellen Sie eine Netzwerkanwendung in Java Step17
Erstellen Sie eine Netzwerkanwendung in Java Step17

Schritt 17. Verbindungen trennen

Die Verbindung wird getrennt, wenn eine Partei ihre Streams schließt. In Java werden durch Schließen des Ausgabestreams auch zugehörige Sockets und Eingabestreams geschlossen. Sobald eine Partei am anderen Ende feststellt, dass die Verbindung tot ist, muss sie auch ihren Ausgabestrom schließen, um Speicherlecks zu verhindern.

// Code weggelassen import java.net. InetAddress; java.net. ServerSocket importieren; java.net. Socket importieren; public class NetworkAppExample { public static void main(String args) wirft Ausnahme { String host = "localhost"; int-Port = 10430; ServerSocket-Server = neuer ServerSocket(Port, 50, InetAddress.getByName(Host)); System.out.println("Server gestartet."); Socket-Client = neuer Socket (Host, Port); System.out.println("Verbindung zum Server…"); Socket-Verbindung = server.accept(); System.out.println("Verbindung hergestellt."); // Code weggelassen System.out.println("Kommunikation ist bereit."); // Code weggelassen clientOut.close(); serverOut.close(); } }

Erstellen Sie eine Netzwerkanwendung in Java Step18 V2
Erstellen Sie eine Netzwerkanwendung in Java Step18 V2

Schritt 18. Verbindungstrennung protokollieren

Für Protokollierungszwecke wurden die Verbindungen zum Drucken mit der Konsole getrennt.

// Code weggelassen import java.net. InetAddress; java.net. ServerSocket importieren; java.net. Socket importieren; public class NetworkAppExample { public static void main(String args) wirft Ausnahme { String host = "localhost"; int-Port = 10430; ServerSocket-Server = neuer ServerSocket(Port, 50, InetAddress.getByName(Host)); System.out.println("Server gestartet."); Socket-Client = neuer Socket (Host, Port); System.out.println("Verbindung zum Server…"); Socket-Verbindung = server.accept(); System.out.println("Verbindung hergestellt."); // Code weggelassen System.out.println("Kommunikation ist bereit."); // Code weggelassen clientOut.close(); serverOut.close(); System.out.println("Verbindungen geschlossen."); } }

Erstellen Sie eine Netzwerkanwendung in Java Step19
Erstellen Sie eine Netzwerkanwendung in Java Step19

Schritt 19. Server beenden

Die Verbindungen werden getrennt, aber der Server läuft noch. Wie

ServerSocket

mit keinem Stream verknüpft ist, muss er explizit durch Aufrufen geschlossen werden

nah dran()

Methode.

// Code weggelassen import java.net. InetAddress; java.net. ServerSocket importieren; java.net. Socket importieren; public class NetworkAppExample { public static void main(String args) wirft Ausnahme { String host = "localhost"; int-Port = 10430; ServerSocket-Server = neuer ServerSocket(Port, 50, InetAddress.getByName(Host)); System.out.println("Server gestartet."); Socket-Client = neuer Socket (Host, Port); System.out.println("Verbindung zum Server…"); Socket-Verbindung = server.accept(); System.out.println("Verbindung hergestellt."); // Code weggelassen System.out.println("Kommunikation ist bereit."); // Code weggelassen clientOut.close(); serverOut.close(); System.out.println("Verbindungen geschlossen."); server.close(); } }

Erstellen Sie eine Netzwerkanwendung in Java Step20
Erstellen Sie eine Netzwerkanwendung in Java Step20

Schritt 20. Serverbeendigung protokollieren

Für Protokollierungszwecke wurde der Druck auf den Konsolenserver beendet.

// Code weggelassen import java.net. InetAddress; java.net. ServerSocket importieren; java.net. Socket importieren; public class NetworkAppExample { public static void main(String args) wirft Ausnahme { String host = "localhost"; int-Port = 10430; ServerSocket-Server = neuer ServerSocket(Port, 50, InetAddress.getByName(Host)); System.out.println("Server gestartet."); Socket-Client = neuer Socket (Host, Port); System.out.println("Verbindung zum Server…"); Socket-Verbindung = server.accept(); System.out.println("Verbindung hergestellt."); // Code weggelassen System.out.println("Kommunikation ist bereit."); // Code weggelassen clientOut.close(); serverOut.close(); System.out.println("Verbindungen geschlossen."); server.close(); System.out.println("Server beendet."); } }

Erstellen Sie eine Netzwerkanwendung in Java Step21
Erstellen Sie eine Netzwerkanwendung in Java Step21

Schritt 21. Kompilieren und ausführen

Durch die Protokollierung konnten wir feststellen, ob die Bewerbung erfolgreich war oder nicht. Erwartete Ausgabe:

Server gestartet. Verbindung zum Server wird hergestellt… Verbindung hergestellt. Die Kommunikation ist bereit. Nachricht an Server gesendet: Hello World Nachricht vom Client empfangen: Hello World Verbindungen geschlossen. Server beendet.

Falls Ihre Ausgabe nicht der obigen entspricht, was unwahrscheinlich ist, gibt es einige Lösungen:

  • Wenn die Ausgabe an der Linie stoppt

    Verbindung hergestellt.

    und Objektströme verwendet werden, spülen Sie jeden

    ObjectOutputStream

  • unmittelbar nach der Initialisierung, da Header aus irgendeinem Grund nicht gesendet wurden.
  • Wenn die Ausgabe gedruckt wird

    java.net. BindException: Adresse wird bereits verwendet

  • wählen Sie eine andere Portnummer, da die angegebene bereits verwendet wird.

Tipps

  • Die Verbindung zu einem Server in einem anderen Netzwerk wird hergestellt, indem eine Verbindung zur externen IP-Adresse eines Geräts hergestellt wird, auf dem der Server mit einem weitergeleiteten Port ausgeführt wird.
  • Die Verbindung zu einem Server im selben Netzwerk erfolgt entweder durch Verbinden mit der privaten IP-Adresse eines Geräts, auf dem der Server ausgeführt wird, oder durch Weiterleiten eines Ports und Verbinden mit der externen IP-Adresse des Geräts.
  • Es gibt Software wie Hamachi, die eine Verbindung mit dem Server in einem anderen Netzwerk ohne Weiterleitung eines Ports ermöglicht, jedoch erfordert dies die Installation der Software auf beiden Geräten.

Beispiele

Netzwerkanwendungen, die blockierende Eingabe/Ausgabe verwenden, müssen Threads verwenden. Die folgenden Beispiele zeigen eine minimalistische Server- und Clientimplementierung mit Threads. Der Netzwerkcode ist im Wesentlichen der gleiche wie im Artikel, außer dass einige Schnipsel synchronisiert, in Threads verschoben und Ausnahmen behandelt werden.

Server.java

import java.io. IOException; java.net. InetAddress importieren; java.net. ServerSocket importieren; import java.net. SocketException; import java.net. UnknownHostException; import java.util. ArrayList; java.util. Collections importieren; java.util. List importieren; /** * Die Klasse {@code Server} repräsentiert einen Server-Endpunkt in einem Netzwerk. Sobald {@code Server} an eine bestimmte IP * Adresse und einen Port gebunden ist, stellt er Verbindungen zu Clients her und kann mit ihnen kommunizieren oder sie trennen. *

* Diese Klasse ist threadsicher. * * @version 1.0 * @see Client * @see Connection */ public class Server implementiert Runnable { private ServerSocket server; private Liste Verbindungen; privater Thread-Thread; privates finales Objekt connectionLock = new Object(); /** * Konstruiert einen {@code Server}, der mit Clients auf dem angegebenen Hostnamen und Port mit der angegebenen * angeforderten maximalen Länge einer Warteschlange eingehender Clients interagiert. * * @param host Zu verwendende Hostadresse. * @param port Zu verwendende Portnummer. * @param backlog Angeforderte maximale Länge der Warteschlange eingehender Clients. * @throws NetworkException Wenn beim Starten eines Servers ein Fehler auftritt. */ public Server(String host, int port, int backlog) wirft NetworkException { try { server = new ServerSocket(port, backlog, InetAddress.getByName(host)); } catch (UnknownHostException e) { throw new NetworkException("Hostname konnte nicht aufgelöst werden: " + host, e); } catch (IllegalArgumentException e) { throw new NetworkException("Portnummer muss zwischen 0 und 65535 (einschließlich): " + port); } catch (IOException e) { throw new NetworkException("Server konnte nicht gestartet werden.", e); } Verbindungen = Collections.synchronizedList(new ArrayList()); Thread = neuer Thread (dieser); thread.start(); } /** * Konstruiert einen {@code Server}, der mit Clients auf dem angegebenen Hostnamen und Port interagiert. * * @param host Hostadresse zum Binden. * @param port Portnummer zum Binden. * @throws NetworkException Wenn beim Starten eines Servers Fehler auftreten. */ public Server(String host, int port) wirft NetworkException { this(host, port, 50); } /** * Hört auf eingehende Verbindungen von Clients, nimmt sie an und registriert sie. */ @Override public void run() { while (!server.isClosed()) { try { connections.add(new Connection(server.accept())); } catch (SocketException e) { if (!e.getMessage().equals("Socket geschlossen")) { e.printStackTrace(); } } catch (NetworkException | IOException e) { e.printStackTrace(); } } } /** * Sendet Daten an alle registrierten Clients. * * @param data Zu sendende Daten. * @throws IllegalStateException Wenn versucht wird, Daten zu schreiben, während der Server offline ist. * @throws IllegalArgumentException Wenn die zu sendenden Daten null sind. */ public void Broadcast(Object data) { if (server.isClosed()) { throw new IllegalStateException("Daten nicht gesendet, Server ist offline."); } if (data == null) { throw new IllegalArgumentException("null data"); } synchronisiert (connectionsLock) { for (Connection connection: connections) { try { connection.send(data); System.out.println("Daten erfolgreich an Client gesendet."); } catch (NetworkException e) { e.printStackTrace(); } } } } /** * Sendet eine Trennungsnachricht und trennt den angegebenen Client. * * @param connection Client zum Trennen. * @throws NetworkException Wenn beim Schließen der Verbindung ein Fehler auftritt. */ public void Disconnect(Connection connection) wirft NetworkException { if (connections.remove(connection)) { connection.close(); } } /** * Sendet eine Trennungsnachricht an alle Clients, trennt sie und beendet den Server. */ public void close() wirft NetworkException { synchronisiert (connectionsLock) { for (Connection connection: connections) { try { connection.close(); } catch (NetworkException e) { e.printStackTrace(); } } } Verbindungen.clear(); versuchen {server.close(); } catch (IOException e) { throw new NetworkException("Fehler beim Schließen des Servers."); } endlich { thread.interrupt(); } } /** * Gibt zurück, ob der Server online ist oder nicht. * * @return True, wenn der Server online ist. Falsch, sonst. */ public boolean isOnline() { return !server.isClosed(); } /** * Gibt ein Array registrierter Clients zurück. */ public Connection getConnections() { synchronisiert (connectionsLock) { return connections.toArray(new Connection[connections.size()]); } } }

Client.java

import java.io. IOException; java.net. Socket importieren; import java.net. UnknownHostException; /** * Die Klasse {@code Client} repräsentiert einen Client-Endpunkt in einem Netzwerk. {@code Client}, sobald eine Verbindung zu einem bestimmten * Server besteht, kann garantiert nur mit dem Server kommunizieren. Ob andere Clients die Daten* erhalten, hängt von der Serverimplementierung ab. *

* Diese Klasse ist threadsicher. * * @version 1.0 * @see Server * @see Connection */ public class Client { private Connection connection; /** * Konstruiert einen {@code Client}, der mit dem Server auf dem angegebenen Host und Port verbunden ist. * * @param host Hostadresse zum Binden. * @param port Portnummer zum Binden. * @throws NetworkException Wenn beim Starten eines Servers ein Fehler auftritt. */ public Client(String host, int port) wirft NetworkException { try { connection = new Connection(new Socket(host, port)); } catch (UnknownHostException e) { throw new NetworkException("Hostname konnte nicht aufgelöst werden: " + host, e); } catch (IllegalArgumentException e) { throw new NetworkException("Portnummer muss zwischen 0 und 65535 (einschließlich) liegen: " + port); } catch (IOException e) { throw new NetworkException("Server konnte nicht gestartet werden.", e); } } /** * Sendet Daten an die andere Partei. * * @param data Zu sendende Daten. * @throws NetworkException Wenn das Schreiben in den Ausgabestream fehlschlägt. * @throws IllegalStateException Wenn versucht wird, Daten zu schreiben, während die Verbindung geschlossen wird. * @throws IllegalArgumentException Wenn die zu sendenden Daten null sind. * @throws UnsupportedOperationException Wenn versucht wird, einen nicht unterstützten Datentyp zu senden. */ public void send(Object data) wirft NetworkException { connection.send(data); } /** * Sendet eine Trennungsnachricht an den Server und schließt die Verbindung mit ihm. */ public void close() wirft NetworkException { connection.close(); } /** * Gibt zurück, ob der Client mit dem Server verbunden ist oder nicht. * * @return True, wenn Client verbunden ist. Falsch, sonst. */ public boolean isOnline() { return connection.isConnected(); } /** * Gibt die {@link Connection}-Instanz des Clients zurück. */ öffentliche Verbindung getConnection() { Verbindung zurückgeben; } }

Verbindung.java

import java.io. DataInputStream; import java.io. DataOutputStream; import java.io. IOException; java.net. Socket importieren; import java.net. SocketException; /** * Die Klasse {@code Connection} repräsentiert entweder eine Verbindung vom Server zum Client oder einen Client-Endpunkt in einem Netzwerk * {@code Connection} kann, sobald eine Verbindung besteht, Daten mit anderen Teilnehmern austauschen, je nachdem auf einem Server *-Implementierung. *

* Diese Klasse ist threadsicher. * * @version 1.0 * @see Server * @see Client */ public class Connection implementiert Runnable { private Socket socket; privater DataOutputStream-Ausgang; privater DataInputStream in; privater Thread-Thread; privates finales Objekt writeLock = new Object(); privates finales Objekt readLock = new Object(); /** * Konstruiert {@code Connection} unter Verwendung von Streams eines angegebenen {@link Socket}. * * @param socket Socket zum Abrufen der Streams.*/ public Connection(Socket socket) throws NetworkException { if (socket == null) { throw new IllegalArgumentException("null socket"); } this.socket = Socket; try { out = new DataOutputStream(socket.getOutputStream()); } catch (IOException e) { throw new NetworkException("Konnte nicht auf Ausgabestream zugreifen.", e); } try { in = new DataInputStream(socket.getInputStream()); } catch (IOException e) { throw new NetworkException("Konnte nicht auf Eingabestream zugreifen.", e); } Thread = neuer Thread (dieser); thread.start(); } /** * Liest Nachrichten, während die Verbindung mit der anderen Partei besteht. */ @Override public void run() { while (!socket.isClosed()) { try { int bezeichner; Byte Byte; synchronisiert (readLock) { Bezeichner = in.readInt(); int-Länge = in.readInt(); if (Länge > 0) { Byte = neues Byte [Länge]; in.readFully(Bytes, 0, Bytes. Länge); } sonst { weiter; } } switch (identifier) { case Identifier. INTERNAL: String-Befehl = new String (Bytes); if (command.equals("disconnect")) { if (!socket.isClosed()) { System.out.println("Disconnection package Received."); versuchen { schließen(); } catch (NetworkException e) { return; } } } brechen; case Identifier. TEXT: System.out.println("Nachricht empfangen: " + new String(Bytes)); brechen; default: System.out.println("Unerkannte Daten empfangen."); } } catch (SocketException e) { if (!e.getMessage().equals("Socket geschlossen")) { e.printStackTrace(); } } catch (IOException e) { e.printStackTrace(); } } } /** * Sendet Daten an den anderen Teilnehmer. * * @param data Zu sendende Daten. * @throws NetworkException Wenn das Schreiben in den Ausgabestream fehlschlägt. * @throws IllegalStateException Wenn versucht wird, Daten zu schreiben, während die Verbindung geschlossen wird. * @throws IllegalArgumentException Wenn die zu sendenden Daten null sind. * @throws UnsupportedOperationException Wenn versucht wird, einen nicht unterstützten Datentyp zu senden. */ public void send(Object data) throws NetworkException { if (socket.isClosed()) { throw new IllegalStateException("Daten nicht gesendet, Verbindung geschlossen."); } if (data == null) { throw new IllegalArgumentException("null data"); } int-Kennung; Byte Byte; if (Dateninstanz von String) { Bezeichner = Bezeichner. TEXT; bytes = ((String) Daten).getBytes(); } else { throw new UnsupportedOperationException("Nicht unterstützter Datentyp: " + data.getClass()); } try { synchronisiert (writeLock) { out.writeInt (identifier); out.writeInt (Bytes. Länge); out.write (Bytes); out.flush(); } } catch (IOException e) { throw new NetworkException("Daten konnten nicht gesendet werden.", e); } } /** * Sendet eine Trennungsnachricht an den anderen Teilnehmer und schließt die Verbindung mit ihm. */ public void close() throws NetworkException { if (socket.isClosed()) { throw new IllegalStateException("Verbindung ist bereits geschlossen."); } try { byte message = "disconnect".getBytes(); synchronisiert (writeLock) { out.writeInt (Identifier. INTERNAL); out.writeInt (Nachricht. Länge); out.write (Nachricht); out.flush(); } } catch (IOException e) { System.out.println("Disconnection message konnte nicht gesendet werden."); } try { synchronisiert (writeLock) { out.close(); } } catch (IOException e) { throw new NetworkException("Fehler beim Schließen der Verbindung.", e); } endlich { thread.interrupt(); } } /** * Gibt zurück, ob die Verbindung zum anderen Teilnehmer aktiv ist oder nicht. * * @return True, wenn die Verbindung aktiv ist. Falsch, sonst. */ public boolean isConnected() { return !socket.isClosed(); } }

Identifier.java

/** * Die Klasse {@code Identifier} enthält Konstanten, die von {@link Connection} zum Serialisieren und Deserialisieren der * über das Netzwerk gesendeten Daten verwendet werden. * * @version 1.0 * @see Connection */ public final class Identifier { /** * Identifier für interne Nachrichten. */ public static final int INTERNAL = 1; /** * Bezeichner für Textnachrichten. */ public static final int TEXT = 2; }

NetworkException.java

/** * Die Klasse {@code NetworkException} zeigt einen Fehler im Zusammenhang mit dem Netzwerk an. */ public class NetworkException erweitert Exception { /** * Konstruiert eine {@code NetworkException} mit {@code null} als Nachricht. */ public NetworkException() { } /** * Konstruiert eine {@code NetworkException} mit der angegebenen Nachricht. * * @param Nachricht Eine Nachricht zur Fehlerbeschreibung. */ public NetworkException(String-Nachricht) { super(Nachricht); } /** * Konstruiert eine {@code NetworkException} mit der angegebenen Nachricht und Ursache. * * @param Nachricht Eine Nachricht zur Fehlerbeschreibung. * @param Ursache Eine Fehlerursache. */ public NetworkException(String-Nachricht, Throwable Cause) { super(Nachricht, Ursache); } /** * Konstruiert eine {@code NetworkException} mit der angegebenen Ursache. * * @param Ursache Eine Fehlerursache. */ public NetworkException(auslösebarer Grund) { super(Ursache); } }

Verwendungsbeispiel.java

/** * Die Klasse {@code UsageExample} zeigt die Nutzung von {@link Server} und {@link Client}. In diesem Beispiel wird * {@link Thread#sleep(long)} verwendet, um sicherzustellen, dass jedes Segment ausgeführt wird, da ein schnelles Starten und Schließen dazu führt, dass einige * Segmente nicht ausgeführt werden. * * @version 1.0 * @see Server * @see Client */ public class UsageExample { public static void main(String args) wirft Ausnahme { String host = "localhost"; int-Port = 10430; Serverserver = neuer Server (Host, Port); Client-Client = neuer Client (Host, Port); Thread.sleep (100L); client.send("Hallo."); server.broadcast("Hey, Kerl!"); Thread.sleep (100L); server.disconnect(server.getConnections()[0]); // oder client.close() zum Trennen vom clientseitigen server.close(); } }

Empfohlen: