Nur die erste Nachricht kommt beim Server an

memo1990

Aktives Mitglied
Hallo zusammen,

bin gerade in die Netzwerkprogrammierung eingetaucht und habe für mich als Beispiel auch schon ein Client Server Programm geschrieben. Soll ein Chat-Programm sein. Das Problem aber ist, das nur die erste Nachricht übermittelt wird. Den Fehler habe ich soweit nicht gefunden.

Hier der Code:

Server:

Java:
package client_server;

import java.io.*;
import java.net.*;

class Server {
	private ServerSocket server;
	private Socket client;
	
	Server(int port) {
		try {
			server = new ServerSocket(port); // Server starten
			System.out.println("Server gestartet!");
			
			while(true) {
				client = server.accept(); // Wartet hier bis ein Client sich meldet
				
				// Sobald sich ein Client gemeldet hat wird ein eigener Thread für ihn erstellt, damit diese Schleife auf weitere Verbindungen warten kann
				Thread t = new Thread(new ClientHandler(client));
				t.start(); // Thread wird gestartet
			}
			
		} catch(IOException e) {
			
		}
	}
	
	public static void main(String[] args) {
		Server s = new Server(5555);
	}
}

class ClientHandler implements Runnable {
	Socket client;
	
	private BufferedReader inReader;
	private String sIn;
	
	ClientHandler(Socket c) {
		client = c;
	}
	
	public void run() {
		try {
			// Streams
			inReader = new BufferedReader(new InputStreamReader(client.getInputStream()));
			sIn = inReader.readLine();
			System.out.println(sIn);
		} catch (IOException e) {
			
		}
	}
}

Client:

Java:
package client_server;

import java.io.*;
import java.net.*;
import java.util.Scanner;

class Client {
	private Socket client;
	
	private BufferedWriter outWriter;
	private String message;
	
	private Scanner scan;
	
	Client(String host, int port) {
		try {
			client = new Socket(host, port); // Client starten und durch Angabe von "Host" und "Port" mit Server verbinden
			System.out.println("Client gestartet!");
			
			starteChat();
		} catch (UnknownHostException e) {
			System.err.print("Server nicht gefunden!");// Falls Server nicht gefunden wurde
		} catch (IOException e) {
			System.err.print("I/O Fehler!");
		}
	}
	
	private void starteChat() {
		try {
			outWriter = new BufferedWriter(new OutputStreamWriter(client.getOutputStream()));
			scan = new Scanner(System.in); // Eingabe von Konsole lesen
			
			while (true) {
				System.out.print("Nachricht eingeben: ");
				message = scan.nextLine();
				
				if (message.equals("exit")) // Wenn "exit" eingeben wird, wird der Client beendet
					break;
				
				outWriter.write(message); // Eingabe an Server schicken.
				outWriter.newLine(); // Damit auf der anderen Seite, der BufferedReader mit der Methode readLine() vom Server, auch das Ende der Zeile erkannt wird, muss explizit einen Zeilenumbruch mitgeschickt werden
				outWriter.flush(); // Damit das geschriebene, der vorerst im Puffer liegt, sofort verschickt wird
			}
			
			outWriter.close(); // Stream schließen
		} catch (IOException e) {
			
		}
		
	}
	
	public static void main(String[] args) {
		Client c = new Client("localhost", 5555);
	}
}

Danke schon mal im Voraus für eure Unterstützung.
 
Zuletzt bearbeitet:

Shine

Mitglied
Um das mal etwas genauer zu verdeutlichen...
-------------------------------------------------
Dein Server wartet in einer Schleife, bis sich ein Client verbindet... (Soweit OK)

Dann erstellt dein Server einen Thread, und diesem wird der Socket als Parameter über geben... (auch noch OK)

So... Was passiert jetzt in diesem Thread?

In diesem Thread wird (in der run-Methode) eine Zeile der empfangenen Daten gelesen und ausgegeben...

Und weiter? Was genau passiert denn mit einer Methode, wenn sie durchlaufen wurde?

Und woher weiß denn der Server, dass der Client überhaupt schon Daten gesendet hat, die er lesen und ausgeben kann?

Denk mal über diese Fragen nach und überleg dir, wie du die Antworten darauf auf deinen Quellcode übertragen kannst.

Schau dazu am besten auch mal in der Java-Doc nach, was es da so für Methoden bei den Streams gibt und wofür diese gut sind.
 
Zuletzt bearbeitet:

memo1990

Aktives Mitglied
Danke. Bin die Fragen durchgegangen und es klappt jetzt. Ich wusste bis jetzt auch nicht, dass die Read-Methoden vom java.io-Paket blockierend sind.

Hier der abgeänderter Codeabschnitt von Klasse Server:

