Chat-Programm

Tach!

Bis jetzt habe ich ein Chat-Programm erstellt und dies besteht aus vier Klassen, die hier folgen:

ChatClientFrame.java

import java.awt.event.ActionEvent;
import java.awt.event.InputEvent;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.rmi.UnknownHostException;

import javax.swing.*;


public class ChatClientFrame extends JFrame {
	
	// Status-Zeile
	JTextField jtfEingabe;
	
	Container contentPane;
	
	// Menü-Objekte
	JMenuBar menuBar;
	JMenu menuOP, menuHelp;
	JMenuItem jmiClose, jmiConnect, jmiDisconnect, jmiHelp, jmiAbout;
	
	// Toolbar-Objekte
	JToolBar toolbar;
	JButton jbtClose, jbtConnect, jbtDisconnect, jbtHelp, jbtAbout;
	private String iconSize = "16";
	
	// Action-Objekte
	private Action actClose, actConnect, actDisconnect, actHelp, actAbout;
	
	// Toolbar-ToolTips
	private final String TTT_CLOSE = "Schließen";
	private final String TTT_CONNECT = "Verbinden";
	private final String TTT_DISCONNECT = "Trennen";
	private final String TTT_HELP = "Hilfe - Suche nach einer Lösung";
	private final String TTT_ABOUT = "Information über das Chat-Programm";
	
	// Tastaturkommando
	private KeyStroke keyStroke;
	
	// HTML-formatierten Text
	JEditorPane editorPane;
	
	// Für Hilfe und Info
	JLayeredPane desktop;
	
	Socket clientSocket;
	BufferedReader serverIn;
	PrintWriter serverOut;
	ClientInputThread inputThread;
	
	public static String host = "localhost";
	public static int port = 4444;
	private static String user = "Anonymus";
	
	public ChatClientFrame(String host, int port, String user) { 
		super("Chat-Client von "+user);
		setSize(600, 450);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		contentPane = this.getContentPane();
		
		// Statusfeld
		jtfEingabe = new JTextField("");
		jtfEingabe.addKeyListener(new KeyAdapter() {
			public void keyPressed(KeyEvent ke) {
				// bei Enter Text übermitteln
				if(ke.getKeyCode() == KeyEvent.VK_ENTER) {
					String text = jtfEingabe.getText().trim();
					if(text.length() > 0) {
						if(serverOut != null) {
							serverOut.println(text);
							// Eingabefeld wieder löschen
							jtfEingabe.setText("");
						} else {
							jtfEingabe.setText("Zunächst "
								+"Verbindung zu einem Server herstellen!");
						}
					} else {
						jtfEingabe.setText("Bitte Text eingeben!");
					}
				}
			}
		});
		
		JPanel panel = new JPanel();
		panel.setLayout(new BorderLayout());
		panel.add(BorderLayout.SOUTH, jtfEingabe);
		
		editorPane = new JEditorPane();
		editorPane.setContentType("text/html");
		JScrollPane editorSP = new JScrollPane(editorPane);	
		panel.add(BorderLayout.CENTER, editorSP);
		contentPane.add(BorderLayout.CENTER, panel);
		
		menu();
		tbar();
		setVisible(true);
		
	}
	
	private void menu() {
		
		// Menübar
		menuBar = new JMenuBar();
		this.setJMenuBar(menuBar);
		
		// Menü
		menuOP = new JMenu("Operationen");
		menuOP.setMnemonic('p');	
		
		// Schließen
		actClose = new AbstractAction("Schließen", new ImageIcon("images/Stop"+iconSize+".gif"))
		{
			public void actionPerformed(ActionEvent ae) {
				jtfEingabe.setText("\"Schließen\" gewählt");
			}
		};
		keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_S, InputEvent.CTRL_MASK);
		actClose.putValue(Action.ACCELERATOR_KEY, keyStroke);
		actClose.putValue(Action.SHORT_DESCRIPTION, TTT_CLOSE);
		jmiClose = menuOP.add(actClose);
		jmiClose.setMnemonic('s');			
		
