Java Echo Server + Client

ISOFX

Cadet 2nd Year
Registriert
Aug. 2008
Beiträge
26
Hallo,

bin Schüler einer HTL und hab heute von einem Lehrer die Aufgabe bekommen einen Echo Server mit dazupassendem Client zu schreiben, z.B:

Client sendet "Hallo Server"
Server antwortet "Hallo Server"

weiters soll die Antwort des Server noch in einer GUI dargestellt werden, aber das ist nicht das Problem.

Mein derzeitiger Code sieht so aus:

Code:
import java.io.*;
import java.net.*;


public class EchoServer {
	
	private static void handleConnection( Socket client ){ 
		BufferedReader br=null;
		BufferedWriter bw=null;
		try{
		InputStreamReader is = new InputStreamReader(client.getInputStream(),"utf8");
		OutputStreamWriter ow = new OutputStreamWriter(client.getOutputStream(),"utf8");
		
		br = new BufferedReader(is);
		bw = new BufferedWriter(ow);
		
		String reply = br.readLine();
		bw.write(reply);
		bw.flush();
		}
		catch(IOException ioe){
			ioe.getMessage();
		}
		finally{
			if(br!=null) try{br.close();}catch(IOException e){}
			 if(bw!=null) try{bw.close();}catch(IOException e){}
		}
	  } 
	 
	  public static void main( String[] args ) throws IOException { 
	    ServerSocket server = new ServerSocket(1337); 
	 
	    while ( true ){ 
	      Socket client = null;
	      try{ 
	        client = server.accept(); 
	        handleConnection ( client ); 
	      } 
	      catch ( IOException e ) { 
	        e.printStackTrace(); 
	      } 
	      finally { 
	        if ( client != null ) 
	          try { client.close(); } catch ( IOException e ) { } 
	      } 
	    } 
	  } 
}

Bzw. der Client

Code:
import java.net.*; 
import java.io.*; 
 
public class EchoClient{
	
  public static void main( String[] args ) 
  { 
    Socket server = null; 
    
    BufferedReader br=null;
    BufferedWriter bw=null;
    try 
    { 
      server = new Socket( "localhost", 1337 ); 
      InputStreamReader is = new InputStreamReader(server.getInputStream(),"utf8");
      OutputStreamWriter ow = new OutputStreamWriter(server.getOutputStream(),"utf8");
      br= new BufferedReader(is);
      bw= new BufferedWriter(ow); 
      
      bw.write("Hallo Server");
      bw.flush();
    
      String reply=br.readLine();
      System.out.println(reply);
    } 
    catch ( UnknownHostException e ) { 
      e.printStackTrace(); 
    } 
    catch ( IOException e ) { 
      e.printStackTrace(); 
    } 
    finally 
    { 
      if ( server != null )  try { server.close(); } catch ( IOException e ) { } 
	  if(br!=null) try{br.close();}catch(IOException e){}
      if(bw!=null) try{bw.close();}catch(IOException e){}
    } 
  } 
}

Senden funktioniert problemlos, der Server empfängts auch, dann sende ich die Antwort und genau hier ist mein Problem.

Wie man im Code vom Client sieht will ich nachdem ich gesendet hab sofort die Antwort vom Socket einlesen, ich nehme mal stark an ich muss bevor ich lesen kann warten (wäre nur logisch)

Aber wie kann ich das "warten" auf eine Antwort realisieren? (gibts sowas wie server.accept() für normale Sockets ?)

Oder hab ich einen anderen Fehler im Code den ich ganz einfach übersehen hab ? (Zur Info, der Client bleibt mir beim readLine() hängen, danach wird nichts mehr ausgeführt)

Ich hoffe es kann mir jemand helfen, Danke im Vorraus

lg ISOFX
 
Hi ISOFX,

bei mir funktioniert deine Implementierung leider nicht. Anstatt der InputStreamReader/-writer und BufferedReader/-writer habe ich DataInputStream/-OutputStream benutzt (beim Server und Client).
Code:
DataInputStream dis = new DataInputStream(server.getInputStream());
DataOutputStream dos = new DataOutputStream(server.getOutputStream());
Um Strings auslesen zu können kannst du die Methode readUTF() und um zu schreiben writeUTF() nutzen. Damit sollte es in beide Richtungen funktionieren.

