# Warum empfängt mein Stream keinen Input?



## lacyuu (11. Jun 2009)

Ich arbeite gerade an einer Art Chat-Programm dass auf dem Client-Server-Modell basiert.
Die Clients melden sich an, Passwort und Name werden überprüft und dann können die Clients Nachrichten an alle Clients senden oder eine Nachricht empfangen.

Wenn sich ein Client anmeldet, sendet er dem Server seine Userdateien, danach startet er einen Thread um Nachrichten zu empfangen, und geht dann in eine Schleife, in der er die Möglichkeit hat, Nachrichtern zu schreiben und abzuschicken. Wenn jetzt der Server z.B. eine nachricht schickt, dass der Client angemeldet ist, passiert nichts.
Beim Client kommt nichts an.
An der Serverseite kann's nicht liegen, dort hab ich alles gecheckt und der Output wird gesendet.

Hier erstmal der Code:


Der Client:

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


public class Client {

            public static void main(String[] args)throws IOException{

                
                anmeldung();
            }
    
            
    public static void anmeldung() throws IOException{

String Name;
String Passwort;

try{
          Socket csocket = new Socket("localhost",12345);       //Verbinden mit dem Server über Socket
    ObjectOutputStream send = new ObjectOutputStream (csocket.getOutputStream());
   BufferedReader in = new BufferedReader ( new InputStreamReader(System.in));

       System.out.print("Bitte Namen eingeben: ");        //Dateneingabe
       Name = in.readLine();



       System.out.print("Bitte Passwort eingeben: ");
       Passwort = in.readLine();

       User clientuser = new User(Name,Passwort);       //Anlegen einer UserKlasse
       Message msg = new Message("",clientuser);               //Anlegen einer default-Message

       send.writeObject(clientuser);        //User-Objekt wird verschickt
       send.flush();
       System.out.println("So, Paket ist raus!!");


    ThreadEmpfang empfang = new ThreadEmpfang(csocket);     //Starten der Threads die gleichzeitiges Senden und Empfangen von Nachrichten ermöglichen

    empfang.start();

    try{
while(true){
         System.out.print("Nachricht eingeben: ");
       message.nachrichtschreiben(in.readLine());
      send.writeObject(message);
      send.flush();
         }
        }catch(IOException e){System.err.print(e);}
    




}catch(IOException e){System.err.println(e);}

    }

}
```

und noch der Empfangsthread:


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

public class ThreadEmpfang extends Thread{

    Socket socket;
    Message nachricht;

    ThreadEmpfang(Socket socket){

            this.socket = socket;

    }

    @Override
    public void run(){
        try{   


            while(true){
                nachricht = new Message("");
              ObjectInputStream input= new ObjectInputStream(socket.getInputStream());
              nachricht = (Message)input.readObject();
              Darstellung(nachricht);
            }
        }catch(IOException e){}
        catch(ClassNotFoundException f){System.out.println("Falscher Datentyp.");}
    }

    public void Darstellung(Message message){
        if(message.absender==null){
            System.out.println("default: "+message.msg);
        }
        else{System.out.println(message.absender.name+" : "+message.msg);}
    }
}
```


Was noch zu erwähnen wäre:

Den Empfangsthread wie er da so steht, hab ich zum Testen in einem vereinfachten Client-ServerProgramm verwendet, dort hat der Client auch etwas empfangen! (aber glaube ich irgendwo anders dann blockiert)

Außerdem verwende ich nur ObjectStreams über die ich einerseits User Objekte(enthalten Userdaten) und Message Objekte(enthalten Nachricht und den absender User)


Habe ich also irgendwas irgendwo falsch gemacht? Oder könnte sich der Fehlerteufel an einer ganz anderne Stelle eingeschlichen haben, was immer wieder Probleme beim Senden/Empfangen verursacht?

Wodurch kommen solche Probleme immer wieder zustande?

Wäre echt lieb, wenn mir jemand weiterhelfen könnte (sogar mein Übungsleiter, ein Dipl.Inf. hat sich an meinem Problem die Zähne ausgebissen )

Danke an alle, die sich wenigstens die Mühe machen, mein Problem mal anzuschauen!

MfG,
lacyuu


(Diese Frage mit Quelltext hatte ich schon in nem anderen Forum gepostet, wo aber nicht so viel los ist)


----------



## SlaterB (11. Jun 2009)

wer ist denn der Server, steht der unter deiner Kontrolle?
du hast nichts von dem gepostet, vielleicht macht der gar nix,

-----