		// Verbinden
		actConnect = new AbstractAction("Verbinden", new ImageIcon("images/Import"+iconSize+".gif"))
		{
			public void actionPerformed(ActionEvent ae) {
				connectServer();
			}
		};
		keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_V, InputEvent.CTRL_MASK);
		actConnect.putValue(Action.ACCELERATOR_KEY, keyStroke);
		actConnect.putValue(Action.SHORT_DESCRIPTION, TTT_CONNECT);
		jmiConnect = menuOP.add(actConnect);
		jmiConnect.setMnemonic('v');
		
		// Trennen
		actDisconnect = new AbstractAction("Trennen", new ImageIcon("images/Export"+iconSize+".gif"))
		{
			public void actionPerformed(ActionEvent ae) {
				if(clientSocket != null)
					disconnectServer();
				System.exit(0);
				jtfEingabe.setText("\"Trennen\" gewählt");
			}
		};
		keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_T, InputEvent.CTRL_MASK);
		actDisconnect.putValue(Action.ACCELERATOR_KEY, keyStroke);
		actDisconnect.putValue(Action.SHORT_DESCRIPTION, TTT_DISCONNECT);
		jmiDisconnect = menuOP.add(actDisconnect);
		jmiDisconnect.setMnemonic('t');
		
		menuBar.add(menuOP);	
		
		// Menü - Hilfe
		menuHelp = new JMenu("Hilfe");
		menuHelp.setMnemonic('H');	
		
		// Hilfe
		actHelp = new AbstractAction("Hilfe", new ImageIcon("images/Help"+iconSize+".gif"))
		{
			public void actionPerformed(ActionEvent ae) {
				showHelp();
				jtfEingabe.setText("\"Hilfe\" gewählt");
			}
		};
		keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_H, InputEvent.CTRL_MASK);
		actHelp.putValue(Action.ACCELERATOR_KEY, keyStroke);
		actHelp.putValue(Action.SHORT_DESCRIPTION, TTT_HELP);
		jmiHelp = menuHelp.add(actHelp);
		jmiHelp.setMnemonic('h');		
		
		// Info
		actAbout = new AbstractAction("Info", new ImageIcon("images/About"+iconSize+".gif"))
		{
			public void actionPerformed(ActionEvent ae) {
				showInfo();
				jtfEingabe.setText("\"Info\" gewählt");
			}
		};
		keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_I, InputEvent.CTRL_MASK);
		actAbout.putValue(Action.ACCELERATOR_KEY, keyStroke);
		actAbout.putValue(Action.SHORT_DESCRIPTION, TTT_ABOUT);
		jmiAbout = menuHelp.add(actAbout);
		jmiAbout.setMnemonic('h');
		
		menuBar.add(menuHelp);
		
	}	
	private void tbar() {
		toolbar = new JToolBar();
		jbtClose = toolbar.add(actClose);
		jbtConnect = toolbar.add(actConnect); 
		jbtDisconnect = toolbar.add(actDisconnect);
		toolbar.addSeparator();
		jbtHelp = toolbar.add(actHelp);
		jbtAbout = toolbar.add(actAbout);
		
		//Toolbar im ChatClientFrame hinzufügen
		contentPane.add(BorderLayout.NORTH, toolbar);
	}	
	// Fenster "Hilfe"
	public void showHelp() {
		// JInternalFrame erzeugen
		JInternalFrame help = new JInternalFrame("Hilfe", 
				true, // resizable  => nicht maximieren
				true); // closeable => Schließen aktivieren
		help.setSize(400, 325);	
		
		// Zentrieren
		int x = (contentPane.getWidth() - help.getWidth())/2;
		int y = (contentPane.getHeight() - help.getHeight())/2;		
		help.setLocation(x,y);		
			
		help.setDefaultCloseOperation(JInternalFrame.DISPOSE_ON_CLOSE);
		desktop = new JLayeredPane();
		desktop = getLayeredPane();
		desktop.add(help);
		
		//Text im Fenster "Hilfe"
		String text = "<html>Dies ist ein <b>Hilfetext</b> zum Chat-Programm.</html>";
		JTextPane helpText = new JTextPane();
		helpText.setContentType("text/html");
		helpText.setText(text);
	    // Wird nicht editiert, der Text wird nur angezeigt
		helpText.setEditable(false);
		
		// Scrollen
		help.add(new JScrollPane(helpText));
		
		help.setVisible(true);
	}	
	// Fenster "Info"
	public void showInfo() {
		JInternalFrame info = new JInternalFrame("Info", true, true);
		info.setSize(300, 200);
		
		// Zentrieren
		int x = (contentPane.getWidth() - info.getWidth())/2;
		int y = (contentPane.getHeight() - info.getHeight())/2;		
		info.setLocation(x,y);
		
		// Unveränderte Größe
		info.setResizable(false);
		
		//Text im Fenster "Info"
		String text = "<html><center><h2>Chat-Programm</h2><br />" +
				"<b>Autor: </b>Judith Klute<br />" +
				"<b>Version: </b>02.06.2010<br />" +
				"<b>Projekt: </b>Lernheft JAV07N<br />" +
				"<b>Abschnitt: </b>Einsendeaufgaben</html>";
		JTextPane infoText = new JTextPane();
		infoText.setContentType("text/html");
		infoText.setText(text);
		infoText.setEditable(false);
		info.add(infoText);
		
		info.setDefaultCloseOperation(JInternalFrame.DISPOSE_ON_CLOSE);
		desktop = new JLayeredPane();
		desktop = getLayeredPane();
		desktop.add(info, new Integer(300)); // new Integer (300) entspricht POPUP-LAYER
		info.setVisible(true);
	}
		private void connectServer() {
		try {
			clientSocket = new Socket(host, port);
			serverIn = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
			serverOut = new PrintWriter(clientSocket.getOutputStream(), true);
			
			// Benutzername an Server:
			serverOut.println(user);
			inputThread = new ClientInputThread(editorPane, serverIn);
			inputThread.start();
			jtfEingabe.setText("");
		} catch (UnknownHostException uhe) {
			System.out.println("*** "+uhe.toString());
			System.exit(-1);
		} catch (IOException ioe) {
			System.out.println("*** "+ioe.toString());
			System.exit(-1);
		}
	}	
	private void disconnectServer() {
		serverOut.println("exit");
		inputThread = null;
		try {
			serverIn.close();
			serverOut.close();
			clientSocket.close();
		} catch (IOException ioe) {
			System.out.println("*** "+ioe.toString());
		}
	}	
	public static void main(String[] args) {
		new ChatClientFrame(host, port, user);
	}	

}