Falls du auf mehr als nur eine Nachricht antworten willst, dann lies weiter.
Mit deiner jetzigen Implementierung kannst du nur einmal was an den Server schicken bzw. der Server reagiert nur auf eine ankommende Nachricht (pro Client):

  • Code:
     while ( true ){ 
          Socket client = null;
          try{ 
             client = server.accept(); 
             handleConnection ( client ); 
          } 
          catch ( IOException e ) { 
             e.printStackTrace(); 
          } 
          finally { 
             if ( client != null ) 
              try { client.close(); } catch ( IOException e ) { } 
          } 
    }
    In dieser while-Schleife wartet der Server auf Verbindungsanfragen und führt beim Erfolg handleConnection (client) aus. Dabei wird die zugeschickte Nachricht zurück an den Client geschickt und damit it ein Durchlauf der Schleife vorbei (Hinzu kommt noch der finally-Block, der jedes Mal ausgeführt wird und das ist unabhängig davon, ob eine Exception auftritt oder nicht). Man landet also wieder in der while-Schleife kommt aber nicht weiter, da der Server wieder eine Verbindungsanfrage erwartet. Hier wäre es sinnvoll diese Anfrage noch vor der Schleife abzuarbeiten.

  • Wie bereits erwähnt, der finally-Block wird immer ausgeführt, selbst wenn eine Exception auftritt. Im Client steht bei dir folgendes:
    Code:
    if ( server != null ) { 
         try { 
             server.close(); 
         } catch ( IOException e ) {
              // hier sollte noch eine Exception-Behandlung rein, zumindest ein e.printStackTrace()
         }
    }// alles in eine Zeile zu schreiben ist nicht schön :)

    Vielleicht ist das beabsichtigt, aber damit kappst du die Verbindung zum Server sofort nachdem du eine Nachricht abgeschickt und eine Antwort bekommen hast. Normalerweise macht man es in diesem Fall dann aber (zuerst) im try-Block in dem du die Antwort verarbeitest.
  • ...

Hmm, ich merke gerade, dass du wahrscheinlich nur die Stream-Geschichte brauchst. Naja, kaum habe ich in die Tasten gehauen, konnte ich mich nicht mehr zurückhalten ;). Ich dachte, die GUI wäre auch dazu da, um Nachrichten einzutippen und sie dann an den Server zu schicken, aber das war wohl falsch gedacht.
Wenn was nicht ganz stimmt, dann lasse ich mich gern eines Besseren belehren.

Viel Erfolg!

Schöne Grüße
munchkin
 
Zuletzt bearbeitet:
Wie man im Code vom Client sieht will ich nachdem ich gesendet hab sofort die Antwort vom Socket einlesen, ich nehme mal stark an ich muss bevor ich lesen kann warten (wäre nur logisch)

das ist so nicht ganz richtig. du musst unterscheiden zwischen blocking- und nonblocking-i/o. standard wäre hier blocking. d.h. ein aufruf auf recv (hier: readLine()) hält das programm so lange an, bis Daten angekommen sind.

Dein Fehler hier ist der aufruf readLine().. diese funktion ist intern eine schleife, die solange aus dem socket ließt, bis ne zeile zuende ist (also wenn \r, \n oder ne mischung aus beidem ankommt). Da du aber nur "Hallo Server" sendest, KANN readLine() NIE eine komplette zeile empfangen.
Ums kurz zu machen: nicht nur dein client hängt und wartet, sondern auch dein server ;)

Beheben kannst das indem du nach bw.write(...) im client noch ein bw.newLine() einbaust.
 
Wer die Java API - Spezifikation lesen kann ist klar im Vorteil. Klappt bei mir jetzt auch. Da ich beim Debuggen in der Zeile br.readline() immer zu stehen kam, dachte ich zuerst, dass die Methode blockierend ist, aber um es geauer in der Spezifikation nachzuschauen, dafür war ich mir wohl viel zu schade ;).
Naja, hoffentlich lerne ich das irgendwann.
 
Zurück
Oben