Java-Socket: Erstellen einer Client/Server-Chat-Anwendung

In diesem Tutorial erfahren Sie, wie Sie mithilfe von Sockets eine Java-Chat-Anwendung zwischen zwei Computern erstellen. Bevor Sie mit dem Programmierteil beginnen, müssen Sie Ihr Netzwerk so konfigurieren, dass diese beiden Maschinen beispielsweise im lokalen Netzwerk Ihres Hauses interagieren. Wir werden das implementieren, was wir in der Theorie gesehen haben: das bekannte Client/Server-Modell.

Am Ende dieses Tutorials werden Sie wissen, wie Sockets Nachrichten austauschen können.

Server

Der javaServer> initialisiert die Verbindung, lauscht auf einem Port und wartet darauf, dass eingehende Verbindungen akzeptiert werden. Die Portnummer ist beispielsweise 5000, der Client sendet eine Anfrage an den Server mit dieser Portnummer 5000. Der Server nimmt die Anfrage entgegen und übermittelt seine Informationen (IP-Adresse) an den Client. Nun ist die Verbindung hergestellt und ein Nachrichtenaustausch kann stattfinden.

Java stellt ein Paket java.net zur Verfügung, das alles vernetzt, Sie benötigen nur zwei Klassen:

  • java.net.ServerSocket: Diese Klasse akzeptiert Verbindungen von clients.
  • java.net.Socket: Diese Klasse verbindet sich mit dem entfernten Rechner.
Sie benötigen auch ein Tool, um den Stream einzugeben, zu senden und zu empfangen:
  • Scan: Tastatureingaben lesen.
  • BufferedReader: Lesen Sie den vom Absender empfangenen Text.
  • PrintWriter: Senden Sie den eingegebenen Text.
ServerSocket socketserver; 
Socket des Servers;
final BufferedReader in;
final PrintWriter raus;
final Scanner sc=neuer Scanner(System.in);
try {
socketserver = new ServerSocket(5000);
serversocket = socketserver.accept();
out = new PrintWriter(serversocket.getOutputStream());
in = new BufferedReader (new InputStreamReader (serversocket.getInputStream()));
String s;
s = sc.next();
out.println(s);
out.flush();
String message_client;
message_client = in.readLine();
System.out.println("Client: "+message_client);
}
catch (IOException e) {
e.printStackTrace();
}
Nachdem der Server-Socket mit der Portnummer 5000 erstellt wurde, wartet der Server auf eingehende Verbindungen, und sobald eine erkannt wird, akzeptiert er sie. Die beiden Variablen, die den Lese- und Schreibfluss in und out werden so initialisiert, dass sie direkt mit dem Sende- und Empfangsstrom verknüpft werden.
Die Variable s  Speichert Text, der mit dem next(), und dann wird es mit dem println(s).
Die Methode flush() ist wichtig, weil es den Schreibpuffer in die Ausgabe leert, sonst wird ein null wird von der anderen Maschine empfangen.
Die Variable message_client speichert die Nachricht   Quittung, die mit println().

Die Einschränkung dieses Codes besteht darin, dass er eine Nachricht nur einmal senden und empfangen kann. Sie haben eine Idee im Kopf: Fügen Sie eine Schleife hinzu while(true). Dies ist richtig, aber wenn der Server beispielsweise eine Nachricht an den Client sendet, kann der Client die Nachricht erst abrufen, wenn er sie ebenfalls sendet. Die optimale Lösung besteht darin, zwei Threads zu erstellen: einen zum Senden und den anderen zum Empfangen. Beide Prozesse ermöglichen das gleichzeitige Senden und Empfangen.

import java.io.BufferedReader; 
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
/*
* www.codeurjava.com
*/
public class Server {

public static void main(String[] test) {

final ServerSocket serverSocket;
final Socket clientSocket;
letzter BufferedReader in;
endgültiger PrintWriter raus;
Scanner sc=new Scanner(System.in);

try {
serverSocket = new ServerSocket(5000);
clientSocket = serverSocket.accept();
out = new PrintWriter(clientSocket.getOutputStream());
in = new BufferedReader (new InputStreamReader (clientSocket.getInputStream()));
Thread send= new Thread(new Runnable() {
String msg;
@Override
public void run() {
while(true){
msg = sc.nextLine();
out.println(msg);
out.flush();
}
}
});
send.start();

Thread receive= new Thread(new Runnable() {
String msg;
@Override
public void run() {
try {
msg = in.readLine();
//solange der Client verbunden ist
while(msg!=null){
System.out.println("Client: "+msg);
msg = in.readLine();
}
//Beenden der Schleife, wenn der Client deconected hat
System.out.println("Client deconected");
//schließen Stream- und Session-Socket
out.close();
clientSocket.close();
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
});
receive.start();
}catch (IOException e) {
e.printStackTrace();
}
}
}

Die Trennung der beiden Prozesse ist klar, der Server und der Client können jederzeit und unbegrenzt Daten austauschen. Die while-Schleife der Wiedergabe testet, ob die Verbindung noch hergestellt ist. Denken Sie daran, Ihre Lese- und Schreibstreams sowie die Verbindung nach dem Beenden der Schleife mit dem close().

Client

Client benötigt nur den Socket zum Herstellen der Server-Verbindung auf Konstruktor verwendet die IP-Adresse und Portnummer des Servers als Eingabe. Der Rest des Codes ist derselbe wie der des servers.

import java.io.BufferedReader; 
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Scanner;
/*
* www.codeurjava.com
*/
public class Client {

public static void main(String[] args) {

final Socket clientSocket;
letzter BufferedReader in;
endgültiger PrintWriter raus;
final Scanner sc = new Scanner(System.in);//to read from keyboard

try {
/*
* Serverinformationen ( Port und IP-Adresse oder Hostname
* 127.0.0.1 ist die lokale Adresse des Rechners
*/
clientSocket = new Socket("127.0.0.1", 5000);

//stream to send
out = new PrintWriter(clientSocket.getOutputStream());
//stream to receive
in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));

Thread send = new Thread(new Runnable() {
String msg;
@Override
public void run() {
while(true){
msg = sc.nextLine();
out.println(msg);
out.flush();
}
}
});
send.start();

Thread empfangen = new Thread(new Runnable() {
String msg;
@Override
public void run() {
try {
msg = in.readLine();
while(msg!=null){
System.out.println("Server: "+msg);
msg = in.readLine();
}
System.out.println("Deconected server");
out.close();
clientSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
});
receive.start();

} catch (IOException e) {
e.printStackTrace();
}
}
}
Execution:

Java tcp socket server
Serverfenster
Client-Socket tcp java
Client window
Hinweis: Wenn Sie auf demselben Computer arbeiten, müssen Sie Eclipse zweimal ausführen, einmal für den Server und einmal für den Client. Sehen Sie sich das folgende YouTube-Video an:
https://www.youtube.com/watch?v=d-eD6EDa3io


Referenzen:
Netzwerk in Java - IP-Adressen manipulieren
So rufen Sie den Namen und die lokale IP-Adresse des Servers/Clients ab
Openclassrooms: Einführung in sockets
Java-Dokument: Klasse Socket