class ClientSession implements Serializable{
int count;
Socket clientSock;
Object bo;
public ClientSession(int count,Socket clientSock,Object bo){
this.count=count;
this.clientSock=clientSock;
this.bo=bo;
}
public int getCount(){
return count;
}
public void setCount(int count){
this.count=count;
}
public Socket getClientSock(){
return clientSock;
}
public void setClientSock(Socket sock){
this.clientSock=sock;
}
public Object getBusObject(){
return bo;
}
public void setBusObject(Object bo){
this.bo=bo;
}
}
第八步:编写服务器调制类BusServer.java(服务器)。
通过继承TunnelServer类,实现了调制的网络层抽象类定义的几个方法。这样做的主要目的是使程序结构简单明了,程序设计者可以集中力量进行业务逻辑的描述与实现,而无须关心数据在网络上被如何封装、如何分发。
该类主要包含构造函数(构造服务器端监听界面)、获取本地商业对象的实例以及根据不同报头执行不同的本地商业对象的相应方法。另外,它也是服务器端的主运行类,具有main方法。实现的代码如下:
/**
*远程方法调用的服务器端,运行后启动监听监听
*参考类:TunnelServer MyWindowListener
*/
public class BusServer extends TunnelServer{
/**
*构造函数,构造服务器端监听界面
*/
public BusServer(int port){
setPort(port);
setTitle("服务器窗口");
Container c=getContentPane();
c.setLayout(new FlowLayout());
addWindowListener(new MyWindowListener());
btn.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
try{
startServer(getPort());
btn.setEnabled(false);
}
catch(Exception ex){}
}
});
c.add(btn);
c.add(new JScrollPane(ta));
addWindowListener(new MyWindowListener());
setSize(new Dimension(400,300));
show();
}
/**
*返回商业对象实例
*/
public Object getRealObject() throws TunnelException{
return new BusObject();
}
/**
*根据报头的不同执行不同的本地方法调用
*/
public void executeMethods(Object busObject,
int flag, DataInputStream in,DataOutputStream out) throws Exception{
BusObject bus=(BusObject) busObject;
switch(flag){
case 1: //从服务器获取指定路径的所有文件名和子文件夹名
String path=(String)readObject();
FileAndDirectory ds=bus.getAllFileName(path);
out.writeInt(flag);
writeObject(ds);
break;
//在此添加其他方法的处理
// case 9998:
// 取入口参数,执行本地方法,返回结果
// break;
}
}
public static void main(String[] args) throws Exception{
BusServer ss=new BusServer(7484);
}
}
第九步:构造窗口关闭监听器MyWindowListener.java(服务器端)。
作为一个助益类,该监听器功能非常简单,可以保证窗口被正确关闭。
代码如下:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
/**
*窗口关闭用的监听器
*/
public class MyWindowListener extends WindowAdapter{
//窗口关闭方法
public void windowClosing(WindowEvent e){
System.exit(1);
}
}
4.存在的缺点:未考虑信息在传递过程中的加密与解密;未对传递信息进行压缩传输;串行化对象大小受整型变量大小限制;未设置对SOKET的监听;连接断开后系统存在内存漏洞。
四、应用测试
1.编写客户端主运行程序
到现在为止,程序设计者已经可以集中力量编写客户端主运行程序了。入口参数、出口参数的网络传输已经被完整而准确地封装到了相关的类中。实现的核心代码如下:
/**
*远程方法调用的客户端,首先要提供用户名和密码登录,默认为:qixiaorui ,20000203
*然后在路径文本框中输入要查看的服务器目录,如:c:\\windows,单击获取按钮
*参考类:BusObjectProxy MyWindowListener
*/
public class BusClient extends JFrame{
JTextArea ta=new JTextArea(10,33);
JLabel lbl1=new JLabel("用户名:"),
lbl2=new JLabel("密码:"),
lbl3=new JLabel("指定路径:");
JTextField tf1=new JTextField(8);
JPasswordField tf2=new JPasswordField(8);
JTextField tf3=new JTextField(19);
JButton btn1=new JButton("获取");
JButton btn=new JButton("连接");
BusObjectProxy bus;
String welcome="";
public BusClient(){
super("客户端窗口");
Container c=getContentPane();
c.setLayout(new FlowLayout(FlowLayout.LEFT));
c.add(lbl1);c.add(tf1);
c.add(lbl2);c.add(tf2);
c.add(btn);
c.add(lbl3);c.add(tf3);c.add(btn1);
c.add(new JScrollPane(ta));
//获取指定目录的所有文件名
btn1.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
try{
String path=tf3.getText();
ta.append("单元测试:获取服务器指定目录"+path+
"下的所有文件名和文件夹名"+"\n");
FileAndDirectory fd=bus.getAllFileName(path);
Vector v=new Vector();
v=fd.getFileArray();
ta.append("输出所有的文件名:\n");
for(int i=0;i<v.size();i++){
ta.append(v.elementAt(i)+"\n");
}
v=fd.getDirectoryArray();
ta.append("输出所有的目录名:\n");
for(int i=0;i<v.size();i++){
ta.append(v.elementAt(i)+"\n");
}
}catch(Exception ex){}
}
});
//登录
btn.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
try{
String name=tf1.getText();
String pass=new String(tf2.getPassword());
bus=new BusObjectProxy(name,pass);
welcome=bus.getWelcome();
ta.append(welcome+"\n");
}catch(Exception ex){}
}
});
addWindowListener(new MyWindowListener());
setSize(new Dimension(400,300));
show();
}
public static void main(String[] args){
BusClient bc=new BusClient();
}
}
2.运行效果
客户端的运行效果如图2所示,服务器端的运行效果如图3所示。
图2 客户端窗口
图3 服务器端窗口
(1)运行服务器端程序。命令:java BusServer
(2)启动服务端口
(3)运行客户端程序。命令:java BusClient
(4)首先输入错误的密码,则服务器拒绝用户登录,然后输入了正确的密码,并获取到服务器C:\\WINDOWS目录中的所有内容显示出来。
对该例子进行简单扩展后就可以完成一个远程资源管理器的程序
五、部署描述
1.服务器端
Helper类:FileAndDirectory.class,MyWindowListener.class
架构类: BusInterface.class,BusObject.class,TunnelServer.class,
Talk.class,ClientSession.class,TunnelException.class
主运行类:BusServer.class
2.客户端
Helper类:FileAndDirectory.class,MyWindowListener.class
架构类: BusInterface.class,BusObjectProxy.class,TunnelClient.class
主运行类:BusClient.class
源代码和类文件请参照附件cs.rar。
|