Java:
public void run() {
		try {
			// Streams
			inReader = new BufferedReader(new InputStreamReader(client.getInputStream()));
			sIn = inReader.readLine(); // Blockiert bis eine Nachricht vom Client empfangen wird
			
			while (!sIn.equals("exit")) {
				System.out.println(sIn);
				sIn = inReader.readLine(); // Blockiert erneut bis eine Nachricht vom Client empfangen wird
			}
		} catch (IOException e) {
			
		}
	}

Was mir aber noch durch den Kopf geht ist die folgende Frage von dir:

Und woher weiß denn der Server, dass der Client überhaupt schon Daten gesendet hat, die er lesen und ausgeben kann?


Ich könnte mittels der ready() Methode von BufferedReader prüfen, ob Bytes zur Verfügung stehen die gelesen werden können. Wenn aber false zurück kommt, wird ja wieder die Methode beendet und es wird später wieder nichts gelesen.
 
Zuletzt bearbeitet:

Sen-Mithrarin

Gesperrter Benutzer
finger weg von ready() ... ist ne ziemliche fehl-implementierung

ready() gibt true wenn garantiert werden kann das der nächste call von read() definitiv nicht blockierend ist ...
false hingegen ist aber kein garant dafür das ready() nächste mal blockieren wird

wozu es diese methode gibt weis ich nicht ... könnte man eigentlich als deprecated ausm verkehr ziehen ...
 

Curiosus

Mitglied
Entschuldigt, dass ich mich hier mal mit einmische aber das man ready() nicht nutzen sollte wusste ich noch nicht, da man diesen Befehl auch in vielen Tutorials sieht und das hat mich jetzt ziemlich neugierig gemacht. Was gäbe es denn da für Alternativen?
 

Sen-Mithrarin

Gesperrter Benutzer
ready() liefert einen bool

dieser bool kann zwei zustände haben : true und false ... und beide zustände haben eine bestimmte bedeutung

true : der nächste call von read() wird definitiv nicht blockieren
das heißt : man hat die gewissheit das man read() callen kann und definitiv ein ergebnis bekomt ... das geht dann so lange gut bis keine daten mehr vorhanden sind ... und in diesem fall sollte ready() dann auch false liefern ...
es macht aber keinen sinn in einem loop immer wieder zu fragen : sind daten da ? ... wenn man einfach direkt read() callt und wenn daten da sind diese halt liest und wenn nicht halt darauf wartet
außerdem kommt es hier bei vielen anfängern zu dem fehler das entweder die loop-bedingung falsch implementiert wird ... also die funktionsweise dieser methode ausgehebelt wird ... oder wenn es dann doch mal richtig ist ein einfaches sleep() fehlt um den cpu vor 100% auslastung zu bewahren

false : das system weis selbst nicht ob es sich sicher sein kann ob read() blockiert oder nicht
was ist das denn für ein schrott ? entweder das system weis : jap, read() wird blockieren ... oder : nope, read() wird nicht blockieren
hier kommt es zum fehler : false ist lediglich das gegenüber von true ... aber hier aber nicht die direkt umgekehrte aussage zur folge
nur weil true bedeutet : jo, kannst lesen ... heißt false halt im umkehr nicht gleich : nope, kannst nicht lesen ... sondern halt nur das sich das system nicht 100% sicher ist das der nächste call von read() nicht blockierend sein wird ...
false bedeutet hier nicht das read() definitiv blockieren wird


in meinen augen ist diese methode so dermaßen nutzlos ... man sollte sie wirklich aus dem verkehr ziehen

bei live-kommunikation ... sei es nun über das terminal mit nem user oder über n socket mit ner gegenstelle ... ready() macht keinen sinn ...
und bei "offline"-bearbeitung von daten kann man alles vorher "berechnen" und abgleichen > hier macht die methode noch weniger als gar kein sinn ...
 

Tobse

Top Contributor
Wie Sen-Marithan schon geschrieben hat ist es vollkommen legitim, einfach read aufzurufen. Read kümmer sich darum, dass Daten da sind. Es ist nur wichtig, dann auch zu beachten, wieviel tatsächluch gelesen wurde (rückgabewert).

Kleines Beispiel (Den Code aber so nicht verwenden wenn RAM wichtig ist):
Java:
public byte[] readData(InputStream in, int minBytes, int maxBytes)
{
    int bytesRead = 0;
    byte[] buffer = new byte[maxBytes];
    while ((bytesRead += in.read(buffer, bytesRead + 1, maxBytes - bytesRead)) < minBytes);
    byte[] fin = new byte[bytesRead];
    System.arraycopy(buffer, 0, fin, 0, bytesRead);
    return fin;
}
 
