使用 RMI 时 GUI 上不显示文本
Text doesn't appear on GUI while using RMI
我的目标是做一个简单的聊天程序。我是 RMI 的新人。到目前为止我得到的是服务器工作。我启动它。然后我启动客户端,它通过 RMI 将字符串传输到服务器。但是后来它没有出现在我制作的 GUI 上。这就是我的问题所在。
我的 StartClient class。我创建了一个 chatClient,并将 chatServer 存根作为参数。
public StartClient() throws RemoteException, NotBoundException, MalformedURLException {
chatServer = (ChatServer) Naming.lookup("rmi://localhost:1099/chatServer");
}
private void run() throws RemoteException, MalformedURLException, NotBoundException {
ChatClientImpl chatClient1 = new ChatClientImpl(chatServer, "ikke");
new ChatFrame(chatClient1);
ChatClientImpl chatClient2 = new ChatClientImpl(chatServer, "bla");
new ChatFrame(chatClient2);
}
public static void main(String[] args) throws RemoteException, NotBoundException, MalformedURLException {
StartClient start = new StartClient();
start.run();
}
在 ChatClientImpl 构造函数中,我使用远程方法 register。
public ChatClientImpl(ChatServer chatServer, String name) throws MalformedURLException, NotBoundException, RemoteException {
this.chatServer = chatServer;
this.name = name;
chatServer.register(this);
}
现在我们在 ChatServerImpl class 的 REGISTER 方法中。我将客户端添加到客户端的 ArrayList。然后我使用方法 SENT 来显示文本。它调用每个客户端对象具有的 RECEIVE 方法。
public class ChatServerImpl extends UnicastRemoteObject implements ChatServer {
private List<ChatClient> clients;
public ChatServerImpl() throws RemoteException {
this.clients = new ArrayList<ChatClient>();
}
public void register(ChatClientImpl client) throws RemoteException {
clients.add(client);
send("server", client.getName() + " has entered the room");
}
public void unregister(ChatClientImpl client) throws RemoteException {
clients.remove(client);
send("server", client.getName() + " has left the room");
}
public void send(String name, String message) throws RemoteException {
for(ChatClient client : clients) {
client.receive(name + ": " + message);
}
}
}
这就是问题所在。 textReceiver 始终为空。 (textReceiver 是客户端对象的attribute/field。)
public void receive(String message) {
if (textReceiver == null) return;
textReceiver.receive(message);
}
客户端的 ArrayList 是服务器端的,其中的所有客户端都将其 textReceivers 设置为 null。如果您回头看看 StartClient,有一条重要的线。新的 ChatFrame(chatClient)。在 ChatFrame 的构造函数中,我设置了 textReceiver。
public ChatFrame(ChatClientImpl chatClient) {
this.chatClient = chatClient;
chatClient.setTextReceiver(this);
String name = chatClient.getName();
setTitle("Chat: " + name);
createComponents(name);
layoutComponents();
addListeners();
setSize(300, 300);
setVisible(true);
}
这个项目在我不使用 RMI 并且它们在一个包中时有效,但是一旦我将它们分离到客户端-服务器中,这个问题就出现了。我如何在它们之间进行通信?服务器端我有一个(不相关的?)ChatClients 列表,即使文本到达也不会影响任何东西。
我是否为每个单独的 ChatClient 使用 RMI 并使 ChatServer 与其连接并像那样发送文本?对我来说似乎很复杂。我该怎么做?
编辑:
ChatClientImpl class
public class ChatClientImpl implements ChatClient, Serializable {
private ChatServer chatServer;
private TextReceiver textReceiver;
private String name;
public ChatClientImpl(ChatServer chatServer, String name) throws MalformedURLException, NotBoundException, RemoteException {
this.chatServer = chatServer;
this.name = name;
chatServer.register(this);
}
public String getName() {
return name;
}
public void send(String message) throws RemoteException {
chatServer.send(name, message);
}
public void receive(String message) {
if (textReceiver == null) return;
textReceiver.receive(message);
}
public void setTextReceiver(TextReceiver textReceiver) {
this.textReceiver = textReceiver;
}
public void unregister() throws RemoteException {
chatServer.unregister(this);
}
}
您的 ChatClientImpl
class 不是导出的远程对象,因此它将被序列化到服务器,并在那里执行。并且因为 register()
发生在构建过程中,它会在调用 setReceiverTextReceiver()
方法之前被序列化。因此,相应的字段将为空。在服务器上。这不是你想要的,也不是你想要的。
因此,使扩展UnicastRemoteObject
并实现您的ChatClient
(假定的)远程接口。如果您在这样做时遇到问题,请解决它们。不要随便乱搞事情。它应该不实施Serializable
.
注意register()
的签名应该是register(ChatClient client)
。与ChatClientImpl
class无关。 unregister()
.
同上
我的目标是做一个简单的聊天程序。我是 RMI 的新人。到目前为止我得到的是服务器工作。我启动它。然后我启动客户端,它通过 RMI 将字符串传输到服务器。但是后来它没有出现在我制作的 GUI 上。这就是我的问题所在。
我的 StartClient class。我创建了一个 chatClient,并将 chatServer 存根作为参数。
public StartClient() throws RemoteException, NotBoundException, MalformedURLException {
chatServer = (ChatServer) Naming.lookup("rmi://localhost:1099/chatServer");
}
private void run() throws RemoteException, MalformedURLException, NotBoundException {
ChatClientImpl chatClient1 = new ChatClientImpl(chatServer, "ikke");
new ChatFrame(chatClient1);
ChatClientImpl chatClient2 = new ChatClientImpl(chatServer, "bla");
new ChatFrame(chatClient2);
}
public static void main(String[] args) throws RemoteException, NotBoundException, MalformedURLException {
StartClient start = new StartClient();
start.run();
}
在 ChatClientImpl 构造函数中,我使用远程方法 register。
public ChatClientImpl(ChatServer chatServer, String name) throws MalformedURLException, NotBoundException, RemoteException {
this.chatServer = chatServer;
this.name = name;
chatServer.register(this);
}
现在我们在 ChatServerImpl class 的 REGISTER 方法中。我将客户端添加到客户端的 ArrayList。然后我使用方法 SENT 来显示文本。它调用每个客户端对象具有的 RECEIVE 方法。
public class ChatServerImpl extends UnicastRemoteObject implements ChatServer {
private List<ChatClient> clients;
public ChatServerImpl() throws RemoteException {
this.clients = new ArrayList<ChatClient>();
}
public void register(ChatClientImpl client) throws RemoteException {
clients.add(client);
send("server", client.getName() + " has entered the room");
}
public void unregister(ChatClientImpl client) throws RemoteException {
clients.remove(client);
send("server", client.getName() + " has left the room");
}
public void send(String name, String message) throws RemoteException {
for(ChatClient client : clients) {
client.receive(name + ": " + message);
}
}
}
这就是问题所在。 textReceiver 始终为空。 (textReceiver 是客户端对象的attribute/field。)
public void receive(String message) {
if (textReceiver == null) return;
textReceiver.receive(message);
}
客户端的 ArrayList 是服务器端的,其中的所有客户端都将其 textReceivers 设置为 null。如果您回头看看 StartClient,有一条重要的线。新的 ChatFrame(chatClient)。在 ChatFrame 的构造函数中,我设置了 textReceiver。
public ChatFrame(ChatClientImpl chatClient) {
this.chatClient = chatClient;
chatClient.setTextReceiver(this);
String name = chatClient.getName();
setTitle("Chat: " + name);
createComponents(name);
layoutComponents();
addListeners();
setSize(300, 300);
setVisible(true);
}
这个项目在我不使用 RMI 并且它们在一个包中时有效,但是一旦我将它们分离到客户端-服务器中,这个问题就出现了。我如何在它们之间进行通信?服务器端我有一个(不相关的?)ChatClients 列表,即使文本到达也不会影响任何东西。
我是否为每个单独的 ChatClient 使用 RMI 并使 ChatServer 与其连接并像那样发送文本?对我来说似乎很复杂。我该怎么做?
编辑:
ChatClientImpl class
public class ChatClientImpl implements ChatClient, Serializable {
private ChatServer chatServer;
private TextReceiver textReceiver;
private String name;
public ChatClientImpl(ChatServer chatServer, String name) throws MalformedURLException, NotBoundException, RemoteException {
this.chatServer = chatServer;
this.name = name;
chatServer.register(this);
}
public String getName() {
return name;
}
public void send(String message) throws RemoteException {
chatServer.send(name, message);
}
public void receive(String message) {
if (textReceiver == null) return;
textReceiver.receive(message);
}
public void setTextReceiver(TextReceiver textReceiver) {
this.textReceiver = textReceiver;
}
public void unregister() throws RemoteException {
chatServer.unregister(this);
}
}
您的 ChatClientImpl
class 不是导出的远程对象,因此它将被序列化到服务器,并在那里执行。并且因为 register()
发生在构建过程中,它会在调用 setReceiverTextReceiver()
方法之前被序列化。因此,相应的字段将为空。在服务器上。这不是你想要的,也不是你想要的。
因此,使扩展UnicastRemoteObject
并实现您的ChatClient
(假定的)远程接口。如果您在这样做时遇到问题,请解决它们。不要随便乱搞事情。它应该不实施Serializable
.
注意register()
的签名应该是register(ChatClient client)
。与ChatClientImpl
class无关。 unregister()
.