您的位置:首页 > 编程语言 > Java开发

用RMI实现一个简单的实时聊天系统(java语言)

2009-11-04 10:29 936 查看
实现一个RMI应用程序(实验报告)
㈠实验内容
实现一个简单的实时聊天系统。
㈡处理流程
1系统设计
① 创建回调接口
定义一个回调接口,服务器端可以回调此接口中声明的方法。该接口必须继承远程接口即Remote。
② 创建一个本地接口
在该接口中添加本接口的实现类中的其他类的实例想要调用的本类的方法。这里的其他类的实例主要指的是程序中的Frame类的实例,即客户端窗口。
③ 创建一个客户端窗口类
该类继承Frame类,实现了ActionListener接口,用于展示一个较为好用的界面,获取用户名、消息和显示其它客户发过来的消息。
④ 创建一个客户端类
该类实现了前面第1、2步中创建的回调接口和本地接口,并继承了UnicastRemoteObject类,继承这个类很关键,Unicast即单播, 计算机网络用, 是在一个单个的发送者和一个接受者之间通过网络进行的通信。开始以为客户端不用继承这个类,结果失败了很多次,最后发现要实现回调,客户端必须继承该类。客户端类中新建一个客户端窗口类的实例,如第3步中所述,这个实例可以调用客户端类中的本地方法。
⑤ 创建一个服务器端接口
该接口也必须继承远程接口即Remote。客户端可以远程调用此类中声明的方法,就像本地调用一样。
⑥ 创建一个服务器端类
该类实现第5步中创建的接口类并实现UnicastRemoteObject类。
2、设计中的特点简介
客户发送的消息,先发送给服务器,再由服务器广播给所有客户,这个过程是通过客户端远程调用服务器端得广播消息方法实现的。在服务器广播消息这个方法中,实际是调用客户端的显示消息的方法。因此,为了实现广播,也即为了能让服务器远程调用客户的方法,就必须实现服务器端对客户端的回调,所以回调是设计中的一个特点。为了实现客户端对服务器端的远程调用,服务器端必须实现UnicastRemoteObject类。为了实现服务器端对客户端的回调,我们的客户端也必须继承UnicastRemoteObject类。最开始在试验回调的时候,由于没有继承这个类,结果失败。后来明白了,回调也是一种远程调用,只要是远程调用,就必须实现这个类。
为了实现客户端有一个可以显示的直观的窗口,在设计上也是实验了很多次。一开始直接定义一个集成窗口类的客户端类,并且让这个类实现客户端回调接口,但是这样做,就不能让客户端类继承UnicastRemoteObject类了,因为java是不支持多继承的。由于这个原因,开始根本就没有继承UnicastRemoteObject类。运行之后,发现服务器调用客户端类的发送消息方法后,在服务器端这边打出消息了。我百思不得其解,既然已经发生了回调,为啥方法执行完了,结果却作用在了服务器端。最后明白了原因就是没有继承UnicastRemotObject类。
再后来仔细研究了java中的接口,即interface,发现接口具有指针一类的功能。这也是rmi远程调用和回调机制实现的理论基础。于是我构想通过让窗口类通过拥有客户端类实例强制转化而来的接口来拥有调用客户端类方法的能力,而不用把窗口类和客户端类捆绑到一块儿。这样分开了窗口类和客户端类之后,就构成了3者之间的关系,即客户端与服务器端,客户端与窗口类。而客户端怎么拥有操作窗口类的能力呢?只要在客户端类中new一个窗口实例,并把自己强制转换为一个借口之后,传给这个窗口实例,那窗口实例就能调用这个客户端的方法,同时,客户端也能直接通过窗口实例直接调用客户端方法。
㈢实验算法分析
1.服务器端绑定服务名
LocateRegistry.createRegistry(8881);
ServerImpl serverimpl = new ServerImpl();
Naming.rebind("//10.26.12.63:8881/ChatServers",serverimpl);
2.客户端连接服务器并注册客户端
client = new ClientImpl();
server=(ServerInterface)Naming.lookup("//10.26.12.63:8881/ChatServers");
server.registry(client);
3.服务器端维护客户的哈希表
protected HashSet<ClientInterfaceCB> clients;
public void registry(ClientInterfaceCB client) throws RemoteException{
System.out.println("Registry client ...");
clients.add(client);
System.out.println("Client registry successfully!");
}
4.服务器广播消息的实现
public void postMessage(String content){
Iterator iter = clients.iterator();
try{
while(iter.hasNext()){
ClientInterfaceCB client = (ClientInterfaceCB) iter.next();
client.showMessage(content);
}
}catch(Exception e){
System.err.println("Removing invalid client.");
iter.remove();
}
}
5.客户端和客户端窗口之间互相调用的实现
窗口类的构造方法如下:
private ClientInterfaceCB clientCB;//回调接口
private ClientInterfaceLC clientLC;//本地接口
ClientWindow(ClientInterfaceCB Client,String s){
super(s);
clientCB=Client;
clientLC=(ClientInterfaceLC)Client;
......
}
客户端的新实例的创建方式:
client = new ClientImpl();这里值得注意的是客户实例在创建完成之后被强制转换为借口类。接口在java里面相当于有指针的作用。
客户端类中窗口的创建方式:
window=new ClientWindow(client,"客户端窗口");请注意与上面窗口类的构造方法比较。
客户端类将获取的消息在窗口中显示:
window.showmessage(content);
窗口中用户输入的消息通过客户端发送到服务器端:
clientLC.sendMessage(message);
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: