# Server/Client Daten empfangen, wenn Daten gesendet werden



## pyro2k8 (7. Jun 2010)

Hallo,
ich brauche eine Server, der bei Bedarf Daten annimmt. Es wird ein Server gestartet und ein Client verbindet sich - das klappt auch alles soweit. jetzt sendet der Client aber nicht sofort Daten, sondern erst wenn er verbunden ist sozusagen bei Bedarf.
Später soll ein KeyEvent übertragen werden, wenn es dann ausgelöst wird - dieses Stück programmcode ist also nur ein test.
Ich habe 2 mal Eclipse laufen und starte dann die jeweiligen methoden: also für den server n.startServer(); und für den client n.openConnection("192.168.0.104"); und anschließend n.sendMoveCommand(2); (2 ist natürlich nur ein Test Integer)

Der Server versucht, wie im Code zu sehen, nachdem er gemerkt hat das ein Client verbunden ist direkt daten von diesem zu empfangen, es werden aber keine gesendet. deswegen gibts auch direkt nen connection reset exception.

Wie macht man sowas ? Die Beispiele die ich gesehen habe, senden direkt nach dem verbinden mit dem Server Daten und der Server empfängt sie. das klappt für mein Beispiel nicht! der Code:


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


public class Network_SendReceive {
	
	PrintWriter aus = null; // wird vom Client genutzt
    
    Socket client = null; //wird von Server/Client benutzt
    InputStream ein; // wird vom Server benutzt
    
	public void openConnection(String ip) throws UnknownHostException, Exception {        

        try { 
            client = new Socket(ip, 10666);
        }        
        catch (UnknownHostException e) {
            System.out.println("Unbekannter Server!");  
            System.exit(0);
        } 
        catch (Exception e) {
            System.out.println(
                    "Verbindung zum Netz existiert nicht \n"                            
                            + e.toString()); 
            System.exit(0);
        }
	}
	
	public void sendMoveCommand(int richtung) throws Exception {
		try {
            
            aus = new PrintWriter(client.getOutputStream(), true);          
            
            aus.print(richtung);           
        } 
		catch (Exception e) {
            System.out.println(e.toString()); 
        }		
	}
	
	public void closeConnection() throws IOException {
		
		try {
			aus.close();	        
	        client.close();
		}
		catch(IOException e) {
			e.getStackTrace();
		}		
	}
	
	public void startServer() {	
		
	    ServerSocket server = null;
	    int richtung = 0;	   

	        try { 
	        	
	        	server = new ServerSocket(10666);        	
	        	System.out.println("Warte auf Verbindungsanforderung");
	        	client = server.accept(); // auf Verbindung warten!
	        	ein = client.getInputStream();
	        	
	        	System.out.println("Verbunden "+client.isConnected());
	        	
	        	while(client.isConnected()) {        		
	        		
	        		richtung = ein.read();
	        		
	        		System.out.println("empfangen "+richtung);        		        		
	        	}
	        } 
	        catch (Exception e) {
	            System.out.println("Fehler beim Ã–ffnen des Ports!");
	            System.out.println("Fehler beim Verbindungsaufbau!");
	            e.printStackTrace();
	            System.exit(0);
	        }
	  }
	
	public static void main(String[] args) throws Exception {
		
		Network_SendReceive n = new Network_SendReceive();	
		
		n.startServer();
		
		//n.openConnection("192.168.0.104");
		//n.sendMoveCommand(2);
		
		//n.closeConnection();
		
	}
}
```


Ich hoffe ihr könnt mir helfen!

Viele Grüße, Tim


----------



## ice-breaker (8. Jun 2010)

Dein Code funktioniert doch, ich weiß nicht was dein Problem ist.

Schau dir mal an was Socket.isConnected() zurückgibt, nicht ob man noch verbunden ist, sondern ob man jemals korrekt verbunden wurde.


----------



## pyro2k8 (8. Jun 2010)

Hallo!
Danke für die Antwort!
Der Code hat so wie er da steht nicht funktioniert. Als ich aber den Printwriter durch einen Outputwriter ersetzt habe hat es wunderbar funktioniert...

Jetzt stehe ich aber vor einem neuen Problem:
Und zwar sollen Geometrische Objekte von einem anderen Rechner aus verschoben werden können und zwar mit Tasten-deswgen diese Netzwerkgeschichte. Das heißt wenn eine z.b. die Linkstaste auf dem einem Programm gedrückt werden sollen sich die Objekte auf dme anderen Programm bewegen. 
Und da ist auch schon das Problem: Es werden ja permanent Daten gesendet, auch wenn der User keine Taste drückt und - ebenfalls permanent Daten empfangen, auch wenn keine gesendet werden. In Verbindung mit meiner Gui kann ich dann nix mehr machen und alles steht still 
Wie ist das zu lösen ? Ich habe schon an Threads gedacht, aber Threads über Netzwerk ?!?! oO, ich komme so schon eher weniger mit Threads klar um ehrlich zu sein.

Ich hoffe ihr könnt mir helfen.
Hier mein Code bis jetzt:

ServerThread:

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

public class Network_ServerThread implements Runnable {
	    
	    Socket client; //wird von Server/Client benutzt
	    InputStream ein; // wird vom Server benutzt
	    ServerSocket server;
	    
	    boolean active;
	    boolean activeclient;
	    int richtung;
	    
	    public Network_ServerThread() {
	    	client = null;
	    	ein = null;
	    	server = null;
	    	
	    	richtung = -1;
	    	active = false;
	    	activeclient = false;
	    }		
		
	    public int getRichtung() {
	    	return richtung;
	    }
	    public boolean getActiveclient() {
	    	return activeclient;
	    }
	    
		public void receiveData() throws IOException{		
			
			try {				
				ein = client.getInputStream();				
				richtung = ein.read();
				
				
			}
			catch(Exception e) {				
				e.printStackTrace();
				
			}
			
		}
		
		public void closeConnection() {
			
			try {				
				if(ein != null) {
					ein.close();
				}
				else if(client != null) {
					client.close();
				}	        
			}
			catch(Exception e) {
				e.getCause();
			}		
		}
		
		public void startServer() throws Exception {     	       

		    try { 
		        	
		        server = new ServerSocket(10701);
		        System.out.println("warten");
		        client = server.accept(); // auf Verbindung warten!
		        System.out.println("verbindung");
		        activeclient = true;
		        	
		        System.out.println("Verbunden");       		        	
		    } 
		    catch (Exception e) {
		        e.getCause();	            
		    }	        
		}

		@Override
		public void run() {
			active = true;
			System.out.println(active);
			
			try {
				while(true) {
					
					
					receiveData();
					
					
					
				}
			}
			catch(Exception e) {
				System.out.println("aus");
				e.getStackTrace();
			}
			finally {
				System.out.println("aus");
				closeConnection();
			}					
		}
		
		public void anhalten() {
			active = false;
			//System.out.println(active);
		}
	}
```

ClientThread

```
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;


public class Network_ClientThread implements Runnable {
	
	OutputStream aus; // wird vom Client genutzt    
    Socket client; //wird von Server/Client benutzt    
    
    String ip;
    int richtung;
    
    boolean active;  
    
    public Network_ClientThread() {
    	aus = null;
    	client = null;    	
    	
    	richtung = -1;
    	ip = null;
    	
    	active = false;
    }
    
    public void setRichtung(int newRichtung) {
    	richtung = newRichtung;
    }
    
    public void setIp(String newIp) {
    	ip = newIp;
    }
    
    public int getRichtung() {
    	return richtung;
    }
    
	public void openConnection(String newIp) throws UnknownHostException, Exception {
		ip = newIp;
		
        client = new Socket(ip, 10669);       
	}
	
	public void sendMoveCommand() {
		try {            
            aus = client.getOutputStream();           
            aus.write(richtung);    
        } 
		catch(Exception e) {
			;
		}
				
	}
	
	public void closeConnection() {
		
		try {
			if(aus != null) {
				aus.close();
			}			
			else if(client != null) {
				client.close();
			}	        
		}
		catch(Exception e) {
			;
		}		
	}

	@Override
	public void run() {
		
		active = true;	
		try {
			while(active) {
				sendMoveCommand();
				richtung = -1;
			}
		}
		catch(Exception e) {
			e.getStackTrace();
		}
		finally {
			closeConnection();
		}
		
		System.out.println(active);
	}
	
	public void anhalten() {
		active = false;
		System.out.println(active);
	}
}
```

Wenn ich jetzt die getRichtung() Methode vom Server im Loop ausführe, um die gesendeten Daten ständig zu erhalten funktioniert das zwar (in der Konsole sehe ich alles richtig), aber ich kann nix mehr machen.

Gruß und danke im Voraus!


----------



## Michael... (8. Jun 2010)

pyro2k8 hat gesagt.:


> Wie ist das zu lösen ? Ich habe schon an Threads gedacht, aber Threads über Netzwerk ?!?! oO, ich komme so schon eher weniger mit Threads klar um ehrlich zu sein.


Um Threads kommst Du da nicht rum (ist auch unabhängig vom Netzwerk ?!?!). Im Client muss das Senden und Empfangen in seperaten Threads passieren, sonst blockiert er ja. Im Server muss für jeden Client ein Thread laufen, der auf deren Input wartet.

==> Aufgabe fürs Wochenende: Kapitel Threads lesen ;-)


----------



## pyro2k8 (8. Jun 2010)

Es gibt nur einen Clienten. 

Dieser soll doch eigentlich nur senden, welcher Key gerade gedrückt wurde, also KeyEvent.UP und so weiter. Der Server soll diese Daten empfangen und diese dann verarbeiten, sodass sich das jeweilige gezeichnete element bewegt.
Also muss der Client doch nur senden und der Server nur empfangen, oder ?

Das Problem ist halt, das der Server ja ständig (while(true)) checken muss, ob er daten bekommt, oder geht das auch anders? es wäre ja am besten, wenn er nur "anspringt" wenn auch daten gesendet werden.

Gruß


----------



## Michael... (8. Jun 2010)

Achso der Server hat auch noch eine GUI!?
Ändert aber nichts daran, dass das Lesen vom InputStream in einen eigenen Thread muss.
Das while (true) ist aber tatsächlich fehl am Platz. Und Du holst Dir dauernd den InputStream des Clientsockets.
- einmalig den InputStream holen
- und dann den Stream solange per while auslesen bis er beendet ist, read() also -1 liefert


----------



## ice-breaker (8. Jun 2010)

pyro2k8 hat gesagt.:


> Das Problem ist halt, das der Server ja ständig (while(true)) checken muss, ob er daten bekommt, oder geht das auch anders? es wäre ja am besten, wenn er nur "anspringt" wenn auch daten gesendet werden.


das ist nur in deiner Implementation so 
Normalerweise ruft man die read()-Methode des InputStreams des Sockets oops direkt auf, und diese blockiert dann solange, wie keine Daten gesendet wurden.
Dies macht man dann in einem extra Thread.
So "springt dein Code" erst an, wenn der Thread erfolgreich etwas von dem Socket gelesen hat.

Schau dir nochmal einige Tutorials zu Sockets oder ChatServern an


----------



## Ruzmanz (8. Jun 2010)

Hm, also ich hätte ready() benutzt. Meinst du die Methode, oder read()? Wenn du letzteres meinst, gibt es einen Nachteil -> while(read() != null) vs while(!ready())?


----------



## pyro2k8 (9. Jun 2010)

joa ich habs hinbekommen, wenn auch ohne threads, bzw nur der server benutzt einen thread. 
danke nochmal für die antworten! haben mir sehr geholfen

gruß


----------



## Michael... (9. Jun 2010)

Ruzmanz hat gesagt.:


> Hm, also ich hätte ready() benutzt. Meinst du die Methode, oder read()? Wenn du letzteres meinst, gibt es einen Nachteil -> while(read() != null) vs while(!ready())?


ready() gibt's nur für Reader (hier z.B. wird direkt vom InputStream gelesen) und sagt nur aus, ob es jetzt mit read() was zu lesen gibt oder nicht. Lesen muss man sowieso mit read() die Methode selbst blockiert einfach, bis es etwas zu lesen gibt und gibt -1 zurück wenn der Stream beendet ist.

Edit: Um's nochmal klar zu stellen while(!ready()) bewirkt was völlig anderes. Die Schleife würde solange laufen bis etwas im zum Lesen im Puffer des StreamReaders anliegt und verlassen werden, sobald etwas zum Lesen vorliegt.
Während mit 
	
	
	
	





```
while((int i = inputstream.read())!=-1)
```
 (!=null geht hier nicht, da read() niemals null liefern würde) die Schleife solange läuft und man somit solange vom Stream lesen kann bis dieser beendet ist.


----------

