RPCServer
这是一个RPC(远程过程调用)服务器的实现,主要功能是根据客户端发送的方法名和参数,调用对应的服务端实现,并将结果返回给客户端。
-
导入相关的类和接口:
import com.rpc.server.lib.RpcInterface;
import java.io.*;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
-
定义
Server
类并实现main
方法:
public class Server {
public static void main(String[] args) throws IOException, InstantiationException, IllegalAccessException, ClassNotFoundException {
}
}
-
初始化方法映射表
methodMap
,用于存储方法名和对应的实现类实例:
HashMap<String, RpcInterface> methodMap = new HashMap<>();
-
通过读取配置文件
methods.txt
,解析其中的方法名和类名,并通过反射实例化类对象,将方法名和实例的映射存储到methodMap
中:
File file = new File("C:\\Users\\18384\\IdeaProjects\\_sjjg_\\src\\RPC\\RPCServer\\config\\methods.txt");
FileReader fileReader = new FileReader(file);
BufferedReader br = new BufferedReader(fileReader);
String listStr = null;
while ((listStr = br.readLine()) != null) {
System.out.println(listStr);
// 解析单行数据 方法名 类名
String[] methodMsg = listStr.split(" ");
String methodName = methodMsg[0];
String className = methodMsg[1];
// 反射获取类对象1
Class<?> aClass = Class.forName(className);
// 加载类实例
Object object = aClass.newInstance();// 实例化
// 存储方法名-类实例
methodMap.put(methodName, (RpcInterface) object);
//System.out.println(listStr);
}
-
启动服务端Socket,监听端口
12345
:
ServerSocket serverSocket = new ServerSocket(12345);
System.out.println("Server started");
-
进入无限循环,等待客户端连接:
while (true) {
}
-
使用 try-with-resources 语句创建 Socket 连接,并获取输入输出流:
try (Socket socket = serverSocket.accept();
ObjectInputStream input = new ObjectInputStream(socket.getInputStream());
ObjectOutputStream output = new ObjectOutputStream(socket.getOutputStream())) {
}
-
从客户端读取方法名,并检查是否存在于
methodMap
中:
String methodName = input.readUTF();
if (methodMap.containsKey(methodName)) {
}
-
如果存在,获取对应的实例对象,并通过反射获取该类的所有方法:
// 根据方法名 获取实例
RpcInterface rpcInterface = methodMap.get(methodName);
// 反射类
Class rpcClass = rpcInterface.getClass();
// 加载方法
Method[] methods = rpcClass.getMethods();
-
从客户端读取参数,并调用方法:
// 读第二句话 参数
String name = input.readUTF();
// 调用方法 获取返回结果
Object obj = methods[0].invoke(rpcInterface, name);
-
将结果发送给客户端:
// 发送给调用者结果
output.writeUTF(obj.toString());
output.flush();
- 处理异常:
catch (IOException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
这段代码实现了一个简单的RPC服务器,通过配置文件指定可调用的方法,并在客户端请求时动态调用相应的方法。需要注意的是,这里只处理了一种方法,即调用类的第一个方法,实际的应用场景可能需要更复杂的处理逻辑。同时,由于没有处理并发,可能在多客户端同时连接时存在问题。
RPClient
这是一个RPC客户端的实现,主要功能是模拟向服务器发起远程方法调用。
-
定义
Client
类并实现main
方法:
public class Client {
public static void main(String[] args) {
}
}
-
使用一个循环模拟多次客户端调用:
for (int i = 0; i < 50; i++) {
}
-
在每次循环中,通过
Thread.sleep(1000)
模拟间隔1秒的延迟:
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
-
创建一个
HelloWorldImp
实例,并调用其sayHello
方法,传入参数 "AJava":
new HelloWorldImp().sayHello("AJava");
-
创建一个
CallImp
实例,并调用其call
方法,传入参数 "张伟":
String res = new CallImp().call("张伟");
-
在每次循环中,都模拟向服务器发起一次
HelloWorldImp
的调用和一次CallImp
的调用
这段代码主要用于模拟客户端向服务器发起RPC调用。需要注意的是,该代码中创建了多个实例对象,而实际使用中可能会考虑复用连接或者采用连接池的方式,以提高效率。此外,对于 HelloWorldImp
和 CallImp
,这些实现类应该是RPC服务器端提供的具体服务实现类。在真实的RPC场景中,通常会使用代理对象来进行远程调用,而不是直接调用服务实现类的方法。
HelloWorldImp
这是一个HelloWorld
接口的客户端实现HelloWorldImp
,用于在客户端发起对RPC服务器上HelloWorld
接口的sayHello
方法的调用。
-
导入相关的类和接口:
import com.rpc.clinet.lib.HelloWorld;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
-
定义
HelloWorldImp
类并实现HelloWorld
接口:
public class HelloWorldImp implements HelloWorld {
}
-
实现
HelloWorld
接口的sayHello
方法:
public String sayHello(String name) {
}
-
在
sayHello
方法中,创建一个Socket
对象,连接到RPC服务器的地址(localhost)和端口(12345):
String response = null;
try (Socket socket = new Socket("localhost", 12345);
ObjectOutputStream output = new ObjectOutputStream(socket.getOutputStream());
ObjectInputStream input = new ObjectInputStream(socket.getInputStream())) {
}
-
通过
ObjectOutputStream
向服务器发送两个字符串,第一个字符串是方法名 "sayHello",第二个字符串是参数name
:
output.writeUTF("sayHello");
output.writeUTF(name);
output.flush();
-
通过
ObjectInputStream
从服务器接收返回结果:
response = input.readUTF();
-
打印服务器返回的结果:
System.out.println(response);
-
处理异常:
catch (IOException e) {
e.printStackTrace();
}
-
返回服务器返回的结果:
return response;
这段代码的作用是通过Socket与RPC服务器建立连接,将方法名和参数发送给服务器,然后接收并返回服务器的处理结果。需要注意的是,这里的实现是简单的同步调用方式,即客户端在调用sayHello
方法时会阻塞等待服务器的响应。在实际应用中,可能会使用异步调用、回调等方式来提高系统的并发性能。
CallImp
这是一个Call
接口的客户端实现CallImp
,用于在客户端发起对RPC服务器上Call
接口的call
方法的调用。
-
导入相关的类和接口:
import com.rpc.clinet.lib.Call;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
-
定义
CallImp
类并实现Call
接口:
public class CallImp implements Call {
}
-
实现
Call
接口的call
方法:
public String call(String name) {
}
-
在
call
方法中,创建一个Socket
对象,连接到RPC服务器的地址(localhost)和端口(12345):
tring response = null;
try (Socket socket = new Socket("localhost", 12345);
ObjectOutputStream output = new ObjectOutputStream(socket.getOutputStream());
ObjectInputStream input = new ObjectInputStream(socket.getInputStream())) {
}
-
通过
ObjectOutputStream
向服务器发送两个字符串,第一个字符串是方法名 "call",第二个字符串是参数name
:
output.writeUTF("call");
output.writeUTF(name);
output.flush();
-
通过
ObjectInputStream
从服务器接收返回结果:
response = input.readUTF();
-
打印服务器返回的结果:
System.out.println(response);
-
处理异常:
catch (IOException e) {
e.printStackTrace();
}
-
返回服务器返回的结果:
return response;
这段代码的作用是通过Socket与RPC服务器建立连接,将方法名和参数发送给服务器,然后接收并返回服务器的处理结果。同样地,这里的实现是简单的同步调用方式。在实际应用中,可能会使用异步调用、回调等方式来提高系统的并发性能。