allgemein:
> nachricht = new Message("");
>              ObjectInputStream input= new ObjectInputStream(socket.getInputStream());
>              nachricht = (Message)input.readObject();

wieso unnötig eine leere Message erzeugen, 
nachricht = null;
ginge genauso oder die Zeile komplett weglassen

> public void Darstellung(Message message){

nie Methoden oder Variablen groß schreiben

> while(true){
>         System.out.print("Nachricht eingeben: ");
>       message.nachrichtschreiben(in.readLine());
>      send.writeObject(message);

ObjectOutputStreams können dazu neigen, einmal gesendete Objekte nicht nochmal zu senden,
oder nur einen Marker in den Stream zu legen 'das bekannte Objekt 5 hier nochmal',

immer neue Objekte reinschreiben oder
stream.reset() benutzen


----------



## lacyuu (11. Jun 2009)

Gut, dann also noch der Server:



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

public class Server {

                Vector clientliste;        //erstellen einer Liste, in der alle angemeldeten Clients registriert werden
            Message message;
            User serveruser;       //da Nachrichten sich über User identifizieren lassen, wird ein Serveruser für Systemmeldungen angelegt
            Message servermessage;
            Message serverbroadcast;       //Nachrichten, die an alle geschickt werden
            ServerSocket serversocket;

Server(){
                this.clientliste = new Vector();        //erstellen einer Liste, in der alle angemeldeten Clients registriert werden
            this.message = new Message("");
            this.serveruser = new User("Server Message", "");       //da Nachrichten sich über User identifizieren lassen, wird ein Serveruser für Systemmeldungen angelegt
            this.servermessage = new Message("Anmeldung erfolgreich, wilkommen auf dem Server. \n Sie können Nachrichten an andere User schreiben. (verlassen mit 'quit')", serveruser);     //Nachrichten, die an einzelnen User gehen
            this.serverbroadcast = new Message("", serveruser);       //Nachrichten, die an alle geschickt werden
        try {
            this.serversocket = new ServerSocket(12345);

        } catch (IOException e) {
            System.err.println(e);
}
}
    

    public void runsocket(Server server) throws IOException {
        try {

            System.out.println("Server is running...");

            while (true) {
                Socket ssocket = serversocket.accept();       //Server horcht Leitung ab
                    

                LoginThread thread = new LoginThread(ssocket,server);      //Thread für diesen Client wird angelegt
                thread.start();

            }
        } catch (IOException e) {
        }
    }

    public static void main(String[] args) {



        try {
            Server server = new Server();


            server.runsocket(server);
        } catch (IOException e) {
            System.err.println(e);
        }
    
    }}
```

der macht natürlich nicht viel, das erledigt der Thread LoginThread für ihn:


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

public class LoginThread extends Thread {

    Socket socket;
    User user;
    Server server;

    LoginThread(Socket socket,Server server) {

        this.socket = socket;
        this.user = null;
        this.server = server;

    }

    public boolean login() {       //Methode, die den eingehender User mit den bereits vorhandenen Usern vergleicht und Passwörter überprüft
        try {
            ObjectInputStream input = new ObjectInputStream(socket.getInputStream());
            ObjectOutputStream output = new ObjectOutputStream(socket.getOutputStream());
            PrintWriter out = new PrintWriter(output);


            user = (User) input.readObject();
            User usercheck = new User();
            user.printUser();
            boolean check = false;;


            if (server.clientliste.isEmpty()) {      //Bisher noch kein Client angemeldet
                check = true;
            }
            else{
            for (int i = 0; i < server.clientliste.size()&&check==true; i++) {       //schrittweise überprüfen der liste nach keys
                usercheck = ((LoginThread) server.clientliste.get(i)).user;
                if (user.name.equals(usercheck.name)) {       //überprüfen ob Name schon vorhanden ist
                    if (user.passwort.equals(usercheck.passwort)) {   //Prüfen, ob passwort übereinstimmt

                      check = true;
                    } else {
                        out.println("User " + user.name + " existiert bereits. Passwort für User " + user.name + " ist falsch. Geben Sie das korrekte Passwort ein oder melden Sie sich mit einem anderen Namen an.");
                       
                    }
                } else {
    }
                }
            
            check = true;}
            //Name existiert noch nicht

return check;


        } catch (IOException e) {
        } catch (ClassNotFoundException f) {
            System.out.println("Datenpaket hatte das falsche Format.");
        }
        return true;
    }

    @Override
    public void run() {       

        boolean check = false;
        boolean close = false;
        
                try {
            ObjectInputStream input = new ObjectInputStream(socket.getInputStream());
            ObjectOutputStream output = new ObjectOutputStream(socket.getOutputStream());
            PrintWriter out = new PrintWriter(output);


            user = (User) input.readObject();
            User usercheck = new User();
            user.printUser();



            if (server.clientliste.isEmpty()) {      //Bisher noch kein Client angemeldet
                check = true;
            }
            else{
            for (int i = 0; i < server.clientliste.size()&&check==false; i++) {       //schrittweise überprüfen der liste nach keys
                usercheck = ((LoginThread) server.clientliste.get(i)).user;
                if (user.name.equals(usercheck.name)) {       //überprüfen ob Name schon vorhanden ist
                    if (user.passwort.equals(usercheck.passwort)) {   //Prüfen, ob passwort übereinstimmt

                      check = true;
                    } else {
                        out.println("User " + user.name + " existiert bereits. Passwort für User " + user.name + " ist falsch. Geben Sie das korrekte Passwort ein oder melden Sie sich mit einem anderen Namen an.");
                        check = false;
                    }
                } else {
    }
                }
            check = true;}
            //Name existiert noch nicht

                }catch(IOException e){}
                    catch(ClassNotFoundException f){}
     if(check){   
         Message nachricht = new Message("",user);
         send(server.servermessage);
         for(int i=0;i<server.clientliste.size();i++){
             nachricht.nachrichtschreiben(((LoginThread)server.clientliste.elementAt(i)).user.name);
             send(nachricht);
         }
        try {
            ObjectInputStream input = new ObjectInputStream(socket.getInputStream());

                        while(!close){
            nachricht = (Message) input.readObject();
            System.out.println(nachricht.msg);

            
            sendall(nachricht);
            
            
            }
        } catch (IOException e) {
        } catch (ClassNotFoundException f) {
            System.out.println("Datenpaket hatte das falsche Format.");
        }
        
    }
                
    }

    public void send(Message nachricht) {        //Methode zum Senden von Nachrichten an einen Clienten
        try {
            System.out.println("Bereit zum Senden!!");
                        System.out.println(nachricht.msg);
            ObjectOutputStream paketsenden = new ObjectOutputStream(socket.getOutputStream());

            paketsenden.writeObject(nachricht);
            paketsenden.flush();
            System.out.println("Paket ist raus");
        } catch (IOException e) {
        }
    }
    public void sendall(Message nachricht){
        
                 
                            for (int i = 0; i < server.clientliste.size(); i++) {        //Nachricht wird an alle angemeldetes Clients verschickt
                        ((LoginThread) server.clientliste.elementAt(i)).send(nachricht);
                    }
    }
}
```

Ist noch nicht alles ganz fertig, was die Funktionen betrifft, aber bevor man mit etwas arbeiten kann, muss ja erstmal der Datenstrom funktionieren.


----------



## SlaterB (11. Jun 2009)

du solltest auf jeder Seite maximal genau einen ObjectInputStream/ OutputStream auf die Socket-Streams legen,
nicht teilweise pro Nachricht neu..,

jeder ObjectOutputStream schreibt neben seinen Objekten auch noch spezielle Markierungen wie 'Begin der Datei' usw.,
das mehrmals durcheinander endet nur im Chaos,

   PrintWriter  über ObjectOutputputStream ist auch ausgeschlossen,
wenn ObjectOutputStream, dann sende dort Strings als Objekte

----
tausende Untermethoden, Listen von Nachrichten usw. machen alles unnötig kompliziert,
übe ersteinmal, eine einfache Kommunikation aufzubauen, der Server sollte z.B. nichts weiter tun, als die empfangenen Objekte zurückzusenden, vielleicht noch erweitert um die Info 'habe ich gelesen'


----------



## lacyuu (11. Jun 2009)

Okay, ich habe die Streams auf jeder Seite radikal auf jeweils zwei (Input/Output) reduziert und endlich kommt was beim Client an.
Jetz hapert's nur noch an dem Verschicken an die anderen User, aber ich glaube, die Lösung dafür liegt darin, endlich Ordnung im Programm zu machen.

Ich weiß selbst, dass mein Programmtext ziemlich undurchsichtig ist, das liegt aber daran, dass ich dieses Programm ziemlich bald vorstellen muss, und wenn schon nichts läuft, soll man wenigstens mein Vorgehen im Programmtext nachverfolgen können. 

Vielen Dank auf jeden Fall für die vielen Ratschläge.


----------

