# Server soll Daten schicken, aber wie?



## H3llGhost (11. Feb 2008)

Hallo Leute,

ich habe eine Frage:

Ich habe zwei Programme geschrieben und davon ist ein ein Server:


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

public class SpardoseServer extends Thread {

       protected Socket socket = null;
       public static int port;
       private SpardoseServer ss;
       private static String pfad = "", datein = "";
       private static KundenAuslesen ka;
       private static Person[] personen;

       public static void main(String args[]) {
       
       System.out.println("Spardosen-Server v. 0.1b\n");

     try {
       BufferedReader lesen = new BufferedReader(new FileReader("config.ini"));
        String zeile;
        while ((zeile = lesen.readLine()) !=null) {
          if (zeile.contains("pfad")) {
           pfad = zeile.replace("pfad=" , "");
          }
          if (zeile.contains("datein")) {
           datein = zeile.replace("datein=" , "");
          }
          if (zeile.contains("port")) {
           port = Integer.parseInt(zeile.replace("port=" , ""));
          }
        }
      }catch(Exception f){
        System.out.println("Fehler: " +f);
      }
     if ((pfad == "") || (datein == ""))
     {
      if (pfad == "") System.out.println("pfad fehlt");
      if (datein == "") System.out.println("dateinamem fehlt");
      System.exit(0);
     } else
     {
      if (port == 0)
      {
        port = 4711;
        System.out.println("Standard-Port gesetzt!");
      }
      System.out.println("Port: "+port);
      System.out.println("Config erfolgreich ausgelesen ...");
     }
     
     try
     {
      BufferedReader lesen2 = new BufferedReader(new FileReader(pfad+"\\"+datein));
     } catch (Exception e)
     {
      try {
       BufferedWriter bw2 = new BufferedWriter(new FileWriter(pfad+"\\"+datein));
      } catch (Exception f)
      {
       System.out.println("Datei kann nicht erstellt werden!");
       System.exit(0);
      }
     }
     
     ka = new KundenAuslesen(pfad+"\\"+datein);
     personen = ka.auslesen();
     
     System.out.println("Server erfolgreich gestartet!\n\n");

              // Socket bereitstellen, an dem "gelauscht" wird
              try {
                  ServerSocket listen = new ServerSocket(port);

                  while(true) {
                              SpardoseServer sClient = new SpardoseServer(listen.accept());
                  }
              } catch (IOException ioe) {
                  System.err.println("Fehler: "+ioe.toString());
              }

       }

       public SpardoseServer(Socket socket) {
              this.socket = socket;
              start();
       }

       public void run() {
       try {
            InputStreamReader  isr = new InputStreamReader(socket.getInputStream());
            BufferedReader in = new BufferedReader(isr);
             String tmp;
             while ((tmp =in.readLine()) != null)
             {
              if (tmp.startsWith("kopen"))
              {
                System.out.println(tmp);
                tmp = tmp.replace("kopen ", "");
                String[] tmp2 = tmp.split(" ");
                int kid = Integer.parseInt(tmp2[0]);
                System.out.println(socket.getRemoteSocketAddress()+" Kunde "+personen[kid].getName()+"(ID: "+personen[kid].getId()+") öffnen");
                if (kid < ka.getPersonenAnzahl())
                {
//        try {
//         tmpi = Integer.parseInt(fe.user.getText());
//         System.out.println(personen[].getName());
//         System.out.println(personen[1].getPassword());
//         e = true;
//        }
                if (personen[kid].getLock())
                {
                  System.out.println(socket.getRemoteSocketAddress()+" Fehler: Kunde "+personen[kid].getName()+"(ID: "+personen[kid].getId()+") ist schon geöffnet!");
                } else
                {
                  System.out.println(socket.getRemoteSocketAddress()+" Kunde "+personen[kid].getName()+"(ID: "+personen[kid].getId()+") wird gesperrt!");

                }
                }
                
//       if (Integer.parseInt(fe.user.getText()) < ka.getPersonenAnzahl())
//       {
//        try {
//         tmpi = Integer.parseInt(fe.user.getText());
//         System.out.println(personen[1].getName());
//         System.out.println(personen[1].getPassword());
//         e = true;
//        }
//        catch (Exception ef) {
//         System.out.println(ef);
//         Toolkit.getDefaultToolkit().beep();
//         JOptionPane.showMessageDialog(null, "Ungültige User-ID!", "Fehler!", JOptionPane.ERROR_MESSAGE);
//         e = false;
//         fe.user.setText("");
//         fe.pw.setText("");
//        }
//        if (e == true)
//        {
//          if (personen[tmpi].getPassword().equals(fe.pw.getText()))
//          {
//           eingeloggt = true;
//           AbfrageExit();
//          } else
//          {
//           System.out.println(fe.pw.getText());
//           JOptionPane.showMessageDialog(null, "Falsches Passwort!", "Fehler!", JOptionPane.ERROR_MESSAGE);
//           fe.pw.setText("");
//           eingeloggt = false;
//          }
//        }
//       } else
//       {
//        JOptionPane.showMessageDialog(null, "Ungültige User-ID!", "Fehler!", JOptionPane.ERROR_MESSAGE);
//        fe.user.setText("");
//        fe.pw.setText("");
//       }
                
              }
              if (tmp.startsWith("cexit")) break;
              System.out.println(tmp);
             }
            System.out.println(socket.getRemoteSocketAddress()+" Verbindung zu Client getrennt");
            socket.close();
           } catch (IOException e) {
            System.err.println("Fehler: "+e.toString());
           }
       }
} // Ende der Klasse
```

Und dazu habe ich einen Client:


```
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
import java.io.*;
import java.net.*;

