# TCP Server/Client



## Fohnbit (14. Mrz 2012)

Hallo Gemeinde

Ihr würdet mir sehr helfen, wenn ihr mir einen Link oder einen Code hier posten könntet, welcher eine TCP Server/Client Kommunikation erstellt.
Ich habe zwar einen am Laufen aber das klappt nicht richtig. Daher ein Neuanfang.
Meine private Anforderung wäre:
Es gibt ein IP Geräte, welch eine TCP Verbindung bereit stellt. Sagen wir Telnet.

Nun möchte ich aus Java mit dem Gerät per TCP verbinden, und die Verbindung aufrecht halten.
Bei Abbruch der Verbindung (Time-Out ca. 30 sek) soll versucht werden neu zu verbinden.

Ich muss vom dem Gerät Daten empfangen aber auch senden können.

Hat hier jemand ein schönes Beispiel um den Start oder vielleicht das Ziel erreichen zu erfüllen?

Dank euch!


----------



## Marcinek (14. Mrz 2012)

Google: Simple TCP Client Server java

Google: Simple TCP Chat java

Google: Simple TCP Example java

Google: How to: TCP Connection java


----------



## Fohnbit (14. Mrz 2012)

Hallo

Danke, die Links hatte ich auch schon gefunden, jedoch brachten die mich nicht an mein Ziel.
Mein Problem ist vor allem das sowohl senden als auch Empfangen über die selbe aufgebaute Verbindung erfolgen, gehalten und im Falle eines Abbruches neu aufgebaut werden soll.

Für Hilfe wäre ich also sehr dankbar!


----------



## Marcinek (14. Mrz 2012)

:bahnhof: 

Ja, dann zeig mal deinen Code, weil jede Socketverbindung bidirektionalen Datenaustausch erlaubt, weiß ich nicht gerade, wo das Problem liegen soll.

Hast du eventuell eine konkrete Frage zu einem Beispiel?


----------



## Fohnbit (15. Mrz 2012)

Hallo

Gerne, dann bauen wir weiter wo ich aufgehört habe:

Die Client/Server Klasse:


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

public class Listener extends Thread

{    
	
    public Listener(TCPServerClient SC) {
        this.SC = SC;
       }
	private TCPServerClient SC;

	String answer;
	