ChatServer.java

import java.net.*;
import java.util.Iterator;
import java.util.LinkedList;

public class ChatServer extends Thread {
	
	private Socket clientSocket;
	private ServerSocket serverSocket;
	private static int port = 4444;
	
	protected LinkedList threadList = new LinkedList();
	private Iterator iterator;
	
	static StringBuffer sb;
	static char c;
	static String ausgabe;
	
	public static void main(String[] args) {
		if(args.length == 1) {
			try {
				port = Integer.parseInt(args[0]);
			} catch (NumberFormatException nfe) {
				System.out.println("Ungültige Port-Angabe");
			}
		}
		ChatServer server = new ChatServer();
		server.init();
		server.start();
		server.closeAll();
		
		while(true) {
			sb = new StringBuffer();
			try {
				Reader in = new InputStreamReader(System.in);
				while((c = (char)in.read()) != '\r') {
					sb.append(c);
				}
			} catch (IOException ioe) {
				System.out.println(ioe.toString());
			}
			ausgabe = sb.toString();
			if(ausgabe.equals("exit")) {
				server.closeAll();
			} else
				System.out.println("\""+ausgabe+"\" wird nicht ausgewertet");
		}
	}
	
	public void init() {
		try {
			serverSocket = new ServerSocket(port);
			System.out.println("Server horcht an port "+port);
		} catch (IOException ioe) {
			System.out.println(ioe.toString());
		}
		try {
			clientSocket = serverSocket.accept();
			System.out.println("Verbindung zu Socket " +clientSocket.getRemoteSocketAddress()
					+" aufgenommen");
			ClientThread clientThread = new ClientThread(clientSocket, this);
			Thread thread = new Thread(clientThread, clientThread.getThreadName());
			threadList.add(clientThread);
			thread.start();
		} catch (IOException ioe) {
			System.out.println(ioe.toString());
		}
	}
	
	public void closeAll() {
		// die Stream werden in den ClientThread-Objekten
		// geschlossen
		try {
			serverSocket.close();
		} catch (IOException ioe) {
			System.out.println(ioe.toString());
		}
	}
	
