Hallo zusammen,
ich muss für eine Übung einen Chat mit RMI programmieren. Wir haben 2 Interfaces gegeben:
ChatService:
und ClientService:
Dazu sollen wir eine Klasse ChatServer schreiben. Meine sieht bisher so aus:
Zum Schluss sollen wir die Klasse ChatClient schreiben. Bei mir enthält Sie außerdem eine GUI:
Das Programm läuft folgendermaßen ab (Eingaben werden mit Strg+Enter abgesendet):
Das Problem ist, dass ich keine Nachrichten verschicken kann. An- und abmelden funktioniert, aber wenn ich eine Nachricht verschicke, versucht der Server diese auszugeben. Zum verschicken rufe ich auf dem Server die Methode
auf. Diese geht die Liste der angemeldeten Clients durch und ruft bei jedem Client die gleichnamige Methode
auf. Die
Methode vom Client soll die übermittelte Nachricht in einer JTextArea ausgeben. Allerdings erscheinen auf der Konsole vom Server die Meldungen, dass eine Nachricht eingegangen ist (Ich habe einfach ein paar Meldungen über sysout zur Kontrolle eingebaut).
Ich hoffe ihr könnt mir sagen wo der Denkfehler ist oder ob ich da komplett falsch rangehe, ich stehe da ganz schön auf dem Schlauch...
Ich habe außerdem den src ordner aus meinem eclipse Projekt bei mediafire hochgeladen, falls ihr damit einen besseren Einblick bekommt.
Danke schon einmal im Voraus!
ich muss für eine Übung einen Chat mit RMI programmieren. Wir haben 2 Interfaces gegeben:
ChatService:
Java:
package com.jchat.interfaces;
import java.rmi.Remote;
import java.rmi.RemoteException;
import java.util.List;
public interface ChatService extends Remote {
void register(ClientService cs) throws RemoteException;
void unregister(ClientService cs) throws RemoteException;
void message(String name, String msgs) throws RemoteException;
List<String> getUserList() throws RemoteException;
}
und ClientService:
Java:
package com.jchat.interfaces;
public interface ClientService {
void message(String name, String msg);
String getName();
void updateClients();
}
Dazu sollen wir eine Klasse ChatServer schreiben. Meine sieht bisher so aus:
Java:
package com.jchat.server;
import java.net.MalformedURLException;
import java.rmi.Naming;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;
import java.util.ArrayList;
import java.util.List;
import com.jchat.interfaces.ChatService;
import com.jchat.interfaces.ClientService;
public class ChatServer extends UnicastRemoteObject implements ChatService {
private List<ClientService> clients;
protected ChatServer() throws RemoteException {
super();
this.clients = new ArrayList<ClientService>();
}
/**
*
*/
private static final long serialVersionUID = 918273645L;
@Override
public void register(ClientService cs) throws RemoteException {
this.clients.add(cs);
System.out.println("Client " + cs.getName() + " has connected");
for (ClientService client : clients) {
client.updateClients();
}
}
@Override
public void unregister(ClientService cs) throws RemoteException {
this.clients.remove(cs);
System.out.println("Client " + cs.getName() + " has disconnected");
for (ClientService client : clients) {
client.updateClients();
}
}
@Override
public void message(String name, String msg) throws RemoteException {
System.out.println(name + ": " + msg);
for (ClientService client : this.clients) {
client.message(name, msg);
}
}
@Override
public List<String> getUserList() throws RemoteException {
List<String> clientNames = new ArrayList<String>();
for (ClientService client : this.clients) {
clientNames.add(client.getName());
}
return clientNames;
}
public static void main(String[] args) {
try {
//rmiregistry starten
LocateRegistry.createRegistry(Registry.REGISTRY_PORT);
System.out.println(LocateRegistry.getRegistry());
Naming.rebind("chat", new ChatServer());
System.out.println("Server started");
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Zum Schluss sollen wir die Klasse ChatClient schreiben. Bei mir enthält Sie außerdem eine GUI:
Java:
package com.jchat.client;
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.io.Serializable;
import java.net.MalformedURLException;
import java.rmi.Naming;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import javax.swing.AbstractAction;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.KeyStroke;
import javax.swing.ScrollPaneConstants;
import com.jchat.interfaces.ChatService;
import com.jchat.interfaces.ClientService;
public class ChatClient extends JFrame implements ClientService, Serializable {
/**
*
*/
private static final long serialVersionUID = 6574839201L;
private String name;
private ChatService remote;
//GUI Elemente
private JScrollPane jScrollPane1;
private JScrollPane jScrollPane2;
private JTextArea chat;
private JTextArea users;
private JPanel textPanes;
private JTextField cmdLine;
private DateFormat df;
private boolean fl;
private boolean connected;
//
public ChatClient() {
super("jChat");
this.df = new SimpleDateFormat("HH:mm");
this.fl = true;
this.connected = false;
this.name = "";
initGUI();
new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
}
}).start();
}
@Override
public void message(String name, String msg) {
System.out.println("client message");
this.chat.append(printLine(name, msg));
}
@Override
public String getName() {
return this.name;
}
private void connect(String ip) {
try {
this.remote = (ChatService) Naming.lookup("//" + ip + "/chat");
this.remote.register(this);
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NotBoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
this.connected = true;
}
}
private void disconnect() {
try {
this.remote.unregister(this);
this.connected = false;
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private void initGUI() {
// Frame Layout setzen
this.setLayout(new BorderLayout());
// Komponenten initilisieren
this.chat = new JTextArea(
printLine("jChat", "Welcome to jChat")
+ printLine("jChat",
"Following commands are available:")
+ printLine("jChat",
"$nickname <YourPrefferedName> (No spaces!)")
+ printLine("jChat",
"$connect <IP> (Server must run jChat)")
+ printLine("jChat", "$disconnect")
+ printLine("jChat",
"You can connect to a Server if you have set a nickname")
+ printLine("jChat",
"Press <Ctrl+Enter> to submit your input")
+ printLine("jChat", "Let's start with your nickname"),
20, 40);
this.users = new JTextArea("Users", 20, 15);
this.jScrollPane1 = new JScrollPane(this.chat);
this.jScrollPane2 = new JScrollPane(this.users);
this.cmdLine = new JTextField(50);
this.textPanes = new JPanel(new BorderLayout());
this.chat.setEditable(false);
this.chat.setLineWrap(true);
this.chat.setWrapStyleWord(true);
this.users.setEditable(false);
this.jScrollPane1
.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
this.jScrollPane2
.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
this.cmdLine.getInputMap().put(KeyStroke.getKeyStroke("control ENTER"),
"send");
this.cmdLine.getActionMap().put("send", new AbstractAction("send") {
/**
*
*/
private static final long serialVersionUID = 1L;
public void actionPerformed(ActionEvent evt) {
parseInput();
}
});
// Komponenten zusammensetzen
this.textPanes.add(this.jScrollPane1, BorderLayout.LINE_START);
this.textPanes.add(this.jScrollPane2, BorderLayout.LINE_END);
this.add(this.textPanes, BorderLayout.PAGE_START);
this.add(this.cmdLine, BorderLayout.PAGE_END);
// Frame anzeigen
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setResizable(false);
this.pack();
this.setVisible(true);
}
private void parseInput() {
String input = this.cmdLine.getText();
if (!input.isEmpty()) {
if (input.startsWith("$nickname")) {
String[] splittedInput = input.split(" ");
if (splittedInput.length == 2 && this.name.isEmpty()) {
this.name = splittedInput[1];
this.chat.append(printLine("jChat", "So you are "
+ this.name));
}
if (splittedInput.length == 1) {
this.chat.append(printLine("jChat",
"You have to submit your name"));
}
if (splittedInput.length > 2) {
this.chat.append(printLine("jChat",
"You can only have one name"));
}
} else if (input.startsWith("$connect")) {
String[] splittedInput = input.split(" ");
if (splittedInput.length == 2 && !this.name.isEmpty() && !this.connected) {
connect(splittedInput[1]);
this.chat.append(printLine("jChat", "Ready to go"));
}
if (splittedInput.length == 1) {
this.chat.append(printLine("jChat",
"You have to submit an IP address"));
}
if (splittedInput.length > 2) {
this.chat.append(printLine("jChat",
"This is not an IP address"));
}
} else if (input.startsWith("$disconnect") && this.connected) {
disconnect();
} else if (this.connected) {
try {
this.remote.message(this.name, input);
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} else {
this.chat.append(printLine("jChat",
"I don't know what to do. Specify your request"));
}
}
this.cmdLine.setText("");
}
private String printLine(String name, String message) {
if (this.fl) {
this.fl = false;
return name + " (" + df.format(new Date()) + "):\t" + message;
} else {
return "\n" + name + " (" + df.format(new Date()) + "):\t"
+ message;
}
}
public static void main(String[] args) {
new ChatClient();
}
@Override
public void updateClients() {
try {
List<String> clients = this.remote.getUserList();
this.users.setText("Users:");
for (String client : clients) {
this.users.append("\n" + client);
}
System.out.println("Clients have been updated");
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Das Programm läuft folgendermaßen ab (Eingaben werden mit Strg+Enter abgesendet):
- Man muss mit $nickname <nickname> einen Name festlegen
- Man muss sich mit $connect <IP> zum Server verbinden
- Danach soll man Nachrichten verschicken können
- Mit $disconnect kann man die Verbindung trennen
Das Problem ist, dass ich keine Nachrichten verschicken kann. An- und abmelden funktioniert, aber wenn ich eine Nachricht verschicke, versucht der Server diese auszugeben. Zum verschicken rufe ich auf dem Server die Methode
Code:
message()
Code:
message()
Code:
message()
Ich hoffe ihr könnt mir sagen wo der Denkfehler ist oder ob ich da komplett falsch rangehe, ich stehe da ganz schön auf dem Schlauch...
Ich habe außerdem den src ordner aus meinem eclipse Projekt bei mediafire hochgeladen, falls ihr damit einen besseren Einblick bekommt.
Danke schon einmal im Voraus!