回撥在客戶端上呼叫方法
概述
在此示例中,2 個客戶端通過伺服器相互傳送資訊。一個客戶端向伺服器傳送一箇中繼到第二個客戶端的號碼。第二個客戶端將數字減半並通過伺服器將其傳送回第一個客戶端。第一個客戶端也這樣做。當任何客戶端返回的數字小於 10 時,伺服器停止通訊。從伺服器到客戶端的返回值(它轉換為字串表示的數字)然後回溯該程序。
- 登入伺服器將自身繫結到登錄檔。
- 客戶端查詢登入伺服器並使用其資訊呼叫
login
方法。然後:- 登入伺服器儲存客戶端資訊。它包含客戶端的存根和回撥方法。
- 登入伺服器建立並向客戶端返回伺服器存根(連線或會話)以進行儲存。它包括伺服器的存根,其方法包括
logout
方法(在本例中未使用)。
- 客戶端使用收件人客戶端的名稱和
int
呼叫伺服器的passInt
。 - 伺服器使用
int
呼叫收件人客戶端上的half
。這將啟動來回(呼叫和回撥)通訊,直到伺服器停止。
共享遠端介面
登入伺服器:
package callbackRemote;
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface RemoteLogin extends Remote {
RemoteConnection login(String name, RemoteClient client) throws RemoteException;
}
伺服器:
package callbackRemote;
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface RemoteConnection extends Remote {
void logout() throws RemoteException;
String passInt(String name, int i) throws RemoteException;
}
客戶端:
package callbackRemote;
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface RemoteClient extends Remote {
void half(int i) throws RemoteException;
}
實施
登入伺服器:
package callbackServer;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;
import java.util.HashMap;
import java.util.Map;
import callbackRemote.RemoteClient;
import callbackRemote.RemoteConnection;
import callbackRemote.RemoteLogin;
public class LoginServer implements RemoteLogin {
static Map<String, RemoteClient> clients = new HashMap<>();
@Override
public RemoteConnection login(String name, RemoteClient client) {
Connection connection = new Connection(name, client);
clients.put(name, client);
System.out.println(name + " logged in");
return connection;
}
public static void main(String[] args) {
try {
Registry reg = LocateRegistry.createRegistry(Registry.REGISTRY_PORT);
LoginServer server = new LoginServer();
UnicastRemoteObject.exportObject(server, Registry.REGISTRY_PORT);
reg.rebind("LoginServerName", server);
} catch (RemoteException e) {
e.printStackTrace();
}
}
}
伺服器:
package callbackServer;
import java.rmi.NoSuchObjectException;
import java.rmi.RemoteException;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;
import java.rmi.server.Unreferenced;
import callbackRemote.RemoteClient;
import callbackRemote.RemoteConnection;
public class Connection implements RemoteConnection, Unreferenced {
RemoteClient client;
String name;
public Connection(String name, RemoteClient client) {
this.client = client;
this.name = name;
try {
UnicastRemoteObject.exportObject(this, Registry.REGISTRY_PORT);
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void unreferenced() {
try {
UnicastRemoteObject.unexportObject(this, true);
} catch (NoSuchObjectException e) {
e.printStackTrace();
}
}
@Override
public void logout() {
try {
UnicastRemoteObject.unexportObject(this, true);
} catch (NoSuchObjectException e) {
e.printStackTrace();
}
}
@Override
public String passInt(String recipient, int i) {
System.out.println("Server received from " + name + ":" + i);
if (i < 10)
return String.valueOf(i);
RemoteClient client = LoginServer.clients.get(recipient);
try {
client.half(i);
} catch (RemoteException e) {
e.printStackTrace();
}
return String.valueOf(i);
}
}
客戶端:
package callbackClient;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;
import callbackRemote.RemoteClient;
import callbackRemote.RemoteConnection;
import callbackRemote.RemoteLogin;
public class Client implements RemoteClient {
RemoteConnection connection;
String name, target;
Client(String name, String target) {
this.name = name;
this.target = target;
}
public static void main(String[] args) {
Client client = new Client(args[0], args[1]);
try {
Registry reg = LocateRegistry.getRegistry();
RemoteLogin login = (RemoteLogin) reg.lookup("LoginServerName");
UnicastRemoteObject.exportObject(client, Integer.parseInt(args[2]));
client.connection = login.login(client.name, client);
} catch (RemoteException | NotBoundException e) {
e.printStackTrace();
}
if ("Client1".equals(client.name)) {
try {
client.connection.passInt(client.target, 120);
} catch (RemoteException e) {
e.printStackTrace();
}
}
}
@Override
public void half(int i) throws RemoteException {
String result = connection.passInt(target, i / 2);
System.out.println(name + " received: \"" + result + "\"");
}
}
執行示例:
- 執行登入伺服器。
- 使用引數
Client2 Client1 1097
執行客戶端。 - 使用引數
Client1 Client2 1098
執行客戶端。
由於有 3 個 JVM,輸出將出現在 3 個控制檯中。在這裡他們被混為一談:
Client2 登入
Client1 登入
從 Client1 收到的
伺服器 :120 從 Client2 收到的伺服器:60
從 Client1 收到的
伺服器 :30 從 Client2 收到的伺服器:15
從 Client1 收到的伺服器:7
收到 Client1: 收到7
Client2:收到15
Client1 :30
Client2 收到:60