|
|
《JavaTM程序设计语 言基础》第
1 部分 JavaTM远程方法调用(RMI)应用编程接 口(API)能够实现客户机和服务器的网络通信。一般情况下,由客户机程序向服 务器程序发出请求,而服务器程序则对这些请求作出响应。 其常见的示例是网络中的共享文字处理程序。文字处理器安装在服务器上,任 何想使用它的人都可以在自己的计算机上通过双击桌面上的图标或在命令行键入 其文件名来启动这个文字处理器。这两个调用操作都是向服务器程序发送一个访 问该软件的请求,而服务器程序的响应则是使该软件可为请求者使用。
本课将解释如何使用 RMI API 创建客户机和服务器之间的通信。 关于示例程序的说明 本课的示例程序是把 第 6 课:文件访问及权限 中的 文件输入与输出 应用程序转换为 RMI API。 程序动作 The RMIClient1
程序是一个简单的用户界面,供用户输入文本。当您点击
客户机 1 的第一实例
如果您启动
客户机 1 的第二实例
文件汇总 如图所示,示例程序由 RMIClient1 程序、远程对象、接口和以及 RMIClient2 程序组成。这些可执行文件所对应的源代码文件见以下列表。
此外,下述 java.policy 安全策略文件将授予运行本示例程序所需要的权限。 grant {
permission java.net.SocketPermission
"*:1024-65535",
"connect,accept,resolve";
permission java.net.SocketPermission
"*:80", "connect";
permission java.awt.AWTPermission
"accessEventQueue";
permission java.awt.AWTPermission
"showWindowWithoutWarningBanner";
};
编译示例程序 这些程序指令都假设开发工作是在 以下是 Unix 和 Win32 平台上命令序列,其后有相应的解释。 Unix:
cd /home/zelda/classes
javac Send.java
javac RemoteServer.java
javac RMIClient2.java
javac RMIClient1.java
rmic -d . RemoteServer
cp RemoteServer*.class /home/zelda/public_html/classes
cp Send.class /home/zelda/public_html/classes
Win32:
cd \home\zelda\classes
javac Send.java
javac RemoteServer.java
javac RMIClient2.java
javac RMIClient1.java
rmic -d . RemoteServer
copy RemoteServer*.class \home\zelda\public_html\classes
copy Send.class \home\zelda\public_html\classes
前两条 接下来的命令行则运行 第一条拷贝命令用其关联的 第二条拷贝命令把
启动 RMI 注册程序 启动客户机程序前,您必须启动 RMI 注册程序,它是服务器端允许远程客户 机获取远程服务器对象引用的命名仓库。 启动 RMI 注册程序前,请确保运行 以下命令将使 Unix:
cd /home/zelda/public_html/classes
unsetenv CLASSPATH
rmiregistry &
Win32:
cd \home\zelda\public_html\classes
set CLASSPATH=
start rmiregistry
运行 RemoteServer 服务器对象 运行实例程序前,应首先启动 本例中,
Unix:
cd /home/zelda/public_html/classes
java
-Djava.rmi.server.codebase=http://kq6py/~zelda/classes
-Djava.rmi.server.hostname=kq6py.eng.sun.com
-Djava.security.policy=java.policy RemoteServer
Win32:
cd \home\zelda\public_html\classes
java -Djava.rmi.server.codebase=file:
c:\home\zelda\public_html\classes
-Djava.rmi.server.hostname=kq6py.eng.sun.com
-Djava.security.policy=java.policy RemoteServer
运行 RMIClient1 程序 以下是 Unix 和 Win32 平台下的命令序列,其后有相应的解释。 本例中,
Unix:
cd /home/zelda/classes
java -Djava.rmi.server.codebase=
http://kq6py/~zelda/classes/
-Djava.security.policy=java.policy
RMIClient1 kq6py.eng.sun.com
Win32:
cd \home\zelda\classes
java -Djava.rmi.server.codebase=
file:c:\home\zelda\classes\
-Djava.security.policy=java.policy
RMIClient1 kq6py.eng.sun.com
运行 RMIClient2程序 以下是 Unix 和 Win32 平台下的命令序列,其后有相应的解释。 本例中,
Unix:
cd /home/zelda/classes
java -Djava.rmi.server.codebase=
http://kq6py/~zelda/classes
-Djava.security.policy=java.policy
RMIClient2 kq6py.eng.sun.com
Win32:
cd \home\zelda\classes
java -Djava.rmi.server.codebase=
file:c:\home\zelda\public_html\classes
-Djava.security.policy=java.policy
RMIClient2 kq6py.eng.sun.com
RemoteServer 类 RemoteServer
类对
class RemoteServer extends UnicastRemoteObject
implements Send {
String text;
public RemoteServer() throws RemoteException {
super();
}
public void sendData(String gotText){
text = gotText;
}
public String getData(){
return text;
}
服务器在缺省状态下以端口 1099 为其名称。若想使用其它端口名,则可以添 加该端口号并以冒号分隔,如:
public static void main(String[] args){
if(System.getSecurityManager() == null) {
System.setSecurityManager(new
RMISecurityManager());
}
String name = "//kq6py.eng.sun.com/Send";
try {
Send remoteServer = new RemoteServer();
Naming.rebind(name, remoteServer);
System.out.println("RemoteServer bound");
} catch (java.rmi.RemoteException e) {
System.out.println("Cannot create
remote server object");
} catch (java.net.MalformedURLException e) {
System.out.println("Cannot look up
server object");
}
}
}
Send 接口 Send
接口声明了 public interface Send extends Remote {
public void sendData(String text)
throws RemoteException;
public String getData() throws RemoteException;
}
RMIClient1 类 RMIClient1
类为远程服务器程序创建连接,并向远程服务器对象发送数据。完成这些任务的 程序代码编写在 actionPerformed 方法
public void actionPerformed(ActionEvent event){
Object source = event.getSource();
if(source == button){
//Send data over socket
String text = textField.getText();
try{
send.sendData(text);
} catch (java.rmi.RemoteException e) {
System.out.println("Cannot send data to server");
}
textField.setText(new String(""));
}
}
main 方法
安全管理器确定是否允许下载程序执行要求具备权限的任务的策略文件。 RMIClient1 frame = new RMIClient1();
if(System.getSecurityManager() == null) {
System.setSecurityManager(new RMISecurityManager());
}
try {
//args[0] contains name of server where Send runs
String name = "//" + args[0] + "/Send";
send = ((Send) Naming.lookup(name));
} catch (java.rmi.NotBoundException e) {
System.out.println("Cannot look up
remote server object");
} catch(java.rmi.RemoteException e){
System.out.println("Cannot look up
remote server object");
} catch(java.net.MalformedURLException e) {
System.out.println("Cannot look up
remote server object");
}
RMIClient2 类 RMIClient2
类创建与远程服务器程序的连接、从远程服务器对象获取数据并显示所得数据。完 成这些任务的程序代码编写在 actionPerformed 方法
public void actionPerformed(ActionEvent event) {
Object source = event.getSource();
if(source == button){
try{
String text = send.getData();
textArea.append(text);
} catch (java.rmi.RemoteException e) {
System.out.println("Cannot send data
to server");
}
}
}
}
main 方法
安全管理器确定是否允许下载程序执行要求具备权限的任务的策略文件。 RMIClient2 frame = new RMIClient2();
if(System.getSecurityManager() == null) {
System.setSecurityManager(new RMISecurityManager());
}
try {
String name = "//" + args[0] + "/Send";
send = ((Send) Naming.lookup(name));
} catch (java.rmi.NotBoundException e) {
System.out.println("Cannot look up remote
server object");
} catch(java.rmi.RemoteException e){
System.out.println("Cannot look up remote
server object");
} catch(java.net.MalformedURLException e) {
System.out.println("Cannot look up remote
server object");
}
更多信息 有关 RMI API 的更多信息,可见于 Java 教程 中的 RMI 部分。 [TOP] |
|
||||||||||||||||||||||||||||||||||||