# java.net.SocketTimeoutException



## Guest (11. Dez 2007)

Hallo,
könnte mir jemand erläutern, warum ich in der Zeile String line = vomServer.readLine(); eine java.net.SocketTimeoutException  erzeugt wird, und wie ich das umgehen oder abändern könnte?
Nachdem ich den Fall, das nichts gesendet wird mit dem try-catch Block abfange, wird folgend ständig etwas gesendet 


```
public synchronized void run() {
      try {
         vomServer = new BufferedReader(new InputStreamReader(socket
               .getInputStream()));
         zumServer = new BufferedWriter(new OutputStreamWriter(socket
               .getOutputStream()));
         
                        //Dieser Block soll mir den Fall abfangen falls keine Eingabe getätigt worden ist.
         socket.setSoTimeout(3000);
         
          try {
            this.varaible = Integer.parseInt(vomServer.readLine());
         } catch (SocketTimeoutException e) {
            throw new Exception();
         }
         //Nun soll er weiter Strings vom Server auslesen
         String line = vomServer.readLine();
         System.out.println("Test: " + line);
      


      } catch (Exception exc) {
        try {
				exc.printStackTrace();
				zumServer.write("Error");
				socket.close();
			} catch (IOException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}
      }
}
```

Danke


----------



## lhein (11. Dez 2007)

```
//Dieser Block soll mir den Fall abfangen falls keine Eingabe getätigt worden ist.
         socket.setSoTimeout(3000);
         
          try {
            this.varaible = Integer.parseInt(vomServer.readLine());
         } catch (SocketTimeoutException e) {
            throw new Exception();
         }
```

Also ich interpretiere den Code so:
Wenn der Server innerhalb von 3 Sekunden nichts geschickt hat, was einen Zeilenumbruch enthält, dann wirf eine SocketTimeoutException.

Und genau das ist passiert, oder?

lr


----------



## tuxedo (11. Dez 2007)

Was ist das denn für eine seltsame Catch-Throw-New Konstellation?

Die erste Exception, die SocketTimeoutException wird ausgelöst, wenn 3sek nach "vomServer.readLine()" keine Zeile gelesen wurde.

Diese Exception wird dann im Catch-Block abgefangen und dann gleich wieder als "Exception" geworfen, welche weiter unten nochmal abgefangen wird und dort dann den Server mit "error" füttert? Also ganz ehrlich? Stumpfsinniger gings nicht, oder?

Das Exception-Handling kann man gleich im inneren Catch-Block (SocketTimeoutException) abhandeln.

Aber um auf deine Frage zurück zu kommen:

>> könnte mir jemand erläutern, warum ich in der Zeile String line = vomServer.readLine(); eine java.net.SocketTimeoutException erzeugt wird, und wie ich das umgehen oder abändern könnte? 

Tja, du hast's doch selbst programmiert und kommentiert?


```
//Dieser Block soll mir den Fall abfangen falls keine Eingabe getätigt worden ist.
         socket.setSoTimeout(3000);
```

Wenn ein blockierendes Lesen länger als 3 Sekunden dauert, kommt die Exception. Und wenn die Exception kommt, dann heisst das, dass der Server gar nicht, oder nicht schnell genug antworten konnte/kann. 

- Alex


----------



## Gast (11. Dez 2007)

Danke für die Antwort.. Die try-catch Klausel ist auf den zweiten Blick gesehen tatsächlich etwas seltsam.

Aber trotzdem stehe ich etwas auf dem Schlauch was die Zeile String line = vomServer.readLine(); angeht. Es kommt vom Server eine Input mit einem leeren String.. Try-catch Block fängt ab, error geht raus. Beim nächsten Versuch kommt als Input ein nicht leerer String z.B. "XY", und ich kriege das nicht eingelesen um darauf zu reagieren. An welcher "Schraube" muss ich denn da jetzt drehen?


----------



## lhein (12. Dez 2007)

Dein Code wie er oben steht liest nur exakt 2 mal aus dem Stream. Beim ersten mal wandelt er das gelesene in einen int Wert um:


```
this.varaible = Integer.parseInt(vomServer.readLine());
```

beim zweiten Mal liest Du einen String:


```
String line = vomServer.readLine();
```

Danach ist der Thread definitiv beendet, sofern der oben gepostete Code vollständig ist.
Wenn Du das nicht willst, dann solltest Du Dich mal mit Schleifenprogrammierung auseinandersetzen.

lr


----------



## Guest (12. Dez 2007)

Ist schon ok das der Thread dann beendet wird und für den nächsten Input ein neuer Thread gestartet wird. Aber die Problematik ist, dass ich in die Variable line nichts eingelesen bekomme. Auch nicht, wenn ich z.B eine whileSchleife davor setze, z.B. so:

```
String line = "";

while (line != null){
         String line = vomServer.readLine();
         System.out.println("Test: " + line); 
}
```


----------



## tuxedo (12. Dez 2007)

Na dann wirds doch dran liegen dass der Server nix sendet, bzw keinen Zeilenumbruch mitschickt ...

- Alex


----------



## lhein (12. Dez 2007)

dann sendet der Server auch keinen Zeilenumbruch.

lr


----------



## Gast (12. Dez 2007)

Laut der Meldung des Clients kann das aber nicht sein. Nun gut, muss wohl eruiert werden.
Wie kann ich das einlesen, was ich vom Client bekomme.. Die Klasse BufferedReader bietet mir, so auf den ersten Blick, nur readLine() für Strings..


----------



## tuxedo (12. Dez 2007)

Wie jetzt? Wer soll wo einlesen? Bisher hast du nur einen Teil des Clients gepostet.


Lass doch den ganzen Krempel mit den Readern erstmal weg und arbeite nur mit dem "InputStream" und "OutputStream" den dir der Socket liefert. Damit kannst du byte[] und byte[] versenden. Wenn das nicht reicht, setze statt dem jweiligen Reader ein "DataInputStream", bzw "DataOutputStream" auf. Da kannst du dann Strings, Zahlenvariablen (int, double, ...) und ganze Objekte versenden und empfangen.

Wenn der Server (oder auch der Client, eben der der sendet) recht wenig Daten sendet, solltest du auch mal nach dem Senden ein .flush() machen, damit der Sendepuffer geleert wird und die Daten wirklich übers Netz gehen.


----------



## Gast (12. Dez 2007)

Ok, ich werde das mal umschreiben.. Aber noch eine Frage vorweg, wie kann ich dann empfangende Daten am besten überprüfen, ob überhaupt etwas gesendet wird und auch ob korrekterweise ein Zeilenumbruch gesendet wurde?

Hat da jemand ein Beispiel, oder gar ein Link der aufzeigt wie man am besten "filtert"..


----------



## tuxedo (12. Dez 2007)

Bevor du dich in etwas "unpraktikables" verrennst: 

Was soll das Ding hinterher können? Welche Informationen sollen übertragen werden? Wieviel (bytes?) und wieoft soll übertragen werden?

Darauf aufbauen kannst du dir dann ein Protokoll überlegen oder doch zu RMI greifen... 


- Alex


----------



## Gast (14. Dez 2007)

Das Ding stellt einen Server für ein Spiel dar. Sprich überträgt es ständig Daten in Form von:
(int)Spieler\n
(int)Spielfeldnummer\n
(int)Anzahl
etc.
Im Falle eines Fehlers, wie z.B. die oben beschrieben, das bis dato empfangene + Error-Meldung und zwei weiter "Strings" für Version und Spielname. Nur finde ich keine Ansätze für diese Vorhaben. Da der client nicht in meiner Hand liegt, fällt RMI raus.


----------



## lhein (14. Dez 2007)

Gast hat gesagt.:
			
		

> Das Ding stellt einen Server für ein Spiel dar. Sprich überträgt es ständig Daten in Form von:
> (int)Spieler\n
> (int)Spielfeldnummer\n
> (int)Anzahl
> ...



Hast Du das \n hinter (int)Anzahl absichtlich vergessen?

lr


----------



## Gast (14. Dez 2007)

nein, ein Konzentrationsfehler. Sorry. Es wird alles mit einem Zeilenumbruch abgeschlossen.

(int)Spieler\n
(int)Spielfeldnummer\n
(int)Anzahl\n


----------



## lhein (14. Dez 2007)

ok, hatte nur vermutet, daß dies der Logikfehler ist 

lr


----------



## Gast (15. Dez 2007)

Hätte denn jemand einen Link, oder eine Idee/Beispiel, wie ich so was sinnvoll umsetzen kann?


----------



## tuxedo (16. Dez 2007)

http://java.sun.com/javase/technologies/core/basic/rmi/index.jsp


----------



## Gast (16. Dez 2007)

Ok, aber wie geschrieben RMI soll nichts genutzt werden.. Mir geht es auch viel mehr erstmal darum ,wie ich am Besten auf falsche "Inputs" filtere...


----------



## tuxedo (17. Dez 2007)

Oh, übersehen, sorry.

Du sprichst dennoch in "Rätseln":

1) Im ersten Post scheints um einen Client zu gehen. In einem weiteren Post schreibst du, der Client läge nicht in deiner Hand ?!
2) Eigentlich ging es um ein TimeOut-Problem das aus einem nicht-gesendeten-aber-darauf-gewarteten-Zeilenumbruch-Problem resultiert. Jetzt willst du ein Protokoll gebastelt/erklärt bekommen?
3) woher sollen wir wissen was "falsche Inputs" sind? Wir kennen das Protokoll des Servers nicht.

Fakt ist:

Wenn deine Anwendung (sei es nun Client oder Server [entscheide dich mal...]) von einer anderen Anwendung jeweils einen String bekommt, dann solltest du eben genau wissen wie der String beim absenden aussieht und ob er mit einem Zeilenumbruch (und vor allem welchem [nur mit \n, mit \r\n oder  \n\r, ...]) gesendet wird. oder nicht.

Nur dann kannst du korrekt den String mit deiner Anwendung vom Stream abholen und auswerten. 

Also mach dir erstmal ein Bild WAS denn jetzt WIE übertragen wird. 

- Alex


----------



## Guest (17. Dez 2007)

Ok, du hast recht. Ich habe mich im Laufe des Threads ein wenig vom Original wegbewegt, um ein Beispiel zu schaffen. 

Ich stelle es mal dar:
Gegeben ist ein Server. Dieser Server lässt sich von einem Client ansprechen, um mit Ihm Spielzuege auszutauschen:
Wir nehmen an ein kompletter Input sieht wie folgt aus: (in Klammern vorangestellt der Datentyp)

```
(int)Spieler\n   //1 oder 2
(int)Spielfeldnummer\n //zwischen 0-9
(int)Anzahl\n //zwischen 1-20
```

Wenn der Server den Input verifiziert hat, und er ok ist, sieht die Antwort wie folgt aus:

```
(String)Erfolgreich\n
(String)Spielversion\n
(String)Spielzustand\n
```

Im Fehlerfall

```
(String)Error+(Welche Eingabe falsch war)\n
(String)Spielversion\n
(String)Spielzustand\n
```

Ich habe den Ansatz der im ersten Posting zu sehen ist, und scheitere daran unvollständige Eingaben (wie Zeilenumbrućh vergessen, nichts gesendet,usw) zu filtern und entsprechend dem Client zu melden..

```
public synchronized void run() {
      try {
         vomServer = new BufferedReader(new InputStreamReader(socket
               .getInputStream()));
         zumServer = new BufferedWriter(new OutputStreamWriter(socket
               .getOutputStream()));
         
                        //Dieser Block soll mir den Fall abfangen falls keine Eingabe getätigt worden ist.
         socket.setSoTimeout(3000);
         
          try {
            this.varaible = Integer.parseInt(vomServer.readLine());
         } catch (SocketTimeoutException e) {
            throw new Exception();
         }
         //Nun soll er weiter Strings vom Server auslesen
         String line = vomServer.readLine();
         System.out.println("Test: " + line);
     


      } catch (Exception exc) {
        try {
            exc.printStackTrace();
            zumServer.write("Error");
            socket.close();
         } catch (IOException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
         }
      }
}
```

Ich stecke nach wie vor am Timeout-Problem und erkenne definitiv, was der Client sendet. Ein nicht gesendeter String wird erkannt, dann kommt z.B nur eine Eingabe für die (int)Spielfeldnummer\n und der Rest fehlt. Da kam ich auf den dieses einzulesen, was nach wie vor nicht funktioniert, und es wird definitiv in diesem Fall ein 8\n gesendet.


----------



## tuxedo (17. Dez 2007)

??? 

>> Ein nicht gesendeter String wird erkannt

Geht's dir jetzt drum etwas zu bauen das Fehler findet? Wenn der Server vorgegeben ist, dann sollte man davon ausgehen dass das Protokoll stimmt. Und dein Client sollte sich nicht selbst kontrollieren müssen ob er auch ja brav alle Zeichen korrekt abschickt. 

Wo liegt das Problem 

2\n   //1 oder 2
4\n //zwischen 0-9
15\n //zwischen 1-20 

zu senden und danach 3 lächerliche Zeilen mit einem readLine() einzulesen?

Und wieso hängst du dich mit dem Timeout auf?

Mach doch einfach folgendes:

Der Thread der die Verbindung zum Server hält macht in der run-methode nichts außer in einer endlosschleife immer und immer wieder 100ms zu warten:


```
while(!interrupted()){
Thread.wait(100);
}
```

Daneben gibts folgende Methode:


```
public String[] sendeInput(String[] daten){
zumServer.write(String[0]+"\n");
zumServer.write(String[1]+"\n");
zumServer.write(String[2]+"\n");
String[] empfangen = new String[3];
empfangen[0] = vomServer.readLine();
empfangen[1] = vomServer.readLine();
empfangen[2] = vomServer.readLine();
return empfangen;
}
```

Dann kannst du deine 3 Strings einfach absenden und bekommst als Ergebnis darauf die 3 Strings die der Server zurückgemeldet hat. 

Die Auswertung ob die Serverrückmeldung okay war oder ob es einen Fehler gab kannst du ja anderswo machen, bzw anderswo drauf reagieren.

Entweder steh ich immer noch saumäßig auf'm Schlauch und Blick das Problem nicht, oder du siehst den Wald vor lauter Bäumen nicht mehr und solltest mal wieder an die frische Luft.

Gruß
Alex


----------



## Gast (17. Dez 2007)

Danke erstmal für die Mühen. Es geht mir wirklich erstmal darum den Server ans Laufen zu bringen, damit er mir vom Client gestellte extra falsche Anfragen (Extra-Option am Client) herausfiltert bis er eine korrekte Anfrage stellt.. Der Client stellt dabei, wen die Option Test gewählt wurde, eine Reihe von falschen Anfragen die mit richtiger "Exception-Antwort" erkannt werden müssen. Dieser Punkt bereitet mir aber Kopfzerbrechen..
Eine korrekte Kommunikation dürfte, hoffe ich weniger das Problem sein.

Nun ja, aber frische Luft ist nie schlecht vor allem wenn man sich in irgendetwas hinein steigert und wirklich den Wald vor lauter Bäumen nicht mehr sieht. Aber frische Luft muss vertagt werden, denn die Arbeit ruft.


----------



## tuxedo (18. Dez 2007)

Kerle kerle ...

Jetzt gehts also doch um den Server?!
Könntest du dich vielleicht mal entscheiden oder so ausdrücken dass es EINDEUTIG ersichtlich ist was du tun willst?

Ist es denn so schwer zu schreiben "Ich habe einen Server den ich mit einem Test-Client "provozieren" möchte um das Protokoll zu testen."???

Das ganze hat dann eigentlich nix mehr mit Netzwerk zu tun, sondern vielmehr mit "Wie erkenne ich einen vermeintlich falschen String und reagiere entsprechend darauf?".

Mal davon abgesehen dass ich von String-Klartext-Protokollen nicht viel halte: Warum sollte ein korrekt geschriebener Client falsche Anfragen senden? Willst du dich damit gegen "Client-Hacks" schützen? Warum machst du das Protokoll nicht einfach ein wenig komplizierter? Oder setzt eine kleine Verschlüsselung drauf? Oder benutzt doch RMI (wenn du ja offensichtlich in den Server eingreifen kannst).

- Alex


----------



## Gast (18. Dez 2007)

Also, das es um den Server geht kann man spätestens aus dem vorletzten Posting rauslesen. Das es um falsche Strings geht, versuche ich ab dem 1 Posting zu kommunizieren..;-)

Warum der Client falsche Anfragen sendet, weil es so vorgegeben ist und er den Server testen will...

So, nun wäre es schön wenn wir das als gegeben hinnehmen, und mir jemand Tipps geben könnte ,wie ich die in diesem Thread aufgekommenen Probleme lösen könnte.


----------



## tuxedo (18. Dez 2007)

Was du versuchst zu kommunizieren, und was dabei raus kommt, sind zwei paar Schuhe. Weder aus dem Threadtitel ist ersichtlich dass du eine Serverlogik testen musst, noch war die ganze Zeit davon die Rede. 

Zu deinem Problem: Na jetzt stell dich halt an. Werte die Antworten vom Server mit einer IF-Abfrage die (Sub-)Strings in der Bedingung vergleicht aus und wirf dann ggf. eine eigene Exception (Klasse die von Exception erbt). 

Zeilenweises empfangen und senden kannst du ja schon. Und die TimeOut-Sache haben wir auch soweit geklärt. Sogesehen wäre der Thread gemäß Titel "erledigt".

- Alex


----------



## Guest (18. Dez 2007)

Nein genau da sind wir wieder.. Bei dem Problem mit dem TimeOut sind wir gerade wieder..

So fange ich nach wie vor keine Input ab


```
socket.setSoTimeout(3000);
         
          try {
            this.varaible = Integer.parseInt(vomServer.readLine());
         } catch (SocketTimeoutException e) {
            throw new Exception();
         }
```

Und dann kommt dein Konstrukt mit der while-Schleife.. Wobei zuerst empfangen wird, und dann entsprechend gesendet wird.. Aber es bleibt beim java.net.SocketTimeoutException: Read timed out, wenn nur z.B. 9\n gesendet wird.

```
while(!interrupted()){
   String[] empfangen = new String[3];
  empfangen[0] = vomServer.readLine();
  empfangen[1] = vomServer.readLine();
  empfangen[2] = vomServer.readLine();
}
```


----------



## tuxedo (18. Dez 2007)

Okay, dröseln wir das ganze also nochmal auf:

1. Frage)
Brauchst du zwingend ein TimeOut? 

Das wirft dir eher alles durcheinander als dass es dir in der Situation hilft.

2. Frage)
Wie sendest du am Server?

Wenn du beim Server "9\n" sendest, dann solltest du noch ein flush() auf das Ausgabeobjekt (OutputStream, irgendein Writer, ...) machen, damit die Daten auch durch den Sendepuffer durchgeschoben werden. Der ist nämlich um ein vielfaches größer als die 2 Zeichen (9 und der Zeilenunbruch). Und erst wenn der Puffer voll ist, wird auch gesendet. Aber mit flush() kannst du das Senden auch vorher schon erzwingen.

-----

Wenn du also am Server sichergestellt hast dass er auch alles SOFORT absendet (flush() direkt nach dem senden von "9\n"), dann solltest du nochmal auf der Clientseite schauen ob da was ankommt und ggf. auf das Timeout verzichten. Timeout ist nur dann gut, wenn der Server in einer bestimmten Zeit antworten MUSS. Da es ja scheinbar um ein Spiel geht, könnte ich mir, aufgrund des doch recht simplen Protokolls vorstellen, dass da nicht im 100 Millisekundentakt Daten hi nund her gehen. Eher im Sekundentakt. Und wenn das Spiel dann vielleicht noch Rundenbasiert ist, oder die Übertragung wirklich von der Reaktion des Users abhängt, dann ist ein TimeOut wirklich nicht unbedingt der richtige Weg. 

Also nochmal kurz:

- Checke ob du am Server ein flush() machen kannst
- Nimm die TimeOut Zeile mal raus (auskommentieren)

Und dann meld dich nochmal.


----------



## Guest (18. Dez 2007)

alex0801 hat gesagt.:
			
		

> 1. Frage)
> Brauchst du zwingend ein TimeOut?



Ich meine schon. Die erste Anfrage des Client (Der Client der Fehler provozieren soll) ist nicht. Also er sendet nichts, und will darauf eine Error_Meldung bekommen, um die nächste Abfrage auf den Server zu lassen.
Deshalb die Idee mit dem TimeOut, wo ich keine Alternative für habe..



			
				alex0801 hat gesagt.:
			
		

> 2. Frage)
> Wie sendest du am Server?


Hmm, wie meinst du das.. Ich eröffne eine Session 

```
public void run() {
			try {
				
				
				
				while (bedingung == true) {
					
					Socket socket = serverSocket.accept();
					
					Thread protocol = new ClientHandler(socket);
					protocol.start();
			
				}
			} catch (Exception ex) {
				System.out.println("Verbindungsproblem");
				ex.printStackTrace();
			}
		}
```

Dann starte ich den Client (um Fehler zu provozieren), und er starten seine erste Anfrage, wie oben beschrieben zunächst nichts..
An den Server sende ich im Fehlerfall dann so:

```
try {
				zumServer.write("Error " + exc + "\n" + version + "\n" + zustand + "\n");
				toClient.flush();
				so.close();
			} catch (IOException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace()
```

Als ein flush() ist vorhanden...


----------



## tuxedo (19. Dez 2007)

Zu meiner zweiten Frage:

Ich wollte wissen wie die Code-Zeilen am Server aussehen die die Antwort senden. Hast du da einen flush() drin? Am Client brauchst du den natürlich auch.

Zur ersten Frage:

Wenn du am Client nix sendest, dann kommt vom Server auch keine Antwort. Die Exception die dann geworfen wird, weil du auf eine nicht-kommende-Antwort wartest, wird sozusagen auch nicht vom Server ausgelöst, weil der ja gar nicht weiß dass nix zu tun ist. Wenn, dann solltest du doch eher "\n", ohne weitere Info zum Server senden, und der Server liefert dann eine Fehlermeldung als Antwort, welche dann vom Client gelesen werden kann.

Aber nix zu senden und dennoch auf eine Antwort zu warten ist kein guter Test. Zumindest kein Test der irgend eine Logik testet.

Sinn macht das nur wenn wirklich alle X Sekunden eine Nachricht übers Netz gehen MUSS!

- Alex


----------



## Gast (19. Dez 2007)

Aklso die zweite Frage habe ich eigentlich beantwortet. Ich benutze ein flush() auf meinem Server.. 

Der Test, ob der Client etwas sendet, ist nun mal vorhanden und macht auch meines Erachtens Sinn. Ich warte am Server ob sich jemand verbindet. Tut es der Client uns sendet nichts, dann will ich die Verbindung abbrechen. Deswegen das TimeOut. Wie schon geschrieben der Client ist gegeben, und kann von mir nicht geändert werden..


----------



## tuxedo (19. Dez 2007)

Okay, das mit dem flush() war halt nicht ganz eindeutig. 

D.h. du kannst nur am Server schrauben? Okay. 

Wenn der Client nach dem Verbinden nix sendet und die Verbindung dann wieder getrennt werden soll, dann ist ein TimeOut ja schon okay. Aber doch nicht beim Client? 

Mach doch eins beim Server:

Der Server wartet dann auf eine Anfrage, bekommt aber keine, woraufhin die TimeOut Exception geworfen wird und der Server die Verbindung zum Client wieder trennt. 

Sag jetzt nicht das hast du schon im ersten Thread so gemacht... Das "vomServer" Objekt sieht nämlich nach deinem Testclient aus....

- Alex


----------



## Guest (19. Dez 2007)

Oh Shit, Schande über mein Haupt.. Jetzt verstehe warum die Kommunikation ein wenig durcheinander ist.. Natürlich müssen die BufferedReader Objekte korrekterweise vomClient und zumClient heissen. (darüber ahbe ich mir überhaupt keine Gednaken gemacht.. Also, muss ich dir sagen, dass ich das schon gemacht habe. 
  


```
public synchronized void run() {
      try {
         vomClient = new BufferedReader(new InputStreamReader(socket
               .getInputStream()));
         zumClient = new BufferedWriter(new OutputStreamWriter(socket
               .getOutputStream()));
         
                        //Dieser Block soll mir den Fall abfangen falls keine Eingabe getätigt worden ist.
         socket.setSoTimeout(3000);
         
          try {
            this.varaible = Integer.parseInt(vomClient.readLine());
         } catch (SocketTimeoutException e) {
            throw new Exception();
         }
         //Nun soll er weiter Strings vom Server auslesen
         String line = vomServer.readLine();
         System.out.println("Test: " + line);
     


      } catch (Exception exc) {
        try {
            exc.printStackTrace();
            zumClient.write("Error");
            socket.close();
         } catch (IOException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
         }
      }
}
```

Das TimeOut Problem bleibt leider aber davon unberührt und ist nach wie vor existent.. Ich könnte bald anfangen zu verzweifeln..


----------



## tuxedo (20. Dez 2007)

Naja, du hast noch nicht erwähnt ob nur das erste lesen vom Client mit einem TimeOut belegt sein soll. Sprich: MUSS der Client auch die zweite, dritte, vierte, ... Anfrage innerhalb einer bestimmten Zeit raus schicken, oder darf er sich da Zeit lassen (rundenbasiertes Spiel in dem der Spieler quasi entscheidet wann sein Spielzug fertig ist und übermittelt wird)?

Ich hab dein Code mal ein wenig "aufgeräumt" und die Exceptions ein wenig geschickter positioniert:


```
public synchronized void run() {
		
		
		// Streams/Reader/Writer holen und Timeout setzen
		try {
			
			vomClient = new BufferedReader(new InputStreamReader(socket
					.getInputStream()));
			zumClient = new BufferedWriter(new OutputStreamWriter(socket
					.getOutputStream()));

			socket.setSoTimeout(3000); // Timeout: 3000 Millisekunden == 3 Sekunden 
			
		} catch(IOException e){
			System.err.println("Es gab einen Fehler beim holen der Streams oder beim setzten des Timeouts. Siehe Stacktrace:");
			e.printStackTrace();
		}
		
		

		// Erster Leseversuch 
		try {
			
			this.variable = Integer.parseInt(vomClient.readLine());
			
			socket.setSoTimeout(0); // Timeout entfernen
			
		} catch (SocketTimeoutException e) {
			// Client hat nicht innerhalb der vorgegebenen Zeit eine Nachricht geschickt
			
			// Error zurückschicken
			try {
				zumClient.write("Error\n"); // Hier sollte ein Zeilenumbroch kommen, damit's der Client auch lesen kann
			} catch (IOException ioException){
				// Wenn das Error-Melden zum Client nicht funktioniert:
				// Egal, die Verbindung wird eh gekappt.
				System.err.println("Konnte die ERROR Meldung nicht zum Client schicken");
			}
			
			// Verbindung zum Client trennen
			try {		
				socket.close();
			} catch (IOException e1) {
				// Wenn das Error-Melden zum Client nicht funktioniert:
				// Egal, die Verbindung wird eh gekappt.
				System.err.println("Konnte die Socketverbindung zum Client nicht ordnungsgemäß schließen");
			} 
		} catch (NumberFormatException e) {

			System.err.println("Der Client hat keine Zahl gesendet, folglich gabb es einen Konvertierungsfehler. Siehe Stacktrace:");
			e.printStackTrace();
			
		} catch (IOException e) {
			
			System.err.println("Es ist ein Kommunikationsfehler beim versuch vom Client zu lesen aufgetreten. Siehe Stacktrace:");
			e.printStackTrace();
			
		}
		
		// Nun soll er weiter Strings vom Server auslesen
		try {
			
			String line = vomClient.readLine();
			System.out.println("Test: " + line);
			
		} catch (IOException e) {
			System.err.println("Das lesen weiterer Zeilen vom Client schlug fehl. Siehe Stacktrace:");
			e.printStackTrace();
		}
		

		
	}
```

Wie du sehen kannst, hab ich nach dem ersten erfolgreichen Leseversuch das Timeout wieder auf unendlich (0) gesetzt. Alle weiteren Leseversuche dürfen also länger als 3 Sekunden dauern.

Wenn der Client UNBEDINGT JEDESMAL INNERHALB 3 Sekunden eine neue Anfrage schicken MUSS, dann wird die Sache etwas komlizierter. Der obige Code verhindert jetzt quasi nur, dass ein, nach dem Verbindungsaufbau aufgehängter Client, oder einer der, getrennt wird und den Server nicht weiter "belastet". 

- Alex


----------



## Guest (20. Dez 2007)

Danke erstmal für die Mühen.. Nur komme ich nun nicht mehr über die erste Anfrage, wo der Client nichts sendet, hinaus..

Er springt direkt in Zeile 64, und kann natürlich nichts einlesen:

```
Das lesen weiterer Zeilen vom Client schlug fehl. Siehe Stacktrace:
java.net.SocketException: Socket closed
	at java.net.SocketInputStream.socketRead0(Native Method)
	at java.net.SocketInputStream.read(SocketInputStream.java:129)
	at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:264)
	at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:306)
	at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:158)
	at java.io.InputStreamReader.read(InputStreamReader.java:167)
	at java.io.BufferedReader.fill(BufferedReader.java:136)
	at java.io.BufferedReader.readLine(BufferedReader.java:299)
	at java.io.BufferedReader.readLine(BufferedReader.java:362)
	at network.ClientConnection.run(ClientConnection.java:136)
```


----------



## Gast (20. Dez 2007)

Wenn ich in meinem Konstrukt so.setSoTimeout(0); mit einbringe, bleibt er beim ersten Versuch wo er etwas einlesen müsste gnadenlos hängen...


----------



## tuxedo (21. Dez 2007)

> Danke erstmal für die Mühen.. Nur komme ich nun nicht mehr über die erste Anfrage, wo der Client nichts sendet, hinaus.. 

Das ist auch "logisch". Grund:

Wenn der Client nix sendet und das TimeOut eintritt, wird


```
socket.close();
```

ausgelöst und die Verbindung beendet. Alle weiteren Versuche schlagen dann natürlich fehl. "Serienreif" ist mein Beispiel natürlich nicht. Sowohl der Server als auch der Client müsste auf diese Aktion reagieren: Der Server müsste den CLientthread beenden weil er ja nicht mehr gebraucht wird (client hats mist gebaut oder ist gar kein richtiger client und wird disconnected) und der Client müsste einen neuen Versuch starten, indem er die Verbindung neu aufbaut und den nächsten Testfall, einer der diesmal was sendet, ausführt.

> Wenn ich in meinem Konstrukt so.setSoTimeout(0); mit einbringe, bleibt er beim ersten Versuch wo er etwas einlesen müsste gnadenlos hängen...

Auch das ist vollkommen logisch:

Der Client verbindet sich und sendet nix. Er ist "mucksmäuschen still". Der Server hängt in Zeile 25 (siehe mein Beispielcode) und wartet und wartet  und wartet und wartet. Bis er "schwarz" wird ;-) Er wird in alle ewigkeiten warten, eben weil der Client halt nix sendet.
Und du ja quasi vorgegeben hast, dass ein Client direkt nach dem Verbinden mit dem Server irgendwas von sich geben MUSS, macht ein TimeOut an dieser Stelle ja auch Sinn. 

Ich strick das ganze nochmal eben schnell um:


```
public synchronized void run() {
		
		
		// Streams/Reader/Writer holen und Timeout setzen
		try {
			
			vomClient = new BufferedReader(new InputStreamReader(socket
					.getInputStream()));
			zumClient = new BufferedWriter(new OutputStreamWriter(socket
					.getOutputStream()));

			socket.setSoTimeout(3000); // Timeout: 3000 Millisekunden == 3 Sekunden 
			
		} catch(IOException e){
			System.err.println("Es gab einen Fehler beim holen der Streams oder beim setzten des Timeouts. Siehe Stacktrace:");
			e.printStackTrace();
		}
		
		

		// Erster Leseversuch 
		try {
			
			this.variable = Integer.parseInt(vomClient.readLine());
			
			socket.setSoTimeout(0); // Timeout entfernen
			
		} catch (SocketTimeoutException e) {
			// Client hat nicht innerhalb der vorgegebenen Zeit eine Nachricht geschickt
			
			// Error zurückschicken
			try {
				zumClient.write("Error\n"); // Hier sollte ein Zeilenumbroch kommen, damit's der Client auch lesen kann
			} catch (IOException ioException){
				// Wenn das Error-Melden zum Client nicht funktioniert:
				// Egal, die Verbindung wird eh gekappt.
				System.err.println("Konnte die ERROR Meldung nicht zum Client schicken");
			}
			
			// Verbindung zum Client trennen
			try {		
				socket.close();
			} catch (IOException e1) {
				// Wenn das Error-Melden zum Client nicht funktioniert:
				// Egal, die Verbindung wird eh gekappt.
				System.err.println("Konnte die Socketverbindung zum Client nicht ordnungsgemäß schließen");
			} 
		} catch (NumberFormatException e) {

			System.err.println("Der Client hat keine Zahl gesendet, folglich gabb es einen Konvertierungsfehler. Siehe Stacktrace:");
			e.printStackTrace();
			
		} catch (IOException e) {
			
			System.err.println("Es ist ein Kommunikationsfehler beim versuch vom Client zu lesen aufgetreten. Siehe Stacktrace:");
			e.printStackTrace();
			
		}
		
		// Nun soll er weiter Strings vom Server auslesen,
		// aber nur wenn es vorher mit dem lesen mal geklappt hat, 
		// sprich der Socket NICHT geschlossen ist
		if (!socket.isClosed()){
			try {
				
				String line = vomClient.readLine();
				System.out.println("Test: " + line);
				
			} catch (IOException e) {
				System.err.println("Das lesen weiterer Zeilen vom Client schlug fehl. Siehe Stacktrace:");
				e.printStackTrace();
			}
		} else {
			System.err.println("Der Client hat beim ersten Lese-Versuch nix gesendet. " +
					"Die Verbindung wurde unterbrochen, der Clientthread wird nun beendet");
		}
		

		
	}
```

Wichitg ist jetzt der untere Teil, da wo weitere Strings gelesen werden.


----------



## Guest (22. Dez 2007)

Hi,

auch dieser Testversuch scheitert an der ersten Stelle bei der der Client nichts sendet. Diese Anfrage wird an dieser Stelle erst abgefangen:

```
} else {
         System.err.println("Der Client hat beim ersten Lese-Versuch nix gesendet. " +
               "Die Verbindung wurde unterbrochen, der Clientthread wird nun beendet");
      }
```


----------



## Gast (22. Dez 2007)

Ok, Korrektur.. Ein flush() hat geholfen, und der 1. Tesfall konnte behandelt werden..

Wären wir wieder an der Stelle an der der Client etwas sendet und der Server einlesen muss.. Hier kommt der Server nicht weiter und wartet, wartet...


----------



## assoziatives pseudonym (22. Dez 2007)

Kinders ... SocketTimeouts & co sind unnötig. Fang einfach eine Connection Reset Exception ab, und schon haste deinen KeepAlive. Ich selbst hab mich da auch schon verfangen, stellte am Ende aber fest dass alles völlig unnötig war und sowieso schon von der VM erledigt wird, man muss nur die Exceptions richtig abfangen, dann klappt auch mit dem Nachbarn


----------



## Gast (23. Dez 2007)

Wenn du mir das vielleicht etwas näher erörtern würdest? Vielleicht ein Beispiel... Wäre super..


----------



## assoziatives pseudonym (23. Dez 2007)

äh ....

```
try {
blablablabla ganz viel Quelltext
} catch (ConnectionResetException e) {System.out.println("Client ist wech!");}
```
???

Also wenn du nichtmal weisst, was eine Exception ist und wie man sie abfängt, dann würde ich dir empfehlen nochmal gaaaaanz von vorne anzufangen, alles andere muss ja im Chaos enden.

Das hier mal komplett lesen und zurückkommen, aber dann bitte angemeldet


----------



## Gast (23. Dez 2007)

Ok, ich dachte jetzt viel mehr das wäre ein Beitrag bezüglich des readLine()- Problemes. Das ist ja das eigentliche Problem. 
Ob ich das durch Einsatz einer ConnectionResetException behoben bekomme glaube ich weniger. Aber auch das werde ich mal testweise einbauen.


----------



## assoziatives pseudonym (23. Dez 2007)

auch das Problem hab ich bereits gelöst, das Problem ist die fehlerhafte und ineffiziente Implementierung von readLine.

Am besten wird es sein, wenn du (so wie ich) dir dein eigenes Pseudo-Protokoll baust, und mit socket.getInputStream().read() arbeitest. Lass den BufferedReader-Blödsinn weg, der is nur für Konsoleneingaben etc. gut.


----------



## Gast (23. Dez 2007)

Na gut, wenn ich jetzt die Klasse DataInputStream verwenden würde, könnte ich mit einem getInputStream.read() nur Integer einlesen und keine Strings mehr, was das ganze für mich gerade nicht einfacher macht. 
Ein readline() vom Typ DataInputStream bringt mir an der Zeile String line = vomClient.readLine() das selbe Ergebnis, nämlich nichts.


----------



## assoziatives pseudonym (23. Dez 2007)

Gast hat gesagt.:
			
		

> Na gut, wenn ich jetzt die Klasse DataInputStream verwenden würde, könnte ich mit einem getInputStream.read() nur Integer einlesen und keine Strings mehr, was das ganze für mich gerade nicht einfacher macht.


:lol: :lol: weisst du eigentlich, was du da redest?
Über ein Netzwerk werden _immer_ Zahlen gesendet (genauer: Bytes, keine Integer!), Text ist garnicht möglich! readLine interpretiert eben eingehende Bytes als Text, und zwar durch Gleichsetzung der Bytes mit dem ASCII-Äquivalent. Ergo muss man mit read() sich sein Übersetzungsprotokoll selbst bauen!
zum Einlesen gibts da meintext.getBytes(), umgekehrt fällt es mir grad nicht ein.


			
				Gast hat gesagt.:
			
		

> Ein readline() vom Typ DataInputStream bringt mir an der Zeile String line = vomClient.readLine() das selbe Ergebnis, nämlich nichts.


Jo, ganz ohne eigenes Protokoll is das natürlich sinnlos ... nochmal:


> Am besten wird es sein, wenn du (so wie ich) dir *dein eigenes Pseudo-Protokoll baust,* und mit socket.getInputStream().read() arbeitest


----------



## Gast (23. Dez 2007)

Was hat das ein mit dem anderen zu tun?? Ich habe nur klar gestellt, dass diese Vorgehensweise es nicht gerade einfacher macht. Ein Übersetzungsprotokoll ist ja schön und gut, und war auch schon im Gespräch, aber ein Link oder Beispiel wäre mir ganz hilfreich, da reinzukommen. Wenn du mir da weiterhelfen könntest, würde es mir ja schon reichen..

Und es werden über ein Netzwerk keine Zahlen versendet, sondern digitale Signale, genauer binäre Signale, die letztendlich nur zwei Werte annehmen können.. (Um auch mal etwas unnötig daher zu reden.. ;-) )


----------



## Gast (23. Dez 2007)

Aber auch ein int example = vomClient.read() endet genauso, wie mit dem alten Code... Oder gibt es beim Einlesen etwas mehr zu beachten?


----------



## assoziatives pseudonym (23. Dez 2007)

Gast hat gesagt.:
			
		

> Und es werden über ein Netzwerk keine Zahlen versendet,