		public void run() {
			
		try {
			SC.outToServer.writeBytes("listen 1\n");
			answer = SC.inFromServer.readLine();
			SC.outToServer.writeBytes("00:04:20:07:3a:b7 status\n");
			 answer = SC.inFromServer.readLine();
	    	  SC.setAnswer(answer);
			
			 while(SC.clientSocket.isConnected()){
		    	  answer = SC.inFromServer.readLine();
		    	  SC.setAnswer(answer);
			 }
			 
			 SC.inFromServer.close();
			 SC.setAnswer("Thread beendet");
				
		} catch (UnknownHostException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
}
```

Im Hauptprogramm wird wie folgt aufgerufen:

```
public class TCPServerClient {

	public Socket clientSocket;
	public DataOutputStream outToServer;
	public BufferedReader inFromServer;
	private Thread listen;

	public synchronized void setAnswer(String answer) throws UnsupportedEncodingException {
		
		if(answer.compareTo("Thread beendet")==0){
			reconnect();
			return;
... und so weiter
		}
```

Verbindung beenden:

```
private void disconnect(){
		 try {
			 timer.cancel();
			 clientSocket.close();
			 listen = null;	
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
```

Verbindung herstellen:

```
private void connect(){
		timer.cancel();
 	try {
    		String IP = get("serverip");
    		int Port = getInt("port",9090);
    		clientSocket = new Socket(IP,Port );
	    	outToServer = new DataOutputStream(clientSocket.getOutputStream());
			inFromServer = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
		} catch (UnknownHostException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			reconnect();
			return;
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			reconnect();
			return;
		}
	if(clientSocket.isConnected()){
		if(listen == null){
			listen = new Listener(this);
			listen.start();				
		} else {
			reconnect();
		}
			
	}

}
	private void reconnect(){
		
		if(get("autostart").compareTo("Automatic")==0){
			try {
				timer = new Timer();
				timer.schedule(new TimerTask() {
			        public void run() {
			              	connect(); 
			              }
			    }, delay*1000);
			} catch(Exception e){
				
			}
				
			
		}
			
	
	}
```

Befehle senden:

```
public void sendCommand(String data) {
    try {
       	  outToServer.writeBytes(data);
              }
    catch(Exception e) {
       ;
    }
 }
```


----------



## Fohnbit (15. Mrz 2012)

Mein Problem ist nun, dass mein Code es nicht bemerkt, wenn der Ziel TCP Server weg ist.
Er bemerkt also den Verbindungsabbruch nicht!

Sofern ich das eruiert habe, hängt er beim readLine:

```
while(SC.clientSocket.isConnected()){
		    	  answer = SC.inFromServer.readLine();
		    	  SC.setAnswer(answer);
			 }
```

Wie der Code also arbeiten soll:
Er soll eine Verbindung aufbauen, diese halten und bei einem Abbruch einen Reconnect versuchen.
Er soll Daten an den TCP Server senden und beim Empfang die ".setAnswer" im Hauptprogramm starten.

Ich bin mir auch nicht sicher, ob der Verbindungsaufbau und ggf. reconnect wirklich gut programmiert ist :autsch:

Wäre toll wenn sich jemand an der Optimierung beteiligen könnte!

Danke!


----------



## Fohnbit (16. Mrz 2012)

Habe ich fast vergessen.

Das .readLine() macht mir auch noch andere Probleme Denn wenn der String nicht mit einem Carriage Return abgeschlossen ist, wartet ReadLine().
Ich bräuchte einen TimeOut in Millisekunden ... also wenn 200 Millisekunden lang keine Daten kommen, dann soll ausgegeben werden.

Danke!


----------



## tuxedo (16. Mrz 2012)

Zum Thema "Erkennen dass die Verbindung tot ist":

Das einzig zuverlässige ist, die Verbindung regelmäßig zu benutzen um zu sehen ob noch kommuniziert werden kann oder nicht. Selbst mit eingschaltetem "TCP KeepAlive" kann es lange (bis zu Stunden??) dauern bis eine unterbrochene Verbinudng als unterbrochen erkannt wird. Ein paar weitere Details dazu: socket : Java Glossary

Wenn du eine unterbrochene Verbindung binnen sekunden (oder darunter) erkennen können willst, musst du das also auf Protokollebene selbst implementieren.


----------



## Fohnbit (16. Mrz 2012)

Hallo tuxedo

Danke für die Info.
Protokollebene: Hört sich kompliziert an. Aber merkwürdig das sonst keiner braucht.

Was wäre wenn ein eigener Thread jede 5 Sekunden prüft ob die Verbindung noch steht?

TCP ist ja ein verbindungs orientiertes Protokoll. Dachte immer das ein Abbruch durch das Übertragngsprotokoll selbst erkannt wird.

Ein Codebeispiel hast du nicht, oder?

Danke!


----------



## Fohnbit (17. Mrz 2012)

Hallo

ich habe nun etwas getestet.
Wenn ich auf der Server Seite die Connection schließe, erhalte ich beim debugen eine Meldung.
Leider kann ich mit dieser nichts anfangen.

Weiß jemand ob ich die Meldung abfangen kann? Denn dann habe ich den Verbindungsabbruch den ich suche:


----------



## Marcinek (17. Mrz 2012)

Es wird eine IOException geworfen, wenn die Verbindung abbricht.

Gruß


----------



## Fohnbit (17. Mrz 2012)

Hallo

Das wäre ja genau das was ich bräuchte, um einen Abbruch zu erkennen. Aber dann habe ich den Try catch Block falsch, oder?:

```
public void run()  {
		try {
			while(SC.clientSocket.isConnected()){
		    	  BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(SC.clientSocket.getInputStream()));
		    	      
		    	  char[] buffer = new char[200];
		    	  int anzahlZeichen = bufferedReader.read(buffer, 0, 200);
		    	  tmpNachricht = new String(buffer, 0, anzahlZeichen);
		    	     		    	      
		    	      if(tmpNachricht != null | tmpNachricht.length() > 0){
		    	    	   Nachricht = tmpNachricht + Nachricht; 
		    	    	   if(timer != null){
		    	    		   timer.cancel();
		    	    	   }
		    	    	   
		    	    	timer = new Timer();
		   				timer.schedule(new TimerTask() {
		   			        public void run() {
		   			            // Task here ...
		   			     	try {
								SC.setAnswer(Nachricht);
								Nachricht = ""; 
							} catch (UnsupportedEncodingException e) {
								// TODO Auto-generated catch block
								e.printStackTrace();
							}
							              }
		   			    }, delay);
		    	      }   
		    	    	    	    
			 }		 
			 SC.inFromServer.close();
			 SC.setAnswer("Thread beendet");
				
			 
			 
		} catch (UnknownHostException e) {
			// TODO Auto-generated catch block
			// e.printStackTrace();
			 try {
				SC.setAnswer("Thread beendet");
			} catch (UnsupportedEncodingException e1) {
				// TODO Auto-generated catch block
				// e1.printStackTrace();
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			// e.printStackTrace();
			 try {
				SC.setAnswer("Thread beendet");
			} catch (UnsupportedEncodingException e1) {
				// TODO Auto-generated catch block
				// e1.printStackTrace();
			}
		}
	}
```

Oder wie sollte man den Fehler abfangen?

Danke!


----------



## Marcinek (17. Mrz 2012)

Ja sollte korrekt sein.

Lass mal das e.printStacktrace stehen und setzte da ein Brechpunkt rein, dann siehst du, was passiert.


----------



## Fohnbit (17. Mrz 2012)

Hallo

Habe alle .printStackTrace stehen gelassen und bei allen einen Breakpoint eingefügt.

Ergebnis das gleiche. Bekomme den Fehler im Editor und kein Breakpoint greift.


----------



## Marcinek (17. Mrz 2012)

Er möchte in String etwas debuggen,w eil dort eine Exception auftritt frage ist warum, das kann man nicht sehen


----------