public class SpardoseClient extends JFrame implements ActionListener
{
   private JMenuItem neuItem, logoutItem, exitItem;
   private static JPanel einPanel, einPanel2, einPanel3;
   private Spardose sp;
   private Spardose_zeichnen sz;
   private String zeile = "", zeile2 = "", pfad = "", datein = "", tmp = "";
   private KundenAuslesen ka;
   private static Dimension d;
   private static SpardoseClient fe;
   private JButton bestaetigenButton, exitButton;
   private JTextField user, pwf;
   //private JPasswordField pwf;
   private String usert, pwt;
   private JButton bestaetigen1Button, bestaetigen2Button;
   private JLabel kontostandtext, kontostand2text;
   private JTextField kontostand;
   private JLabel bestaetigen1text, bestaetigen2text;
   private JTextField bestaetigen1, bestaetigen2;
   private double geld;
   private int tmpi = 0;
   private Person[] personen;
   private boolean e = true, eingeloggt = false;
   private JMenuBar menuBar;
   private JMenu dateiMenu;
   private PrintWriter pw;
   // Konstruktor, alles was man für die Initialisierung benötigt hier hinein!!
   public SpardoseClient() throws Exception
   {
    Console eingabeTastatur = System.console();
    Socket server = new Socket("localhost", 4711);
    InputStreamReader  in  = new InputStreamReader(server.getInputStream());
    BufferedReader datenstromEinlesen = new BufferedReader(in);
    OutputStreamWriter out = new OutputStreamWriter(server.getOutputStream());
    pw = new PrintWriter(out, true);

     setTitle("Virtuelle Spardose");
     d = Toolkit.getDefaultToolkit().getScreenSize();
     setSize(d.width, d.height); // Größe des Rahmens in Pixel
     setDefaultCloseOperation(EXIT_ON_CLOSE); // Schließt den Rahmen

     menuBar = new JMenuBar();
     setJMenuBar(menuBar);
     dateiMenu = new JMenu("Datei");

     neuItem = new JMenuItem("Neuer Kunde");
     neuItem.addActionListener(this);

     logoutItem = new JMenuItem("Ausloggen");
     logoutItem.addActionListener(this);

     exitItem = new JMenuItem("Exit");
     exitItem.addActionListener(this);

     einPanel = new JPanel();  // Erzeugung der "Leinwand" für die Komponenten
     einPanel.setLayout(null); // Keinen Layoutmanager verwenden
     einPanel.setBackground(Color.GRAY);

     einPanel2 = new JPanel();  // Erzeugung der "Leinwand" für die Komponenten
     einPanel2.setLayout(null); // Keinen Layoutmanager verwenden
     einPanel2.setBackground(Color.GRAY);

     einPanel3 = new JPanel();  // Erzeugung der "Leinwand" für die Komponenten
     einPanel3.setLayout(null); // Keinen Layoutmanager verwenden
     einPanel3.setBackground(Color.GRAY);

     user = new JTextField("", 10);
     user.setDocument(new NumberDocument());
     user.setEditable(true);
     user.setText("");
     user.setToolTipText("Hier ist ihr aktueller user!");
     user.setBounds(49, 50, 100, 30);

     pwf = new JTextField("", 10);
     pwf.setDocument(new StringNumberDocument());
     pwf.setEditable(true);
     pwf.setText("");
     pwf.setToolTipText("Hier ist ihr aktueller user!");
     pwf.setBounds(151, 50, 100, 30);

     bestaetigenButton = new JButton("OK");  // Erzeugung des Buttons
     bestaetigenButton.setBounds(49, 100, 100, 30);
     bestaetigenButton.setToolTipText("Klicke hier zum Berechnen!");
     bestaetigenButton.addActionListener(this);

     exitButton = new JButton("Abbrechen");  // Erzeugung des Buttons
     exitButton.setBounds(151, 100, 100, 30);
     exitButton.setToolTipText("Klicke hier zum Beenden!");
     exitButton.addActionListener(this);

     kontostandtext = new JLabel();
     kontostandtext.setBounds((d.width-375)/2, 50, 250, 30);
     kontostandtext.setFont(new Font("MS Sans Serif", Font.PLAIN, 18));
     kontostandtext.setText("Aktueller Kontostand in Euro:");

     kontostand = new JTextField("", 10);
     kontostand.setDocument(new NegativeDoubleDocument());
     kontostand.setEditable(false);
     kontostand.setText(String.valueOf(geld));
     kontostand.setToolTipText("Hier ist ihr aktueller Kontostand!");
     kontostand.setBounds((d.width+125)/2, 50, 100, 30);

     bestaetigen1Button = new JButton("Bestätigen");  // Erzeugung des Buttons
     bestaetigen1Button.setBounds(d.width-200, 150, 140, 30);
     bestaetigen1Button.setToolTipText("Klicke hier zum Berechnen!");
     bestaetigen1Button.addActionListener(this); // this ist eine Referenz auf die eigene Klasse

     bestaetigen1 = new JTextField("", 10);
     bestaetigen1.setDocument(new NegativeDoubleDocument());
     bestaetigen1.setEditable(true);
     bestaetigen1.setToolTipText("Bitte hier die einzuzahlenden Euros eingeben!");
     bestaetigen1.setBounds((d.width+50)/2, 150, 50, 30);

     bestaetigen1text = new JLabel();
     bestaetigen1text.setBounds((d.width-250)/2, 150, 150, 30);
     bestaetigen1text.setFont(new Font("MS Sans Serif", Font.PLAIN, 18));
     bestaetigen1text.setText("Einzahlen Euro:");

     bestaetigen2Button = new JButton("Bestätigen");  // Erzeugung des Buttons
     bestaetigen2Button.setBounds(d.width-200, 200, 140, 30);
     bestaetigen2Button.setToolTipText("Klicke hier zum Beenden!");
     bestaetigen2Button.addActionListener(this);

     bestaetigen2 = new JTextField("", 10);
     bestaetigen2.setDocument(new NegativeDoubleDocument());
     bestaetigen2.setEditable(true);
     bestaetigen2.setToolTipText("Bitte hier die einzuzahlenden Euros eingeben!");
     bestaetigen2.setBounds((d.width+50)/2, 200, 50, 30);

     bestaetigen2text = new JLabel();
     bestaetigen2text.setBounds((d.width-250)/2, 200, 150, 30);
     bestaetigen2text.setFont(new Font("MS Sans Serif", Font.PLAIN, 18));
     bestaetigen2text.setText("Auszahlen Euro:");

     kontostand2text = new JLabel();
     kontostand2text.setBounds((d.width-250)/2, 200, 250, 30);
     kontostand2text.setFont(new Font("MS Sans Serif", Font.PLAIN, 18));
     kontostand2text.setText("");

     sz = new Spardose_zeichnen(kontostand2text, d, geld);
     sz.setBounds(0, 350, d.width, d.height);

     einPanel.add(kontostandtext);
     einPanel.add(kontostand);
     einPanel.add(kontostand2text);           // den Button auf die "Leinwand" packen
     einPanel.add(bestaetigen2text);           // den Button auf die "Leinwand" packen
     einPanel.add(bestaetigen2);
     einPanel.add(bestaetigen2Button);
     einPanel.add(bestaetigen1text);           // den Button auf die "Leinwand" packen
     einPanel.add(bestaetigen1);
     einPanel.add(bestaetigen1Button);
     einPanel.add(sz);

     einPanel2.add(user);
     einPanel2.add(pwf);
     einPanel2.add(bestaetigenButton);           // den Button auf die "Leinwand" packen
     einPanel2.add(exitButton);           // den Button auf die "Leinwand" packen

     sp = new Spardose();

     menuBar.add(dateiMenu);         // den Button auf die "Leinwand" packen

     //add(einPanel2);

     setVisible(true); // Zum Schluss das ganze sichtbar machen
     setResizable(true);
   }
   public void Abfrage() {
     fe.user.setText("");
     fe.pwf.setText("");
     fe.dateiMenu.add(neuItem);
     fe.dateiMenu.add(exitItem);
     fe.dateiMenu.remove(logoutItem);
     fe.add(einPanel2);
     fe.setBounds((d.width-300)/2,(d.height-300)/2,300,300);
     fe.setResizable(false);
     fe.setVisible(true);
   }
   public void Abfrageb() {
   if ((!fe.user.getText().equals("")) && (!fe.pwf.getText().equals("")))
     {
     
     
     pw.println("kopen "+fe.user.getText()+" "+fe.pwf.getText());


     }
    }
   public void AbfrageExit() {
      fe.dateiMenu.remove(neuItem);
      fe.dateiMenu.add(logoutItem);
      fe.dateiMenu.add(exitItem);
      fe.remove(einPanel2);
      fe.setBounds(0,0,d.width, d.height);
      fe.add(einPanel);
      sz.setGeld(personen[tmpi].getMoney());
      fe.kontostand.setText(String.valueOf(personen[tmpi].getMoney()));
      fe.setResizable(false);
      fe.setVisible(true);
   }
   public void Haupt() {
     fe.add(einPanel);
     fe.setBounds(0,0,d.width, d.height);
   }
   public void HauptExit() {
     fe.remove(einPanel);
     fe.setSize(d.width,d.height);
   }
   public void KundeNeu() {

   }
   public void KundeNeuExit() {

   }
   public static void main(String args[]) throws Exception
   {
     fe = new SpardoseClient();
     fe.Abfrage();
   }
   public void actionPerformed(ActionEvent evt)
   {
     Object quelle = evt.getSource();
     if(quelle == bestaetigenButton)
     {
      fe.Abfrageb();
     }
     if(quelle == exitButton)
     {
      pw.println("cexit");
      beenden();
     }
     if(quelle == bestaetigen1Button)
     {
      sp.einzahlen(Double.parseDouble(bestaetigen1.getText()));
     }
     if(quelle == bestaetigen2Button)
     {
      sp.abziehen(Double.parseDouble(bestaetigen2.getText()));
     }
     if(quelle == exitItem)
     {
      beenden();
     }
     if(quelle == logoutItem)
     {
      fe.HauptExit();
      fe.Abfrage();
     }
   }

