# Client - Server Problem



## Kassel (29. Mrz 2011)

Hi Community,

ich habe folgendes Problem:
Ich habe einen Server und einen Client ( Telnet - console ) jetzt möchte ich wenn einer eine Console öffnet und dort t:10 eingibt dass ich beim Server dieses t:10 aufspalte so dass ich dann den Wert 10 an eine Variable übergeben kann.

Doch bei mir stürzt der Client ( die Console ) ab wenn ich etwas eingebe...

Ich habe erstmal einen Server der für jeden Client einen Thread anlegt:


```
..
ServerSocket serverSocket = new ServerSocket(5000);
			while (true) {
				System.out.print("Listening for connections on port 5000... ");
				Socket client = serverSocket.accept();
				anzahlClients++;
				Thread t = new Thread(new EchoClientHandler(client, frameController, anzahlClients));
				t.start();
..
```

dann habe ich denn EchoClientHandler der für jede eingegabgene Connection die Eingaben überprüft , jetzt kommt der wichtige Teil:


```
..
outputWriter = new PrintWriter(incomingSocket.getOutputStream());
		bufferedReader = new BufferedReader(new InputStreamReader(
				socket.getInputStream()));
..

	String line = null;
			int wert = 0;
			String parser = "";
			String geparst = null;
			

			int x = 0;
			int y = 0;
			
			while ((line = bufferedReader.readLine()) != null) {
				System.out.println("IP des Clients: " + socket.getInetAddress()
						+ " mit: " + line);
			
				
				byte buffer[] = new byte[1024];
				int ret_read = 0;
				ret_read = socket.getInputStream().read(buffer);
				parser = parser + new String(buffer, 0, ret_read);

				

				if (parser.startsWith("t:") || parser.startsWith("T:")) {

					geparst = parser.substring(2);
					wert = Integer.parseInt(geparst);
					
				}
```


----------



## SlaterB (29. Mrz 2011)

du postest offensichtlich den Code zum Server-Socket sowie den Handler pro Client im Server,
was hat das alles mit einem Absturz im Client zu tun, dessen Code du nicht postest?

generell aber ein Fehler:
im Server hast du einen BufferedReader auf den Socket-InputStream und liest außerdem teilweise direkt aus dem Socket-InputStream,
das ist strengstens zu vermeiden, 
Input- und Output-Ketten sollten absolut sauber nur mit dem jeweiligen Endstück bedient werden, nicht auf halben Wege etwas reinschreiben oder rauslesen

gerade bei Buffer funktioniert das auch technisch nicht: wenn der Client 5 Zeilen schickt und du  bufferedReader.readLine() aufrufst, dann buffert/ catch dieser bis zu x.000 Zeichen, bestimmt alle 5 Zeilen die da sind, 
die erste Zeile liest du aus und erwartest sicherlich, dass danach der socket.getInputStream().read(buffer)-Aufruf die Daten direkt nach der ersten Zeile liefert, 
das passiert aber nicht weil diese Daten schon längst aus dem Socket-InputStream raus in den Buffer des BufferedReaders gewandert sind,
der neue Aufruf liest entweder gar nichts wenn nix vorhanden, wartet vielleicht, oder liest schlimmstenfalls spätere Daten in der Verarbeitung völlig ohne Kontrolle


----------



## Kassel (29. Mrz 2011)

also entschuldigung wenn ich mich falsch ausgedrückt habe ich meine halt wenn ich mich per console zum server connecte ... dann schick er die nachricht ich soll was eingeben und wenn ich was eingeben will dann schliesst die console weil ein fehler aufgetreten ist ... also es ist ein fehler beim server nicht bei der console...

zweitens ... so wie ich dich verstanden habe soll ich kein BufferedReader nutzen sondern einfach sagen:


```
InputStream in=socket.getInputStream();
```

und dann 


```
byte buffer[] = new byte[1024];
			int ret_read = 0;
			boolean end_loop = false;

			
			do{
				try{
					
				ret_read = in.read(buffer);
				if(ret_read > 0)
				{
				parser = parser + new String(buffer, 0, ret_read);

				if (parser.startsWith("t:") || parser.startsWith("T:")) {
					geparst = parser.substring(2);
					wert = Integer.parseInt(geparst);
					System.out.println(1);
				}
                              catch (Exception e)
				                        {
			                           System.err.println("Exception while reading  keyboard:"                          +            e.getMessage());
				                            end_loop = true;
				                       }
}
while((ret_read > 0) && (end_loop == false));
```