	public void generateOutput(String output) {
		iterator = threadList.iterator();
		while(iterator.hasNext()) {
			ClientThread thread = (ClientThread) iterator.next();
			thread.output(output);
		}
	}
}```
ClientInputThread.java
```import java.awt.*;
import java.io.BufferedReader;
import java.io.IOException;

import javax.swing.JEditorPane;

public class ClientInputThread extends Thread {
	private StringBuffer editorString;
	private BufferedReader serverIn;
	private JEditorPane editorPane;
	
	public ClientInputThread(JEditorPane editorPane, BufferedReader serverIn) {
		this.editorPane = editorPane;
		this.serverIn = serverIn;
	}
	
	public void run() {
		editorPane.setText("<b>Beendigung des Chats "
				+"über den Button \"Disconnect\"</b>");
		String fromServer, fromEditor;
		int beginIndex, endIndex;
		Rectangle rect;
		try { // readLine kann Exception werfen
			while((fromServer = serverIn.readLine()) != null) {
				if(fromServer.equals("exit")) {
					break;
				}
				fromEditor = editorPane.getText();
				beginIndex = fromEditor.indexOf("<body>")+6;
				endIndex = fromEditor.indexOf("</body>");
				editorString = new StringBuffer(
						fromEditor.substring(beginIndex, endIndex));
				editorString.append("<br>"+fromServer);
				editorPane.setText(editorString.toString());
				// an die untere Kante scrollen
				rect = new Rectangle(new Point(0, editorPane.getSize().height));
				editorPane.scrollRectToVisible(rect);
			}
		} catch (IOException ioe) {
			System.out.println(ioe.toString());
		}
	}
}```
ClientThread.java
```import java.io.*;
import java.net.Socket;


public class ClientThread implements Runnable {

  private ChatServer parent;
  private Socket clientSocket;
  private BufferedReader clientIn;
  private PrintWriter serverOut;

  private String threadName;

  public String getThreadName() {
    return threadName;
  }

  public ClientThread(Socket clientSocket, ChatServer parent) {
    this.parent = parent;
    this.clientSocket = clientSocket;
    try {
      clientIn = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
      serverOut = new PrintWriter(clientSocket.getOutputStream(), true);

      // Die erste Meldung soll der Benutzername sein!
      threadName = clientIn.readLine();
      serverOut.println("SERVER: Connection von " +threadName+ " angenommen");

    } catch (IOException ioe) {
      System.out.println("ClientThread-Konstruktor: "+ioe.toString());
    }
  }

  public void run() {
    try {
      String fromClient;
      while((fromClient = clientIn.readLine()) != null) {
        if(fromClient.equals("exit")) {
          output(fromClient);

          // die Streams schließen
          clientIn.close();
          serverOut.close();

          //while-Schleife abbrechen:
          break;

        } else
            //output("<b>"+getThreadName()+":</b> "+fromClient);
        	parent.generateOutput("<b>"+getThreadName()+":</b> "+fromClient);
      }
    } catch (IOException ioe) {
      System.out.println("ClientThread-run: "+ioe.toString());
      try {
    	  Thread.sleep(100);
      } catch (InterruptedException ie) {
    	  
      }
    }
  }