   public void beenden() {
     //ks = new KundenSpeichern(pfad+"\\"+datein, personen.length, ka.getPersonen());
     //ks.speichern();
     System.exit(0);
   }
}
```

Mein Problem ist ganz einfach:

Ich weiß nicht wie ich es realisieren soll. Also ich kann eine Verbindung vom Client auf den Server herstellen und Daten übertragen, aber ich weiß nicht wie ich es in die andere Richtung realisiert wird.

Kann mir jemand helfen?
Bzw. einen Tipp geben wie ich das machen soll?


----------



## SlaterB (11. Feb 2008)

aber schön, dass du schonmal 200 Zeilen GUI hast 
zumindest der Client würde doch auch in ein 50-Zeilen-Konsolen-Programm passen..

-----

also, du hast recht, der Server kann nicht zum Client eine Verbindung als Server zum Client aufbauen,
es geht nur:

a.) die Verbindung vom Client aus bleibt dauerhaft bestehen
oder
b.) der Client ist auch selber ein Server und der Server kann als Client eine Verbindung zum anderen Client (Server  ) aufbauen,
muss die IP-Adresse und Port usw kennen, alles analog


----------



## H3llGhost (11. Feb 2008)

Wie würdest du denn a realisieren?


----------



## SlaterB (11. Feb 2008)

das close() bei einer Verbindung wegstreichen 

ne, keine Ahnung was das Programm überhaupt macht,
erzähl doch mal, wie der Server auf die Idee kommt, einem Client irgendwas zu schicken

da muss sich der Client doch vorher gemeldet haben?
warum ist diese Verbindung nicht mehr da, vergeht zwischendurch ne Stunde Zeit/ kommen viele Clients,
schaltet der Client seinen PC ab oder was ist hier los?


----------



## H3llGhost (12. Feb 2008)

Also die Idee des Programmes ist eine Kontoverwaltung mit Server.
Der Client schickt an den Server Daten, wodrin steht, dass folgendes Konto gesperrt werden soll, so dass keien weitere Person, denselben Kunden öffnen kann.

Wenn das passiert ist, soll der Server was zurückschicken, aber ich weiß nicht wie ich das machen soll ...


----------



## SlaterB (12. Feb 2008)

du hast immer noch nicht gesagt, ob die Verbindung noch offen oder gekapt ist (und wieso),
vielleicht weißt du ja grundsätzlich nicht, dass bei einer Socket-Verbindung vom Client zum Server auch der Server Daten schicken kann?


----------



## H3llGhost (12. Feb 2008)

Die Verbindung kappe ich ja nur wenn der Client weg ist ... 
Hmm ...
Das kann schon sein ... 



> vielleicht weißt du ja grundsätzlich nicht, dass bei einer Socket-Verbindung vom Client zum Server auch der Server Daten schicken kann?



Und wie?
Könntest du mir dafür ein Beispiel bitte geben?


----------



## H3llGhost (15. Feb 2008)

So ...
Habe nun den Server um folgendes erweitert:


```
public void run() {
       try {
            InputStreamReader  isr = new InputStreamReader(socket.getInputStream());
            OutputStreamWriter osw = new OutputStreamWriter(socket.getOutputStream());
            BufferedReader in = new BufferedReader(isr);
            PrintWriter out = new PrintWriter(osw);
             String tmp;
             while ((tmp =in.readLine()) != null)
             {
              if (tmp.startsWith("kopen"))
              {
                System.out.println(tmp);
                tmp = tmp.replace("kopen ", "");
                String[] tmp2 = tmp.split(" ");
                int kid = Integer.parseInt(tmp2[0]);
                System.out.println(socket.getRemoteSocketAddress()+" Kunde "+personen[kid].getName()+"(ID: "+personen[kid].getId()+") öffnen");
                out.println("Kunde geöffnet!");
                System.out.println("Kunde geöffnet!");
[...]
```

Und den Client habe ich um folgendes erweitert:


```
public SpardoseClient() throws Exception
   {
    Console eingabeTastatur = System.console();
    Socket server = new Socket("localhost", 4711);
    InputStreamReader  isr  = new InputStreamReader(server.getInputStream());
    in = new BufferedReader(isr);
    OutputStreamWriter out = new OutputStreamWriter(server.getOutputStream());
    pw = new PrintWriter(out, true);
[...]
```

und


```
public void Abfrageb() {
   if ((!fe.user.getText().equals("")) && (!fe.pwf.getText().equals("")))
     {
     pw.println("kopen "+fe.user.getText()+" "+fe.pwf.getText());
     String tmp;
     try
     {
     while ((tmp =in.readLine()) != null)
     {
     System.out.println(tmp);
     }
     } catch (Exception e)
     {
     System.out.println(e);
     }

     }
    }
```

Habe nun meinen Fehler gefunden!
Ich hatte das Flush nicht aktiviert.
Aber wie kann verhindern, dass ich ein readLine das Programm abstürtzt, wenn kein Printwrite kommt?


----------



## H3llGhost (17. Feb 2008)

Keiner eine Idee?


----------



## SlaterB (17. Feb 2008)

ich kann morgen mal reinschauen, erkläre aber bitte 
> Aber wie kann verhindern, dass ich ein readLine das Programm abstürtzt, wenn kein Printwrite kommt?
näher,

gehts um den Server oder den Client?
welcher Programmzustand, welche Zeile, was ist ein 'Printwrite'?


----------



## H3llGhost (17. Feb 2008)

Es geht um den Client ...
Der Server benutzt einen PrintWriter und dann printLn um seinen Status dem Client mitzuteilen.
Wenn aber der Server mal nichts sendet, dann hängt der Client.
Sprich der macht dann garnichts mehr, der OK-Button der gedrückt worden ist bleibt ewig gedrückt und das wars dann.

Ich hoffe das klärt deine Frage, ansonsten frag nach ...


----------



## SlaterB (18. Feb 2008)

so ist das gedacht in Java, was willst du denn ansonsten haben?

wenn du im Client nebenbei weiterarbeiten willst,
dann musst du das Warten auf den Socket in einen eigenen Thread stecken,
den kannst du nach x Sekunden fragen ob der Server schon geantwortet hat oder nicht


----------



## tuxedo (18. Feb 2008)

Oder man benutzt RMI (oder Simon *mitdemzaunpfahlwink*). Dann muss man sich nahezu keine Gedanken machen wie was und wo übertragen wird oder mit einem Thread entkoppelt werden muss.

- Alex


----------



## SlaterB (18. Feb 2008)

wenn sich der Server ein sleep(10000) gönnt oder entsprechend lange sinnvoll arbeitet, 
dann kann man aber auch mit RMI die Client-GUI lahmlegen


----------



## tuxedo (18. Feb 2008)

Stimmt. Mit Threads arbeiten können schadet wirklich nix. 
Mit RMI spart man sich eben den Protokoll-Kram.

- Alex


----------



## H3llGhost (18. Feb 2008)

Wie meinst du das mit dem Warten?


----------



## SlaterB (18. Feb 2008)

entweder du fragst den Server blockierend, dann macht der Client so lange Pause, bis die Antwort da ist,
oder der Client läuft weiter und wartet nur in einem separaten Thread auf die Antwort,

die wird nach einer Nanosekunde nicht da sein, nach zwei auch nicht,
der Rest des Clients muss überlegen, wann er den separaten Thread nach der Antwort fragt,
dafür könnte der Rest warten (Thread.sleep()) oder das Nachfragen passiert erstn nach einer User-Eingabe (Refresh-Button)
oder der separate Thread wird selbstständig aktiv, wenn er die Antwort vom Server erhält,
oder oder oder


----------



## tuxedo (18. Feb 2008)

Na wenn der Server mit dem abarbeiten einer Methode beschäftigt ist und der Client nur den Main-Thread hat in dem er auf das Ergebnis des Methodenaufrufs wartet, dann muss der Client warten.

Wenn der Client allerdings mit mehr als einem Thread arbeitet kann er in dem einen auf das Ergebnis warten und im anderen andere Dinge erledigen. Schlage vor du liest dich mal ins Kapitel "Threads" der Javainsel (google oder FAQ hilft) ein.



- Alex


----------



## H3llGhost (18. Feb 2008)

Irgendwie wird das sehr kompliziert ...
Ich habe ehrlich gesagt nicht so die Ahnung jetzt jedes Programm mit Threads auszustatten ... 

Aber ist es eigentlich mit dem Quellcode vom Client, den ich mal gepostet habe überhaupt möglich?


----------



## SlaterB (18. Feb 2008)

was soll man da sagen, in jedes Programm kann man irgendwas einbauen, wenn man nur lang genug daran biegt 

das wäre eine separate Klasse, die an mehreren Stellen aufgerufen werden,
aber so genau kann man das nichtmal beschreiben, solange nicht feststeht, was eigentlich passieren soll


----------



## H3llGhost (18. Feb 2008)

Was fehlt dir denn noch zum kompletten Verständnis des Programmes?


----------



## SlaterB (18. Feb 2008)

na alles, da ich bisher noch gar nichts verstanden habe, da du bisher noch nichts erklärt hast
(außer dass du nicht zufrieden bist, wenn dein Client wartet)


----------



## H3llGhost (18. Feb 2008)

Also mein Client "loggt" sich beim Server ein bzw. versucht es.
Der Server antwortet mit einem Statuscode, was Sache ist.
Und da ich eine universelle Verarbeitungsschleife mit dem Statuscode des Servers schreiben wollte, bin ich halt unzufrieden.
Weil hin und wieder sendet der Server nur eine Zeile im Falle von einem Fehler und bei einem Erfolg sendet er halt mehrere Zeilen zurück.
Verstehste jetzt was ich meine?


----------



## SlaterB (18. Feb 2008)

> Und da ich eine universelle Verarbeitungsschleife mit dem Statuscode des Servers schreiben wollte

ich weiß nicht so wirklich was das ist, klingt aber nach einem normalen Stück Programm

>  bin ich halt unzufrieden

keine Ahnung, warum du mit deinem normalen Programm unzufrieden bist

> Weil hin und wieder sendet der Server nur eine Zeile im Falle von einem Fehler und bei einem Erfolg sendet er halt mehrere Zeilen zurück. 

klingt alles irgendwie nicht bösartig und selbst wenn: du kontrollierst ja was der Server sendet,
da kannst du dich nicht beschweren

> Verstehste jetzt was ich meine?

weniger als vorher, denn vom Blockieren des Clients ist nun gar nicht mehr die Rede


----------



## H3llGhost (18. Feb 2008)

Der Client selber blockiert sich aber wenn ich eine readLine()-Funktion aufrufe und drauf warte das ein InputStream kommt, dann blockiert der Client.

Was eine universelle Verarbeitungsschleife ist?
Ganz einfach:

Ein Code der mit jeden Statuscode vom Server klar kommt.
Fertig.
Sprich sendet der Server Code 0 => Fehler, nicht auf weitere Inputs warten.
Sendet der Server Code 1 => Alles ok, weitere Inputs vom Server abwarten.

Und das möchte ich halt in eine Funktion, Methode oder wie ich es jetzt da auch immer am Besten einbauen kann, schreiben.

Eindeutiger geworden?


----------



## tuxedo (19. Feb 2008)

Ich kann's nur nochmal betonen:

a) Nimm RMI oder was vergleichbares (Simon ;-) ). Dann sparst du dir den Protokoll-Quatsch. Da du, wie zwischen den Zeilen zu lesen ist, dich mit der Materie "Protokoll" eh noch nicht so gut auskennst ist das wohl der einfachste Weg.

b) Schau in die Javainsel und schlag dort bei den Threads  nach.

Wenn du a) befolgst solltest du binnen 1 Std. ein funktionsfähiges Gerüst haben. Wenn du dich noch im Thema Threads einliest, solltest du nach einer weiteren Stunde das auch erledigt haben und den Thread hier abhaken können.

- Alex


----------



## SlaterB (19. Feb 2008)

> Ein Code der mit jeden Statuscode vom Server klar kommt.  [0 -> .., 1 -> ..]

sicher ist sowas nett, und deine Aufgabe, das zu programmieren,
ist nicht schwer und bisher nicht da also noch zu programmieren,
was ist dazu die Frage?


hier gebe ich alex0801 recht, dass du mit RMI hier z.B. einen String mit beliebig vielen Zeilen senden kannst, ohne das auf einzelne Zeilen gewartet werden muss,
oder noch besser, es können gleich höhere Objekte mit int statuscode, String message, und vielem anderen ohne Aufwand ausgetauscht werden

alles per String zu übertragen hat natürlich auch seine Reize,
noch ein Tipp zur Verarbeitung in der 'universelle Verarbeitungsschleife':
schicke die Anfragen und Antworten es formatierter als XML:

eine Antwort:
<antwort>
<statuscode>
0
</statuscode>

// optional:
<message>
  ...
</message>
</antwort>

selbst wenn du keine XML-Tools zum Lesen/ Schreiben verwendest,
hast du zumindest leichter lesbare + analysierbare Nachrichten


----------



## H3llGhost (19. Feb 2008)

*baff*

Und wie soll ich das mit dem XML realisieren?
Und was zum Teufel ist eigentlich RMI?
Ist das hier das richtige?
http://de.wikipedia.org/wiki/Remote_Method_Invocation


----------



## SlaterB (19. Feb 2008)

das ist richtig, ja

XML:

String antwort = "<antwort>\n";
antwort +="<statuscode>\n"+statuscode+"<s/tatuscode>";
usw.


----------



## H3llGhost (19. Feb 2008)

Und dann das Durchsuchen lassen?
Oder wie stellst du dir die weitere Verarbeitung vor?


----------



## SlaterB (19. Feb 2008)

ja so stelle ich mir das vor


----------



## H3llGhost (19. Feb 2008)

Ich verstehe nur noch nicht wie ich den String dann untersuchen soll.
Kannst du mir dabei helfen?
Mit contains()?


----------



## SlaterB (19. Feb 2008)

wenn du die besonderen Token als einzelne Zeilen schreibst, dann reicht auch equals,
die Nachricht ist beispielsweise zu Ende, wenn die aktuelle Zeile gleich "</antwort>" ist

> Kannst du mir dabei helfen? 

nur sehr begrenzt, 
wenn du inhaltlich stichhaltige Fragen stellst, kann ich sie hoffentlich beantworten,
für dich programmieren geht aber nicht


----------



## H3llGhost (19. Feb 2008)

Jetzt verstehe ich garnichts mehr ...
Ich dachte es sollte ein String sein der komplett gesendet wird.
Also einzeilig ...

Jetzt soll der mehrzeilig sein?
Wenn ja kann ich die Abtrennung mit dem PrintWriter println("blabla\nbalba"); machen?
Ist das richtig so von der Theorie?

Und dann später mit dem String noch was machen?
Also die \n als Trennzeichen nehmen und einen explode durchführen?


----------



## SlaterB (19. Feb 2008)

nun, dass mehrere Zeilen gesendet werden war deine Idee,
oder habe ich zumindest so rausgelesen

>  Weil hin und wieder sendet der Server nur eine Zeile im Falle von einem Fehler und bei einem Erfolg sendet er halt mehrere Zeilen zurück.

> Wenn aber der Server mal nichts sendet, dann hängt der Client. 
[weil er auf die restlichen Zeilen wartet, die im Normalfall noch kommen würden]

wenn du immer nur genau eine Zeile sendest, dann kann ja zumindest schonmal der Client nicht mehr blockieren,
war das nicht das Hauptproblem?

wie auch immer, im Falle nur einer Zeile musst du mit contains() arbeiten, ja

-------------

> Wenn ja kann ich die Abtrennung mit dem PrintWriter println("blabla\nbalba"); machen? 
> Ist das richtig so von der Theorie? 

am besten ist beim Schreiben, jede Zeile einzeln zu schreiben und dann 
writer.newLine();
\n sollte aber im Normalfall das richtige Zeichen sein, ja

> Also die \n als Trennzeichen nehmen und einen explode durchführen?

normalerweise liest der Client doch zeilenweise ein?
dann hast du die Zeilen einzeln, dann musst du nicht mehr trennen, die \n filtert dann Java sowieso raus


----------



## H3llGhost (19. Feb 2008)

Aber dann bin ich doch wieder bei dem selben Problem oder?
Der Client wird sich aufhängen oder?
Weil er doch mehr erwartet ...


----------



## SlaterB (19. Feb 2008)

wenn du mehrzeilig arbeitest, dann muss der Server als letzte Zeile </antwort> schicken,
egal, ob es insgesamt 5 (nur Statuscode) oder 55 Zeilen sind (mit Message)

der Client schaut auf jede Zeile, 
wenn diese gleich </antwort> ist, dann weißt der Client, dass nix weiter kommt,
hört auf zu warten -> blockiert nicht

wie der Client auf das Fehler der Message reagiert, ist damit noch nicht gesagt, 
es geht nur um den Empfang der Gesamtnachricht


----------



## H3llGhost (19. Feb 2008)

hmm ...
Also ich habe nun vor die Sachen in einem Array zu speichern.
Weißt du wie ich ein Array dynamisch verlängern kann?


----------



## SlaterB (19. Feb 2008)

klar, nennt sich ArrayList


----------



## H3llGhost (19. Feb 2008)

Kannte ich bis jetzt noch nicht sry ... 

Habe das nun so geregelt:

```
input = new ArrayList();
     try
     {
       while (in.readLine() != "</antwort>")
       {
         input.add(in.readLine());
       }
     } catch (Exception e)
     {
      System.out.println(e);
     }
input.add("</antwort>");
```
Ist das so generell von der Idee richtig?

Beim Kompilieren kommen aber folgende Meldungen:



> Note: SpardoseClient.java uses unchecked or unsafe operations.
> Note: Recompile with -Xlint:unchecked for details.



Hast du eine Idee woran das liegen kann?


----------



## tuxedo (20. Feb 2008)

mit != überprüft man keine Strings, sondern Referenzen

Würde eher sowas wie


```
while(!in.readLine().equalsIgnoreCase("</antwort>"))
```

nehmen.

- Alex


----------



## SlaterB (20. Feb 2008)

die Warnung kommt wegen 
ArrayList()
statt
ArrayList<String>() 
usw.

Generics verwenden oder mit der Warning leben


----------



## H3llGhost (20. Feb 2008)

alex0801 hat gesagt.:
			
		

> mit != überprüft man keine Strings, sondern Referenzen
> 
> Würde eher sowas wie
> 
> ...



Ach deswegen hat es nie bei mir geklappt ... xD

Ich habe das nun so mit dem Generics gemacht wie auf dieser Seite hier:

Klick
Geht aber trotzdem nicht selber Fehler!


```
input = new ArrayList();
     try
     {
       while (!in.readLine().equalsIgnoreCase("</antwort>"))
       {
         input.add((String)in.readLine());
       }
     } catch (Exception e)
     {
      System.out.println(e);
     }
     input.add((String)"</antwort>");
```


----------



## SlaterB (21. Feb 2008)

tja, vielleicht weil auf der kleinen Seite Generics nicht komplett erklärt wird? 

> input.add((String)"</antwort>");

"</antwort>" ist doch schon ein String, was um alles in der Welt bringt es, nochmal auf String zu casten?
in einer guten Programmierumgebung wie Eclipse bekommst du dann eher eine zusätzliche Warnung wegen Unsinnigkeit statt eine weniger 

wenn du nicht weißt, was Generics ist, dann lasse es weg,
ansonsten lerne es einen Tag bis eine Woche lang in 10-100 Seiten,
nicht 10 Min. lang auf einer Seite

http://www.galileocomputing.de/open...06_012.htm#ix9045e82a74f9b3dce8278c3231a4ecda

oder schaue dir zumindest die vollständigeren Beispiele dort an

-------

> while (!in.readLine().equalsIgnoreCase("</antwort>")) 
>      { 
>         input.add((String)in.readLine()); 
>       } 

hier prüfst du übrigens Zeile 1 und fügst dann dem input die nächste Zeile 2 hinzu!,
jeder Aufruf von in.readLine() liest eine neue Zeile,
da das ein String ist, ist auch hier der Cast unnötig


----------



## H3llGhost (21. Feb 2008)

Hey danke für die schnelle Antwort!
Hatte gestern noch eine andere Seite zu den Generics gefunden und das wie es da erklärt worden ist, hat funktioniert ... 

Mit dem readLine() stimmt, habe ich nicht gerade nicht drangedacht!
Danke für den Tipp ... 
Werde nun mal weiterbasteln ...


----------



## tuxedo (21. Feb 2008)

H3llGhost hat gesagt.:
			
		

> ..., habe ich nicht gerade nicht drangedacht!



Doppelte Negation... Also hast du doch wieder dran gedacht ;-)

- Alex


----------



## H3llGhost (21. Feb 2008)

Stimmt ...


----------



## H3llGhost (28. Feb 2008)

Hallo Leute,

ich habe nun einen Code zum Auslesen von Kunden aus einer Datei:


```
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.Vector;
import java.util.ArrayList;

public class KundenAuslesen {

   private Vector<String> zeilen;
   private String datei;
   private int hoechsteid;
   private String tmp;

   public KundenAuslesen(String datei) {
      zeilen = new Vector<String>();
      this.datei = datei;
      hoechsteid = 0;
      tmp = "";
   }
   public int getPersonenAnzahl() {
      int anzahl = 0;   // Zaehler
      BufferedReader br;
      String zeile = "";
      try {
         br = new BufferedReader(new FileReader(datei));
         while((zeile = br.readLine()) != null) {
            if(zeile.startsWith("[")) {
               anzahl++;
               //continue;
               tmp = zeile.replace("[", "");
               tmp = tmp.replace("]", "");
               if (Integer.parseInt(tmp) > hoechsteid)
               {
                 hoechsteid = Integer.parseInt(tmp);
               }
            }
            zeilen.add(zeile);
         }
         br.close();
      } catch (FileNotFoundException e) {
         // TODO Auto-generated catch block
         e.printStackTrace();
      } catch (IOException e) {
         // TODO Auto-generated catch block
         e.printStackTrace();
      }

      return anzahl;
   }
   public Person[] getPersonen() {
      getPersonenAnzahl();
      Person[] pers = new Person[hoechsteid+1];
      Person p = new Person();
      int cnt = 0;
      for(String zeile: zeilen) {
         if (cnt == 0) {
            p.setID(Integer.parseInt(zeile.replaceAll("\\W", "")));
            cnt++;
            continue;
         }
         if (cnt == 1) {
            p.setName(zeile.substring(1));
            cnt++;
            continue;
         }
         if (cnt == 2) {
            String tmp2 = zeile.substring(1);
            p.setMoney(Double.parseDouble(tmp2.replace(",", ".")));
            cnt++;
            continue;
         }
         if (cnt == 3) {
            p.setPassword(zeile.substring(1));
            cnt = 0;
         }
         pers[p.getId()] = new Person(p.getId(), p.getName(), p.getMoney(), p.getPassword(), false, false);
      }
      return pers;
   }
   public Person[] auslesen() {
      System.out.println("Kunden auslesen ...");
      System.out.println("höchste Kunden-ID: "+getPersonenAnzahl());
      KundenAuslesen da = new KundenAuslesen(datei);
      Person[] personen = da.getPersonen();
      System.out.println("Fertig!");
      return personen;
   }

}
[code]

Mein Problem ist nun folgendes:

Ich möchte das Array verlängern und ich habe es schon mit ArrayList ausprobiert, aber ich weiß nicht wie ich folgende Zeile:

pers[p.getId()] = new Person(p.getId(), p.getName(), p.getMoney(), p.getPassword(), false, false);

mit einer ArrayList realisieren soll!
Ich hatte folgendes probiert:

pers.set(p.getId(), new Person(p.getId(), p.getName(), p.getMoney(), p.getPassword(), false, false));

Aber das hat nicht funktioniert.
Könnt ihr mir bitte nochmal helfen?
Danke im Voraus!
```


----------

