Chat Server Problem

KGD92

Mitglied
Hi Leute,
ich bin gerade dabei ein kleines Chat Programm zu schreiben. Der Client funktioniert auch schon so wie er soll, aber ich hab leider ein kleines Problem mit meinem Server. Und zwar empfängt dieser die Nachrichten und verteilt sie an alle andern Nutzer (inklusive des Senders) weiter. Dies funktioniert auch wunderbar, solange nur ein Client angemeldet ist. Sind es aber schon zwei, bekommt der erste seine Nachricht zurück, bei dem zweiten kommt sie allerdings nie an. Wenn ich nun veruche mit dem zweiten Client (der keine Antwort bekam) eine nachricht zu schicken, wird diese zwar versendet, kommt aber bei keinem der beiden Clients an.

Ich poste hier mal meinen Code vom Server

Java:
import java.io.*;
import java.net.*;
import java.util.*;


/**
 *
 * @author kaidoelger
 */


public class server
{

    ArrayList clientOutput;

    public void los ()
    {
        clientOutput = new ArrayList();

        try
        {
            ServerSocket s = new ServerSocket (5000);

            while(true)
            {
                Socket clientSocket = s.accept();
                PrintWriter out = new PrintWriter (clientSocket.getOutputStream());
                clientOutput.add(out);
                System.out.println("Verbindung zu Client Hergestellt");
                Thread t = new Thread (new ClientHandler (clientSocket));
                t.run();
            }
        }
        catch (IOException ex)
        {
            ex.printStackTrace();
        }
    }

    public void sayToAll (String message)
    {
        Iterator it = clientOutput.iterator();

        while (it.hasNext())
        {
               PrintWriter out = (PrintWriter) it.next();
                out.println(message);
                out.flush();
        }
    }

    public class ClientHandler implements Runnable
    {

        BufferedReader in;
        Socket clientSocket;
        
        public ClientHandler (Socket socket)
        {
            try
            {
                clientSocket = socket;
                InputStreamReader stream = new InputStreamReader (clientSocket.getInputStream());
                in = new BufferedReader (stream);
            }
            catch (IOException ex)
            {
                ex.printStackTrace();
            }
        }

        public void run ()
        {
            String message;

            try
            {
                while ((message = in.readLine()) != null)
                {
                System.out.println("Nachricht empfangen");
                sayToAll (message);
                }
            }
            catch (IOException ex)
            {
                ex.printStackTrace();
            }


        }

    }
}

Hier mal der Code vom Client (den Code fürs GUI weggelassen)

Java:
public class client
{

    Socket socket;
    PrintWriter writer;
    BufferedReader reader;
    GUI main;
    String nickname;
    

public void connect () throws UnknownHostException, IOException, InterruptedException
{
    GUIStart start = new GUIStart ();
    wait (2000);
    start.startFrame.setVisible(false);
    GUILogin login = new GUILogin ();
    socket = new Socket ("localhost" , 5000);
    reader = new BufferedReader (new InputStreamReader (socket.getInputStream()));
    writer = new PrintWriter (socket.getOutputStream());
    Thread readerT = new Thread (new readerT ());
    readerT.run();
    
}

public void write ()
{
    if (main.outgoing.getText().length() == 0)
    {
        GUIWarning warning = new GUIWarning ();
    }
    else
    {
    writer.println(nickname + ": " + main.outgoing.getText());
    writer.flush();
    main.outgoing.setText("");
    main.outgoing.requestFocus();
    //TODO: Scrollbar in letzte Zeile setzen
    }
}

public void playJinggle ()
{
    try{
            AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(new File("C:\\Users\\Fahrenheit\\Documents\\NetBeansProjects\\client\\incoming.wav"));
            AudioFormat af     = audioInputStream.getFormat();
            int size      = (int) (af.getFrameSize() * audioInputStream.getFrameLength());
            byte[] audio       = new byte[size];
            DataLine.Info info      = new DataLine.Info(Clip.class, af, size);
            audioInputStream.read(audio, 0, size);

           // for(int i=0; i < 32; i++) {
                Clip clip = (Clip) AudioSystem.getLine(info);
                clip.open(af, audio, 0, size);
                clip.start();
           // }
        }catch(Exception e){ e.printStackTrace(); }
}

public class readerT implements Runnable
{
   public void run ()
   {
       String message;
       String temp;
       try
       {
           while ((message = reader.readLine()) != null)
           {
               temp = main.incoming.getText();
               main.incoming.setText(temp + "\n" + message);
               playJinggle();
           }        
       }
       catch (IOException ex)
       {
           ex.printStackTrace();
       }
   }
}

//Hier kommt der GUI Code

public void exit () throws IOException
{
    reader.close();
    writer.close();
    socket.close();
    System.exit(0);
}

public static void wait (int n)
{
long t0,t1;
t0=System.currentTimeMillis();

do
{
t1=System.currentTimeMillis();
}
while (t1-t0<1000);
}


}

Schonmal danke im Vorraus. Grüße Kai
 
Zuletzt bearbeitet:
Hallo!

Zuallererst ein kleiner Hinweis: Bitte nutze JAVA tags damit der Code korrekt eingefärbt wird.


Was mir sofort ins Auge sticht ist, dass der pro Client erstellte Thread nicht gestartet wird.

Die Thread.run(); Methode führt nur die run(); Methode des Runnables aus.
Es wird also so lange blockiert, bis run() returned.

Dies ist ein sehr häufiger Fehler, der mir auch manchmal passiert...

Du musst die start() Methode des Threads aufrufen, damit er parallel läuft.

Java:
Thread t = new Thread (new ClientHandler (clientSocket));
t.start();

Sollte das nicht dein Problem lösen, sage es bitte, denn ich hab' deinen Servercode nur bis zu dieser Stelle gelesen :p
 
Zuletzt bearbeitet:
Danke für die Lösung, arbeite bei diesem Programm das erste mal mit Threads und ich dachte an einen Übersetzungsfehler im Tutorial :D

Ein kleines Problem habe ich aber noch, könnte mir jemand einen tipp geben, wie ich den Client richtig beende, d.h. die Verbindung zum Server korrekt schließe.

Grüße und besten Dank, Kai
 
Ein kleines Problem habe ich aber noch, könnte mir jemand einen tipp geben, wie ich den Client richtig beende, d.h. die Verbindung zum Server korrekt schließe.

Streams und Sockets haben dafür eine Methode namens close();

Ist auch richtig umgesetzt bei dir.

Auf der Serverseite wird bei dir readLine irgendwann null liefern, oder readLine liefert eine Exception und der Client-thread wird beendet.

Dort solltest duch auch den Socket und die Streams schließen und den clientSocket auch aus der Liste der Empfänger nehmen.

Dazu eignet sich ein finally{} block nach dem catch in deiner run() Methode beim Server.

Beachte, dass auch die close(); Methoden Exceptions werfen können.


Auf der Client-seite solltest vor dem System.exit(0); auch die Ressourcen der offenen Fenster mit dispose() releasen.
 
Zurück