实验要求:假设有一台应用服务器以RMI(或Socket编程)的方式向客户端提供英汉互译词典的服务。请尝试完成服务器端程序编码和一个客户端应用,并分别部署到两台计算
机上进行测试。服务接口声明见附录。说明:不考虑服务器端词典的容量,用数据库或使用Map在内存中保存少量的英汉词汇对应表。RMI有多种实现途径,参考网址中的内容只是其中一种,而且也不是最好的方式。请同学们不要局限于此,尽量通过google、sos0、百度发现更多、更好的方式,并对其优劣进行对比。
相关代码:
1.创建一个translator接口并定义相应的translate抽象方法。
public interface translator {
String translate(String word);
}
创建translatorImpl类实现接口
public class dictionaryImpl implements translator {
Map<String,String> dict = new HashMap<>();
public dictionaryImpl(){
dict.put("分布式","distributed");
dict.put("系统","system");
dict.put("架构","architecture");
dict.put("distributed", "分布式");
dict.put("system", "系统");
dict.put("architecture", "架构");
}
@Override
public String translate(String word) {
if(dict.containsKey(word)){
return dict.get(word);
}
throw new RuntimeException("未找到该单词");
}
}
- Socket服务端设计实现
对远程词典接口的一个具体实现,构建Socket套接字并实现与客户端Socket链接的逻辑。创建线程池维护Socket通信线程,包括构建输入输出流和远程调用translate方法等。
public class SocketServer {
public static void main(String[] args) throws IOException {
int port = 55533; //一般使用49152到65535之间的端口
ServerSocket server = new ServerSocket(port);
// 使用线程池,防止过多线程耗尽资源
ExecutorService threadPool = Executors.newFixedThreadPool(100);
Socket socket;
while (true) {
socket = server.accept(); //会一直阻塞,直到有客户端连接进来
// new Thread 只是创建一个类的对象实例而已。而真正创建线程的是start()方法。
// 这里并没有直接调用start()方法,所以并没创建新线程,而是交给线程池去执行。
threadPool.submit(new SocketThread(socket));
}
}
static class SocketThread implements Runnable {
private Socket socket;
InputStream inputStream;
OutputStream outputStream;
translatorImpl translatorImpl;
public SocketThread(Socket socket) {
this.socket = socket;
translatorImpl = new translatorImpl();
}
@Override
public void run() {
try {
inputStream = socket.getInputStream();
outputStream = socket.getOutputStream();
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
String message;
while(true){
message = in.readLine();
String word = translatorImpl.translate(message);
out.println(word);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
System.out.println("finish");
try {
if (inputStream != null) {
inputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
try {
if (outputStream != null) {
outputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
try {
if (socket != null) {
socket.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
- 客户端实现
与服务端实现逻辑类似,由于一个客户端通常仅需要与一个服务端构建链接,因此不需要构建线程池维护。与服务端代码另一个较大区别为多一个通过IO输入获取输入词汇逻辑。
public class SocketClient {
public static void main(String[] args) throws Exception {
Socket socket = null;
InputStream inputStream = null;
OutputStream outputStream = null;
Scanner sc = new Scanner(System.in);
try {
// 要连接的服务端IP地址和端口
String host = "127.0.0.1";
int port = 55533;
// 与服务端建立连接
socket = new Socket(host, port);
// 建立好连接后,从socket中获取输入流
inputStream = socket.getInputStream();
// 建立好连接后,从socket中获取输出流
outputStream = socket.getOutputStream();
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
System.out.println("客户端已连接到服务端");
System.out.println("请输入要翻译的词(输入\"exit\"退出)");
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
while(true){
String line = reader.readLine();
if("exit".equals(line)){
break;
}
out.println(line);
String response = in.readLine();
System.out.println(line + "-翻译结果:" + response);
}
} finally {
try {
if (inputStream != null) {
inputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
try {
if (outputStream != null) {
outputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
try {
if (socket != null) {
socket.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}