Zuletzt bearbeitet:

Shine

Mitglied
@memo1990
Mal noch ne Anmerkung bezüblich des Codes in deinem 2. Post.

Du wartest zuerst, bis eine Nachricht ankommt und speicherst sie dann in eine Variable, danach gehst du in die while-Schleife und machst da genau das gleiche. Denk mal kurz darüber nach, ob es da nicht evtl. eine Schleife gibt, mit der das etwas eleganter gelöst werden kann.
 

memo1990

Aktives Mitglied
Danke soweit für eure Antworten.

@Shine
Etwa so? :D

Java:
public void run() {
		try {
			// Streams
			inReader = new BufferedReader(new InputStreamReader(client.getInputStream()));
			
			while (true) {
				if (sIn.equals("exit"))
					break;
				
				sIn = inReader.readLine(); // Blockiert bis eine Nachricht vom Client empfangen wird
				System.out.println(sIn);
			}
			
			inReader.close();
		} catch (IOException e) {
			
		}
	}
 

Shine

Mitglied
Naja, die Bedingung zum Schleifenabbruch sollte wenn möglich schon in den Schleifenkopf aber nimm lieber ne do-while-Schleife. (Hmmm... heißt das bei ner do-while-Schleife eigentlich immer noch Schleifenkopf, oder muss man es da Schleifenfuß nennen? ^^)
 
Zuletzt bearbeitet:

memo1990

Aktives Mitglied
Danke @Shine.

Soweit klappt jetzt alles. :applaus:

Eine letzte Frage abseits hätte ich noch: Wie kann man Daten die zwischen Server und Client geschickt werden filtern? Wo her weiß ich ob jetzt eine Nachricht, Nickname, Objekt oder aber auch eine binäre Datei geschickt wird?
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
I Socket Das erste Server-Client Programm Netzwerkprogrammierung 16
V erste Client - Server Anwendung, paar Fragen wie Socketverbindung checken usw. Netzwerkprogrammierung 4
K Erste Schritte mit Netzwerken: Verbindungs-Block Netzwerkprogrammierung 1
Kenan89 JSP-erste Schritte, Java einzubauen Netzwerkprogrammierung 16
D RMI Erste Versuche mit RMI... klappt nicht Netzwerkprogrammierung 35
E Erste Server-Client Anwendung Netzwerkprogrammierung 2
M Socket Nachricht von TCP-Client an Server schicken Netzwerkprogrammierung 12
L Socket Wie kann ich checken ob ein User eine Nachricht per Outputstream an den Server gesendet hat? Netzwerkprogrammierung 1
T Socket jamod WriteMultipleRegistersRequest ist keine ModBus/TCP Nachricht Netzwerkprogrammierung 1
Sogomn IRC-Nachricht Regex Netzwerkprogrammierung 0
H Socket Java | Server sendet Nachricht nur wenn vorher eine JOptionPane-Nachricht ausgegeben wurde. Netzwerkprogrammierung 2
I Server schickt eine Nachricht an Broadcast Netzwerkprogrammierung 2
J Nachricht kommt erst nach beendigung der Anwendung an Netzwerkprogrammierung 4
G Nachricht an Server unverändert Netzwerkprogrammierung 2
H Neues NIO problem nachricht an alle clients Netzwerkprogrammierung 3
B Nachricht über Sockets kommt nicht an Netzwerkprogrammierung 8
G Nachricht an mehrere Clients schicken Netzwerkprogrammierung 10
A JavaMail Problem - Nachricht wird nicht versendet ? Netzwerkprogrammierung 9
H SOAP-Nachricht mit Java Netzwerkprogrammierung 8
G Nachricht von server an alle clients senden Netzwerkprogrammierung 6
M wichtig!! Bitte!! (Nachricht von Server an Client senden) Netzwerkprogrammierung 2
T OutputStream kommt nicht an Netzwerkprogrammierung 18
T String von Client zu Server kommt nicht an Netzwerkprogrammierung 92
Thallius JDBC getConnection kommt nicht zurück Netzwerkprogrammierung 1
M Byte Array kommt nicht an Netzwerkprogrammierung 0
C Über welchen Netzwerkadapter kommt mein receive? Netzwerkprogrammierung 15
K TrafficClass eines UDP Pakets kommt beim Empfänger nicht an Netzwerkprogrammierung 5
B InetAddress.getHostAddress() wo kommt die IP Auslösung her? Netzwerkprogrammierung 6
O BufferedReader.readline kommt nicht zurück Netzwerkprogrammierung 7
K Chat: Verbindung kommt nicht zu stande Netzwerkprogrammierung 6

Ähnliche Java Themen


Oben