  public void output(String output) {
    System.out.println("Output an: "+clientSocket.getPort());
    serverOut.println(output);
  }

}```

1. Problempunkt:
Diese Daten habe ich kompiliert. Es ist eigentlich fehlerfrei.
1. Schritt: ChatServer starten, so dass er sich meldet: "Server horcht an Port 4444".
2. Schritt: Zweite CMD - ChatClientFrame starten mit "java ChatClientFrame localhost, 4444, yampi" 
3. Schritt: Klick auf Connect-Button - Erfolgmeldung erscheint im Fenster. 
4. Schritt: Nach Belieben einen Text im Status (= jtfEingabe) eingeben

5. Schritt: "Exit" eingeben und mit Eingabetaste ("Enter") bestätigen, so dass der Server seine Arbeit beendet. 
6. Klick auf Close-Button, um den Client zu schließen.

Bei mir funktioniert 5. Schritt nicht. *grübel*

2. Problempunkt: 
In diesem Projekt sollen mehrere Chats sein - bei mir geht es nicht. Wenn ich zweite CMD aufrufe
und ChatClientFrame (siehe wie oben beschrieben) starten lasse, ist das Fenster da. Und danach wenn ich 
dritte und mehrere CMDs aufrufe und ChatClientFrame starte, wird 1. Fenster nun verschwunden. Woran 
kann es liegen? Kann es in der Code nicht korrekt sein? *grübel*

Könnt Ihr vielleicht was fehlerhaftes herausfinden?
  1. Was soll denn die while-Schleife in der main vom ChatServer bewirken? Die sollte man nicht brauchen, und wenn man die rausnimmt, scheint es (bei mir, lokal) zu funktionieren.

  2. Wenn man mehrere Clients aufmachen will, muss man auch mehrere “CMD-Fenster” (Eingabeaufforderungen) aufmachen, und dort dann jeweils einen neuen Client starten. Dann ging das hier auch erstmal. Allerdings konnte sich erstmal immer nur einer verbinden … vielleicht hat ein Netzwerk-Experte da eine Idee, wenn nicht, muss man nochmal genauer schauen.

Zu 1. Das geht wieder! Ich muß nachdenken, wo ich eine While-Schleife einfügen soll.

			sb = new StringBuffer();
			try {
				Reader in = new InputStreamReader(System.in);
				while((c = (char)in.read()) != '\r') {
					sb.append(c);
				}
			} catch (IOException ioe) {
				System.out.println(ioe.toString());
			}
			ausgabe = sb.toString();
			if(ausgabe.equals("exit")) {
				server.closeAll();
			} else
				System.out.println("\""+ausgabe+"\" wird nicht ausgewertet");
		}```
Zu 2. 

> Wenn man mehrere Clients aufmachen will, muss man auch mehrere "CMD-Fenster" (Eingabeaufforderungen) aufmachen, und dort dann jeweils einen neuen Client starten.

Das habe ich x-mal probiert und das funktioniert nicht! Wenn ich mehrer Clients aufmachen will und 
jeweiligen Connect anklicke, wird ein Fenster übrig geblieben und alle Fenstern verschwunden. Das kann ich 
doch nicht begreifen. :mad:
Kann es an Firewall liegen?
  1. Sollte das, was dort in der Schleife gemacht wird, nicht schon durch die Schleife in ClientThread#run erledigt sein?

  2. Mal schrittweise:

  • Erste Eingabeaufforderung aufmachen
  • „java ChatClientFrame 127.0.0.1, 4444, yampi“ eintippen
  • Ein Fenster geht auf. OK
  • Zweite Eingabeaufforderung aufmachen
  • „java ChatClientFrame 127.0.0.1, 4444, yampi“ eintippen
  • Ein Fenster geht auf.
    … und DANN geht automatisch das erste Fenster zu? :confused: Das kann eigentlich kaum sein…:confused:

[QUOTE=Marco13]

  1. Mal schrittweise:
  • Erste Eingabeaufforderung aufmachen
  • „java ChatClientFrame 127.0.0.1, 4444, yampi“ eintippen
  • Ein Fenster geht auf. OK
  • Zweite Eingabeaufforderung aufmachen
  • „java ChatClientFrame 127.0.0.1, 4444, yampi“ eintippen
  • Ein Fenster geht auf.
    … und DANN geht automatisch das erste Fenster zu? :confused: Das kann eigentlich kaum sein…:confused:[/QUOTE]

Das geht ja. Wenn ich auf „Connect“ (=Verbinden) anklicke, geht es auch. Aber wenn ich im zweiten Fenster
auf „Connect“ anklicke, ist zweites Fenster nun verschwunden! Und so weiter… Probier das doch mal!

Ja, wenn der zweite Client sich zu verbinden versucht, wird die Verbindung nicht angenommen, und es fliegt eine Exception - vermutlich geht dann bei dir das Fenster zu - warum, weiß ich gerade nicht, aber das kann man glaub’ ich ignorieren :wink:

Du müßtest sicherstellen, dass der Server auch mehrere Clients akzeptiert. Dazu steht z.B. auf dieser Seite ein bißchen was. Im speziellen: Wenn man in der ChatServer in der Init-Methode

    public void init() {
        try {
            serverSocket = new ServerSocket(port);
            System.out.println("Server horcht an port "+port);
        } catch (IOException ioe) {
            System.out.println(ioe.toString());
        }
        try {
            while (true) // <---------------------------- Diese Schleife
            {
                clientSocket = serverSocket.accept();
                System.out.println("Verbindung zu Socket " +clientSocket.getRemoteSocketAddress()
                        +" aufgenommen");
                ClientThread clientThread = new ClientThread(clientSocket, this);
                Thread thread = new Thread(clientThread, clientThread.getThreadName());
                threadList.add(clientThread);
                thread.start();
            }
        } catch (IOException ioe) {
            System.out.println(ioe.toString());
        }
    }

einfügt, nimmt er die Verbindungen von beliebig vielen Clients an. Aber „richtigen“ Programm sollte man das etwas schöner machen, und da z.B ein Flag einbauen statt while(true) …

Das kann ich immer noch nicht begreifen, glaube,
ich hole mir was nachzuschlagen. :confused:

Was meinst du mit Links?

Dazu steht z.B. auf dieser Seite ein bißchen was.

Edit: Ich suche weitere Beispiele - Server mit mehrerer Clients.
Mal sehen, welches es passt.

Dein Client schließt sich, weil ein System.exit(-1); die Ausführung beendet. (ChatClientFrame: Zeile 282 und 285)

Ist auch klar, wenn man eine Verbindung anschließt und das (aus
dem Versehen) nochmal anklickt, wird die Verbindung abgebrochen
und das Fenster ist verschwunden.

Fast habe ich es endlich hingekriegt!

try {
            while (true) // <---------------------------- Diese Schleife
            {
                clientSocket = serverSocket.accept();
                System.out.println("Verbindung zu Socket " +clientSocket.getRemoteSocketAddress()
                        +" aufgenommen");
                ClientThread clientThread = new ClientThread(clientSocket, this);
                Thread thread = new Thread(clientThread, clientThread.getThreadName());
                threadList.add(clientThread);
                thread.start();
            }
        } catch (IOException ioe) {
            System.out.println(ioe.toString());
        }```
Diese Code habe ich in der run()-Methode, die ich neu erstellt habe, eingefügt.
Dann geht's! ;)

Nun muß ich noch einiges erledigen. Und zwar geht es um Username.

private static String user = „Anonymus“;

public ChatClientFrame(String host, int port, String user) {
super("Chat-Client von "+user);```
Wenn ich ChatClientFrame aufrufe und java ChatClientFrame localhost 4444 yampi eingebe,
steht yampi nicht auf dem Fenster! Mit user = serverIn.readline() habe ich es probiert.
Das funktioniert nicht! Was nun? :frowning:

Die Parameter
ChatClientFrame localhost 4444 yampi
sind das, was in den “args” von der main-Methode ankommt. Man könnte also ganz pragmatisch in der main-Methode von der ChatClientFrame-Klasse ungefähr sowas schreiben wie

public static void main(String[] args) 
{
    if (args.length < 3)
    {
        System.out.println("Drei Parameter erwartet: host port user");
        return;
    }
    int port = 0;
    try
    {
        port = Integer.parseInt(args[1]);    
    }
    catch (NumberFormatException e)
    {
        System.out.println("Das ist kein port: "+args[1]);
        return;
    }
    new ChatClientFrame(args[0], port, args[2]);
}   

Ach ja…eingefügt, kompiliert, gestartet, das funktioniert! :wink:

Aber mit „users“ muß ich los werden. Wie kann ich es machen, wenn ich
z.B. yampi sehe (nach dem ich „java ChatclientFrame localhost 4444 yampi“
eingegeben habe, das gestartet habe)?
Wenn ich irgendeinen Text im Textfeld (jtfEingabe) eingebe, dann sehe
ich „Ananymus: Hallo“. Da soll „yampi: Hallo“ sein.
Ich glaube, das mit „PrintWriter“ hat zu tun, oder? -_-

Ja, in den statischen Variablen im ChatClientFrame stehen ja noch die alten Werte

public static String host = "localhost";
public static int port = 4444;
private static String user = "Anonymus";