----------



## SlaterB (29. Mrz 2011)

der neue Code sieht funktional aus, ob es so geht musst du wissen,

was ist es denn für eine Exception, gib sie doch mit e.printStackTrace(); aus?
nur dass du sagst 'ich habe eine Exception' bringt die Welt ja nicht weiter (und bitte nicht entschuldigen)

ich selber kann dein Programm nicht testen, dafür müsstest du komplett lauffähigen Server + Client posten,
sicherlich könnte ich restlichen Code ergänzen, aber das wäre ja etwas Arbeit die du auch übernehmen kannst


----------



## Kassel (29. Mrz 2011)

Also ich würde es nett finden wenn du mir ein kleines Beispiel snippet geben könntest wie es aussehen soll ... also haupt sächlich was brauche ich, wenn ich an den Server etwas per telnet schicke damit er es richtig interpretiert.

Also ich schicke per Telnet ein t:10 er soll mit sagen wert=10 ...


----------



## Kassel (29. Mrz 2011)

die Exception lautet: 
Exception while reading keyboard:null

bringt mich aber nicht weiter


----------



## SlaterB (29. Mrz 2011)

erhälst du "Exception while reading keyboard:null" beim Client?
das würde zu meiner Internet-Suche passen, ein solcher Text ist nämlich manuell in TelnetClientExample.java und ähnlichen Client-Code eingetippt, verwendest du das?

wobei du ja schon sagst dass du Telnet verwendest, aber eher ein richtiges Programm, keinen eigenen Java-Client?
alles Infos die du nennen könntest

jetzt sehe ich auch dass "Exception while reading keyboard" sogar direkt in deinem Code drinsteht,
das ist in der Tat nur begrenzt hilfreich, aber schon ein bisschen, deutet auf NullPointerException hin,

ich schrieb aber doch, e.printStackTrace(); einzufügen? und zwar in den catch-Block, dann erfährst du die genaue Exception und Zeilennummern, in welcher Zeile tritt der Fehler auf?


----------



## Kassel (29. Mrz 2011)

also ich benutze keinen eigenen Java-Client ... ich öffne nur die Console dort tippe ich telnet localhost 5000 ein und connecte mich ... also die fehler ausgabe ist im server sozusagen.

Fehler ausgabe:

Exception while reading keyboard:null
java.lang.NullPointerException
	at EchoClientHandler.run(EchoClientHandler.java:100)
	at java.lang.Thread.run(Unknown Source)

und die Zeile 100 war ein weiteres Stück code von mir habe es jetzt auskommentiert ... 

frameController.getHauptFrame().getTempLv().setValue(wert);

...
jedoch wenn ich jetzt wieder starte bekomme ich eine fehlermeldung:

java.lang.NumberFormatException: For input string: ""
	at java.lang.NumberFormatException.forInputString(Unknown Source)
	at java.lang.Integer.parseInt(Unknown Source)
	at java.lang.Integer.parseInt(Unknown Source)
	at EchoClientHandler.run(EchoClientHandler.java:76)
	at java.lang.Thread.run(Unknown Source)

und zeile 76 ist : wert = Integer.parseInt(geparst);


----------



## SlaterB (29. Mrz 2011)

nun, die NullPointerException dürfte also klar sein, noch nicht geklärt aber deutlich mit irgendwas komischen bei dir verknüpft,

die andere Exception besagt ganz offensichtlich, dass du Integer.parseInt() mit einem Leerstring "" aufrufst, was nicht erlaubt ist,
die Lösung dazu ist mal wieder fast zu trivial, aber man muss es wohl sagen:
untersuche das ganze!, 
gib 'ret_read' aus, wieviele Zeichen wurden gelesen, gib den String parser aus, was genau kommt alles an?
wenn es nur "t:" ist, dann liefert parser.substring(2); offensichtlich den Leerstring und die Exception ist geklärt

die genaue Problemursache ist damit noch nicht gefunden, aber Informationen dazu!, das ist das wichtige,
finde heraus was gelesen wird und danach kann man weiter nachdenken vorher das wohl kommt

was genau gibst du denn im Client ein, wenn kein Java-Programm zu posten ist, dann Screenshot vom anderen?
kann man hier ans Posting anhängen

vielleicht sendet Telnet die Zeichen einzeln, das könntest du daran erkennen wenn im ersten Schleifendurchlauf nur ein t ankommt, danach das : usw.,
dann sammle erst in einer Schleife soviel wie geht, und DANACH substring() usw.


