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?