public ChatClientFrame(String host, int port, String user) {
    super("Chat-Client von "+user);
   ....

Die könnte man direkt in der main setzen … oder man könnte sie “nicht-static” machen (weil sie eigentlich nicht static sein müssen und auch nicht “public static” sein sollten). Kannst mal schauen ob es mit

// Alle "private" statt "public static"
private String host = "localhost";
private int port = 4444;
private String user = "Anonymus";

public ChatClientFrame(String host, int port, String user) {
    super("Chat-Client von "+user);

    // Hier die übergebenen Werte merken
    this.host = host;
    this.port = port;
    this.user = user;

   ....
    

funktioniert.

Das funktioniert! Super!

Mit


this.host = host;
this.port = port;
this.user = user;

hatte ich mal eingefügt und sah ein, dass es nicht gehen konnte.
Danach habe ich es rausgenommen, weil keine Parameter in der
main-Methode stand. Nun ist es damit vorhanden und somit geht
es doch! Ich wäre knapp darauf gekommen! :o

Vielen Dank, Marco!

Noch einiges muß ich ergänzen. Wenn was problematisch ist,
dann poste ich hier.

      serverOut.println("Keine Teilnahme!");
    } else {
      serverOut.println("Teilnahmern: "+threadName.toString());
    }```
Diese habe ich in der Methode ```public ClientThread(Socket clientSocket, ChatServer parent)```
(in der Klasse ClientThread) eingefügt. Das funktioniert, aber nicht genau. Weil mehrere angemeldete 
Teilnehmern im ChatClientFrame nicht aufgelistet wurden. Immerhin nur eine Teilnahme! Fehlt da etwas?

Vorletzten Beitrag wollte ich editieren. Das geht nicht! Daher muß ich neuen Beitrag aufmachen.

Edit:
Hintergrund:
Aus der ChatServer:

    iterator = threadList.iterator();
    while(iterator.hasNext()) {
      ClientThread thread = (ClientThread) iterator.next();
      thread.output(output);
    }
  }```
Aus der ClientThread und zwar in der Methode **public ClientThread(Socket clientSocket, ChatServer parent)**
```serverOut.println("SERVER: Connection von " +threadName+ " angenommen");```

Eine Methode habe ich erstellt:
```public void chatList() {
	  threadList.addAll(threadList);
  }```
Alle angemeldete Teilnehmern werden aufgelistet. Ich weiß nicht, ob es geht. Muß es mal probieren.

Hast du dazu auch eine Frage? Oder ist das eine Ergänzung zu einem der obigen Beiträge?

Jupp, zu meiner beiden vor- und letzten Beiträge!

Vielleicht solltest du die Frage noch mal genauer stellen. Mir ist nicht klar, was genau die Frage ist.

Aber diese Methode

	  threadList.addAll(threadList);
  }```
sieht komisch aus: Die fügt nur zur Liste alle Elemente hinzu, die schon drin sind. Aus
"A", "B", "C"
würde damit
"A", "B", "C", "A", "B", "C"
?!

Ich versuche, etwas anderes zu formulieren.

Erst fange ich mal an, folgende Schritte zu erklären.

    iterator = threadList.iterator();
    while(iterator.hasNext()) {
      ClientThread thread = (ClientThread) iterator.next();
      thread.output(output);
    }
  }```
Diese Threadliste ist eine Grundlage, um eine eingehende Nachricht an alle
angemeldeten Threads zu verteilen. 

Aus der ClientThread:
```parent.generateOutput("<b>"+getThreadName()+":</b> "+fromClient);```
Diese ist in der run()-Methode. 

Ausgabe:

**yampi:** hallo

Dann will ich dazu ergänzen, dass jedem angemeldeten Besucher alle bereits im
Chat angemeldeten Teilnehmer in der Mitteilung (Begrüßung) des Servers aufge-
listet werden. 

Welche Code (siehe Beitrag von gestern - 21:26) ich angegeben habe, funktioniert
es nicht. 

Die Ausgabe im Fenster soll aussehen:

**Teilnahme:** yampi, meier, muster

Wenn keine Teilnahme im Chat steht, dann soll es aussehen:
**Kein Teilnahme! **

  public void chatList() { 
        threadList.addAll(threadList);
    }```

Das habe ich ausgedacht und probiert. Das geht nicht, denn es ist falsch. Vergiß dieses.

Versteht Ihr es, was ich meine? Wenn nein, versuche ich noch mal anders zu formulieren. :o