----------



## Kassel (29. Mrz 2011)

Also ich sehe es genau wie du ... ich gebe t: ein dann wird die verbindung geschlossen ... also er kommt in die if rein und dann möchte er "" in int umwandeln was ja nicht geht:

jedoch hier noch ein Bild von der Console:


----------



## Kassel (29. Mrz 2011)

also ich muss es ürgend wie schaffen dass ich t:10 eingebe und erst wenn ich Enter drücke soll er den Wert schicken.
Und nicht sofort , also wenn ich t eingetippt habe weiss er dass schon... dort liegt das Problem , jedoch wie kann ich dass lösen


----------



## SlaterB (29. Mrz 2011)

das scheint mir kein Screenshot von der TelNet-Eingabe zu sein, die beweisen soll, dass du mehr als t: eingibst,
auch ist das kaum ein Log wie gewünscht mit Ausgabe was in parser drinsteht usw.

na wie auch immer, die letzten beiden Zeilen in meinem vorherigen Postings sind bestimmt das Problem,
klingt mir immer vertrauter wenn ich TelNet höre,
da musst du umstellen

> also ich muss es ürgend wie schaffen dass ich t:10 eingebe und erst wenn ich Enter drücke soll er den Wert schicken.

wenn der Client kein Java-Programm ist, hast du darauf doch keine Kontrolle wann dieser etwas schickt, oder?
wie du den Server umstellst, falls du den meinst, habe ich ja bereits angedeutet, erst Zeichen sammeln, später verarbeiten


----------



## Kassel (29. Mrz 2011)

ja da der client kein java programm ist habe ich darauf keinen zugriff das stimmt ... also ich habe nie behauptet dass ich es schaffe mehr als t: einzugeben ... bei t: bricht er schon ab dass sieht man auf dem bild ... 
also zu erst sammeln und dann verarbeiten - dass ist mir klar 
doch wie weiss der server dass er nichts mehr sammeln soll - also z.b: bei t:10 soll er aufhören zu sammeln ... also t:10 dann enter drücken , dann kann ich wieder t:30 eingeben und so weiter - also ich möchte ihm beibringen dass er bei Enter aufhören soll zu sammeln und nach dem enter soll er wieder anfangen , damit ich die zweite variable verarbeiten kann ...


----------



## SlaterB (29. Mrz 2011)

ui, bei t: Abbruch im Telnet-Client,
tatsächlich, das ergibt Sinn, mit der Info hätte ich alles viel schneller geschaltet 

dass du das bisher nicht so genau erzählt hast ist keine Auszeichnung und kontraproduktives hast du durchaus geschrieben, etwa
"Also ich schicke per Telnet ein t:10" 

aber genug gemeckert, dein neues Posting enthält doch quasi auch die Anleitung für dich:
lies solange Zeichen für Zeichen ein bis eben auch ein Enter dabei ist, ob das letzte Zeichen ein Enter ist kannst du testen,
oder gar wieder BufferedReader mit readLine() versuchen, erspart dir eine Schleife

dann hast du eine Zeile vorliegen, falls vom BufferedReader ohne Zeilenumbruch am Ende, ansonsten evtl. mit,
in dieser Zeile dann nach t: suchen usw.


----------



## Kassel (29. Mrz 2011)

SlaterB danke für deine Mühe, doch mir ist ein geistes Blitz durch den Kopf geschossen und ich habe es auf eine sehr sehr einfache Art gelöst :

einfach nur:

```
bufferedReader = new BufferedReader(new InputStreamReader(
				socket.getInputStream()));
.
.
.
String parser = "";
while ((parser = bufferedReader.readLine()) != null) {
.
.
.
}
```

Dadurch bekomme ich die ganze Zeile bis zum Enter also ist in diesem Fall parser="t:10" ... wenn ich t:10 eingebe ... jedoch vielen Dank für deine Mühe


----------



## SlaterB (29. Mrz 2011)

so ein 'jedoch' lese ich gar nicht gerne, zumal ich auf diese Möglichkeit im letzten Posting auch hingewiesen
und dich am Anfang überhaupt nicht von BufferedReader weggedrängt habe


----------



## Kassel (29. Mrz 2011)

Verstehe mich bitte nicht falsch - ich schätze all deine Mühe und all deine Investierte Zeit.
Ich hasse es selber wenn jemand nicht wertschätzt was jemand für einen macht

Nochmals danke:toll:


----------