11001010 ist also keine Zahl für dich? Sehr interessant ... Sag das mal bitte zu deinem Mathe-Lehrer


			
				Gast hat gesagt.:
			
		

> sondern digitale Signale,


Nö ... tatsächlich sind die allermeissten Internet-Anschlüsse analog --> ein Modem wandelt digitale Information in analoge um, speziell bei DSL werden die Transportrichtungen unterschieden, der Modulator/Demodulator teilt selbige in 2 versch. Frequenzbereiche auf


			
				Gast hat gesagt.:
			
		

> genauer binäre Signale,


Es gibt keine "Signale", es gibt nur Zustände. Man benutzt in der etwas tiefergehenden Informationstechnik Wahrheitstabellen und Zustandstabellen. Ein "Signal" wäre ein fest definiertes Paket aus Zuständen, also *könnte* man sagen dass das eine Steigerung wäre


			
				Gast hat gesagt.:
			
		

> die letztendlich nur zwei Werte annehmen können..


sicher? Bei dir ist also der mögliche physikalische Spannungsbereich begrenzt? Wieder sehr interessant ... Man kann unendlich viele Zustände definieren, weil es auch unendlich viele Spannungsbereiche in physikalischen Leitern gibt, allerdings hat man sich auf 2 einzelne Bereiche zur Übertragung von Informationen geeinigt


			
				Gast hat gesagt.:
			
		

> (Um auch mal etwas unnötig daher zu reden.. ;-) )


Soso, die Wissenschaft ist also unnötig ...  ???:L

Es wird dir übrigens niemand komplette Programme vorkauen, dies Forum soll als Hilfestellung dienen, und nicht als "wie kopiere-ich-am-besten-von-anderen"-Sammelplatz. Wer ein bischen (!) programmieren kann, implementiert sich das vorhin genannte ganz schnell selbst (ich habe dafür ca. 2 Stunden benötigt, allerdings auch nur weil ich noch Verschlüsselung mit eingebaut habe)



			
				Gast hat gesagt.:
			
		

> Aber auch ein int example = vomClient.read() endet genauso, wie mit dem alten Code... Oder gibt es beim Einlesen etwas mehr zu beachten?


Jetzt wird es mir zu lächerlich ... du liest keineswegs, was ich schreibe .... du willst nur alles fertig vorgekaut haben

So ... könnten wir jetzt bitte den Klugschiss & Fantasie-Modus verlassen und zurück zu ernsthaften Fragen kommen?


----------



## Gast (23. Dez 2007)

Meine Aussage bezogen auf das Netzwerk war auch nur als "Fingerzeig" gemeint. Aber du scheinst mit der Thematik rudimentär vertraut zu sein, so mit müssen wir das nicht mehr auf relativ niedrigem Niveau diskutieren. Obwohl deine Aussagen zur Haarspalterei einladen.. ;-) Es ist ja auch gar nicht Thema.

Es geht auch nicht darum komplette Programme vorzukauen, sondern mir in dem Teilbereich eines bereits relativ komplexen Programms weiterzuhelfen. Und es hilft mir definitiv nicht von Dir zu hören, wie schnell, toll oder sonst was du bist. Es geht mir nur um Beispiel, die sonst woher sein können, zu Rate zu ziehen, um ich der Thematik einzudenken. Und entweder hast du was im Lesezeichen oder sonst wo, oder halt nicht.
Aber das mit dem meinText.getBytes() habe ich tatsächlich überlesen. Danke nochmal für den freundlichen Hinweis.. ;-)


----------



## assoziatives pseudonym (23. Dez 2007)

Gast hat gesagt.:
			
		

> Und es hilft mir definitiv nicht von Dir zu hören, wie schnell, toll oder sonst was du bist.


Wo steht das? Habe ich ein Schattendouble, welches kurz vor dem absenden des Formulars nochmal Text hinzufügt?


----------



## Gast (23. Dez 2007)

Es kommt im Ansatz so rüber in den Posts... Aber wie auch immer, wenn es nicht so ist, dann ist es halt nicht so..

Aber jetzt mal eine Frage bezüglich des getBytes().. Wie komme ich an den String ran, von dem ich einlesen soll?


----------



## assoziatives pseudonym (23. Dez 2007)

... die Frage ist jetzt nicht ernst gemeint, ne?

Naja, ich hab keine Lust mehr, mich verarschen zu lassen, tschö


----------



## Gast (23. Dez 2007)

So, Troll ist weg.. 

Wie sieht es denn jetzt aus? Könnte mir das jemand erläutern...
Die Frage bezüglich getBytes war schon irgendwie ernst gemeint. Schließlich kann ich das nur auf ein string anwenden. Zur Zeit sehe ich nicht viele Möglichkeiten etwas einzulesen, Stringtechnisch, außer mit readline()...
Aber auch die readLine() Geschichte will mir nicht in den Kopf warum er nichts einließt, obwohl etwas vorhanden


----------



## tuxedo (23. Dez 2007)

Herrgott... Hast du schonmal einen Blick in die Api-Doku geworfen?

Viele Wege führen nach Rom. Zum einen kann man einen String nach seiner byte[] Repräsentation fragen, zum anderen kann man mit DataInputStream sowie DataOutputStream  sehr wohl mit Strings hantieren. Ich kau dir aber nicht die ApiDoc vor. Schau halt selbst mal rein. Dann lernst du auch den Umgang damit.

- Alex


----------



## Gast (24. Dez 2007)

Natürlich habe ich schon was weiß ich ausprobiert um etwas eingelesen zu bekommen. Ich sitze doch nicht hier und warte auf irgendein Posting.. Ich müsste mittlerweile jede Methode der Klassen BufferedReader, DataInputStream etc durch haben, kriege aber nichts eingelesen.


----------

