Java RMI:如何使在服务器上调用的客户端存根方法在客户端屏幕上打印消息?
Java RMI: how to make client stub method called on server print message on client screen?
我正在 Java 中与 rmi 聊天。我有一个服务器对象和至少两个客户端对象。当客户端向远程调用 recebeMensagem 方法的服务器发送消息时,服务器必须在所有客户端的屏幕上打印该消息(发送消息的客户端除外)。
客户端class有一个方法printMenssagem(Mensagem msg)
,由服务器远程调用。问题是该方法正在服务器屏幕上打印。我该如何改为在客户端屏幕上打印消息?
Server.java:
import java.rmi.NotBoundException;
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.function.Predicate;
public class Server implements ChatServer {
private ArrayList<String> listaClientes = new ArrayList<>();
private static int port = 5002;
public static void main(String[] args) {
try {
Server obj = new Server();
ChatServer stub = (ChatServer)
UnicastRemoteObject.exportObject(obj, port);
// Bind the remote object's stub in the registry
Registry registry = LocateRegistry.createRegistry(port);
registry.bind("chat", stub);
System.out.println("Server ready!");
} catch (Exception e) {
System.err.println("Server exception: " + e.toString());
e.printStackTrace();
}
}
@Override
public void adicionaCliente(String user) {
this.listaClientes.add(user);
}
@Override
public void retiraCliente(String userName) {
Predicate<String> clientePredicate = cp ->
cp.equals(userName);
listaClientes.removeIf(clientePredicate);
try {
Registry registry = LocateRegistry.getRegistry(port);
registry.unbind(userName);
} catch (RemoteException e) {
e.printStackTrace();
} catch (NotBoundException e) {
e.printStackTrace();
}
}
@Override
public void recebeMensagem(Mensagem msg) {
try {
Registry registry = LocateRegistry.getRegistry(port);
for(String cliente : listaClientes) {
if (!cliente.equals(msg.getRemetente())) {
Client stub = (Client) registry.lookup(cliente);
stub.printMensagem(msg);
}
}
} catch (RemoteException e) {
e.printStackTrace();
} catch (NotBoundException e) {
e.printStackTrace();
}
}
public ArrayList<String> getListaClientes() {
return listaClientes;
}
public void setListaClientes(ArrayList<String> listaClientes) {
this.listaClientes = listaClientes;
}
}
Client.java :
import java.io.Serializable;
import java.rmi.Remote;
public class Client implements Remote, Serializable {
private static final long serialVersionUID = 6864579049922061838L;
private static int port = 5002;
private static String host = "127.0.0.1";
public static void main(String[] args) {
new Thread(new ClientInterface(host, port)).start();
}
public void printMensagem(Mensagem mensagem) {
System.out.println(mensagem.getRemetente() + ": " + mensagem.getMensagem());
}
}
how to make client stub method called on server print message on client screen?
客户没有存根。它不是远程对象。它是一个可序列化的对象,它已被传输到注册表中,并且它运行在执行 Registry.lookup()
以获取它的任何 JVM 中。这不是你想要的。您希望它成为一个带有存根的远程对象,因此您必须使其实现一个远程接口,导出它,并通过其在对等端的远程接口使用它。
您还需要注意,您当前的体系结构无法跨多个主机工作,因为您无法绑定到远程注册表。您将需要向服务器添加客户端注册方法。
我正在 Java 中与 rmi 聊天。我有一个服务器对象和至少两个客户端对象。当客户端向远程调用 recebeMensagem 方法的服务器发送消息时,服务器必须在所有客户端的屏幕上打印该消息(发送消息的客户端除外)。
客户端class有一个方法printMenssagem(Mensagem msg)
,由服务器远程调用。问题是该方法正在服务器屏幕上打印。我该如何改为在客户端屏幕上打印消息?
Server.java:
import java.rmi.NotBoundException;
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.function.Predicate;
public class Server implements ChatServer {
private ArrayList<String> listaClientes = new ArrayList<>();
private static int port = 5002;
public static void main(String[] args) {
try {
Server obj = new Server();
ChatServer stub = (ChatServer)
UnicastRemoteObject.exportObject(obj, port);
// Bind the remote object's stub in the registry
Registry registry = LocateRegistry.createRegistry(port);
registry.bind("chat", stub);
System.out.println("Server ready!");
} catch (Exception e) {
System.err.println("Server exception: " + e.toString());
e.printStackTrace();
}
}
@Override
public void adicionaCliente(String user) {
this.listaClientes.add(user);
}
@Override
public void retiraCliente(String userName) {
Predicate<String> clientePredicate = cp ->
cp.equals(userName);
listaClientes.removeIf(clientePredicate);
try {
Registry registry = LocateRegistry.getRegistry(port);
registry.unbind(userName);
} catch (RemoteException e) {
e.printStackTrace();
} catch (NotBoundException e) {
e.printStackTrace();
}
}
@Override
public void recebeMensagem(Mensagem msg) {
try {
Registry registry = LocateRegistry.getRegistry(port);
for(String cliente : listaClientes) {
if (!cliente.equals(msg.getRemetente())) {
Client stub = (Client) registry.lookup(cliente);
stub.printMensagem(msg);
}
}
} catch (RemoteException e) {
e.printStackTrace();
} catch (NotBoundException e) {
e.printStackTrace();
}
}
public ArrayList<String> getListaClientes() {
return listaClientes;
}
public void setListaClientes(ArrayList<String> listaClientes) {
this.listaClientes = listaClientes;
}
}
Client.java :
import java.io.Serializable;
import java.rmi.Remote;
public class Client implements Remote, Serializable {
private static final long serialVersionUID = 6864579049922061838L;
private static int port = 5002;
private static String host = "127.0.0.1";
public static void main(String[] args) {
new Thread(new ClientInterface(host, port)).start();
}
public void printMensagem(Mensagem mensagem) {
System.out.println(mensagem.getRemetente() + ": " + mensagem.getMensagem());
}
}
how to make client stub method called on server print message on client screen?
客户没有存根。它不是远程对象。它是一个可序列化的对象,它已被传输到注册表中,并且它运行在执行 Registry.lookup()
以获取它的任何 JVM 中。这不是你想要的。您希望它成为一个带有存根的远程对象,因此您必须使其实现一个远程接口,导出它,并通过其在对等端的远程接口使用它。
您还需要注意,您当前的体系结构无法跨多个主机工作,因为您无法绑定到远程注册表。您将需要向服务器添加客户端注册方法。