手写一个简单的RPC
程序员文章站
2022-07-12 16:38:55
...
公共类
public class User implements Serializable {
private static final long serialversionUID = 1L;
private Integer id;
private String name;
public User(Integer id, String name) {
this.id = id;
this.name = name;
}
public static long getSerialversionUID() {
return serialversionUID;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}
public interface IUserService {
public User findUserById(Integer id);
}
public class UserServiceImpl implements IUserService {
@Override
public User findUserById(Integer id) {
return new User(id, "Alice");
}
}
版本一
public class Client {
public static void main(String[] args) throws IOException {
Socket socket = new Socket("127.0.0.1", 8888);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(baos);
dos.writeInt(123);
socket.getOutputStream().write(baos.toByteArray());//把123变成二进制数组 在网络中传输的数据归根结底都是二进制数据
socket.getOutputStream().flush();//清空缓冲区 将数据强行输出去
DataInputStream dis = new DataInputStream(socket.getInputStream());
int id = dis.readInt();
String name = dis.readUTF();
User user = new User(id, name);
System.out.println(user);
dos.close();
socket.close();
}
}
public class Server {
private static boolean running = true;
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(8888);
while (running) {
Socket s = serverSocket.accept();
process(s);
s.close();
}
serverSocket.close();
}
public static void process(Socket socket) throws IOException {
InputStream in = socket.getInputStream();
OutputStream out = socket.getOutputStream();
DataInputStream dis = new DataInputStream(in);
DataOutputStream dos = new DataOutputStream(out);
int id = dis.readInt();
IUserService service = new UserServiceImpl();
User user = service.findUserById(id);
dos.writeInt(user.getId());
dos.writeUTF(user.getName());
dos.flush();
}
}
版本二
public class Client {
public static void main(String[] args) throws IOException {
Stub stub = new Stub();//这么写就给你屏蔽了许多细节
System.out.println(stub.findUserById(223));
}
}
//将网络进一步的封装
public class Stub {
public User findUserById(Integer id) throws IOException {
Socket socket = new Socket("127.0.0.1", 8888);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(baos);
dos.writeInt(id);
OutputStream out = socket.getOutputStream();
out.write(baos.toByteArray());
out.flush();
DataInputStream dis = new DataInputStream(socket.getInputStream());
int readId = dis.readInt();
String readName = dis.readUTF();
User user = new User(readId, readName);
dis.close();
dos.close();
socket.close();
return user;
}
}
public class Server {
private static boolean running = true;
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(8888);
while (running) {
Socket s = serverSocket.accept();
process(s);
s.close();
}
serverSocket.close();
}
public static void process(Socket socket) throws IOException {
InputStream in = socket.getInputStream();
OutputStream out = socket.getOutputStream();
DataInputStream dis = new DataInputStream(in);
DataOutputStream dos = new DataOutputStream(out);
int id = dis.readInt();
IUserService service = new UserServiceImpl();
User user = service.findUserById(id);
dos.writeInt(user.getId());
dos.writeUTF(user.getName());
dos.flush();
}
}
版本三
public class Client {
public static void main(String[] args) {
IUserService service = Stub.getStub();
System.out.println(service.findUserById(123));//实际调的是invoke这个方法
}
}
public class Server {
private static boolean running = true;
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(8888);
while (running) {
Socket s = serverSocket.accept();
process(s);
s.close();
}
serverSocket.close();
}
public static void process(Socket socket) throws IOException {
InputStream in = socket.getInputStream();
OutputStream out = socket.getOutputStream();
DataInputStream dis = new DataInputStream(in);
DataOutputStream dos = new DataOutputStream(out);
int id = dis.readInt();
IUserService service = new UserServiceImpl();
User user = service.findUserById(id);
dos.writeInt(user.getId());
dos.writeUTF(user.getName());
dos.flush();
}
}
public class Stub {
public static IUserService getStub() {
InvocationHandler h = new InvocationHandler() {
/**
*
* @param proxy 代理的对象是谁
* @param method 调的是哪个方法 findUserById()
* @param args 这个方法传了哪些参数 123
* @return
* @throws Throwable
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("你好");
Socket s = new Socket("127.0.0.1", 8888);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(baos);
dos.writeInt(123);
s.getOutputStream().write(baos.toByteArray());
s.getOutputStream().flush();
DataInputStream dis = new DataInputStream(s.getInputStream());
int id = dis.readInt();
String name = dis.readUTF();
User user = new User(id, name);
dos.close();
s.close();
return user;
}
};
//第一个参数:被代理对象的类加载器
//第二个参数:被代理对象的接口 IUserService本来就是个接口
//第三个参数:
Object o = Proxy.newProxyInstance(IUserService.class.getClassLoader(), new Class[] {IUserService.class}, h);
return (IUserService) o;
}
}
版本四
public class Client {
public static void main(String[] args) {
IUserService stub = Stub.getStub();
System.out.println(stub.findUserById(123));//你调findUserById这个方法会给你调invoke这个方法
}
}
public class Server {
private static boolean running = true;
public static void main(String[] args) throws Exception {
ServerSocket ss = new ServerSocket(8888);
while (running) {
Socket s = ss.accept();
process(s);
s.close();
}
}
private static void process(Socket s) throws Exception {
InputStream in = s.getInputStream();
OutputStream out = s.getOutputStream();
ObjectInputStream ois = new ObjectInputStream(in);
DataOutputStream dos = new DataOutputStream(out);
String methodName = ois.readUTF();//把方法名读进来
Class[] parameterTypes = (Class[])ois.readObject();//参数类型读进来
Object[] args = (Object[])ois.readObject();//参数读进来
IUserService service = new UserServiceImpl();
Method method = service.getClass().getMethod(methodName, parameterTypes);//通过反射的方式找到类里面的方法
User user = (User)method.invoke(service,args);//对方法进行调用
dos.writeInt(user.getId());//返回数据
dos.writeUTF(user.getName());
dos.flush();
}
}
public class Stub {
public static IUserService getStub() {
InvocationHandler h = new InvocationHandler() {
/**
*
* @param proxy 代理的对象是谁
* @param method 调的是哪个方法 findUserById()
* @param args 这个方法传了哪些参数 123
* @return
* @throws Throwable
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Socket s = new Socket("127.0.0.1", 8888);
ObjectOutputStream oos = new ObjectOutputStream(s.getOutputStream());
//把方法的信息通过网络传过去
String methodName = method.getName();//现在调用方法的name
//通过 方法名 和 参数列表 就可以知道你要调用哪个方法了
Class<?>[] parameterTypes = method.getParameterTypes();//方法的参数类型 防止出现方法重载 来辨认哪个方法
//将一个方法的基本信息都写出去
oos.writeUTF(methodName);
oos.writeObject(parameterTypes);
oos.writeObject(args);
oos.flush();
DataInputStream dis = new DataInputStream(s.getInputStream());
int id = dis.readInt();
String name = dis.readUTF();
User user = new User(id, name);
dis.close();
s.close();
return user;
}
};
//第一个参数:被代理对象的类加载器
//第二个参数:被代理对象的接口 IUserService本来就是个接口
//第三个参数:
Object o = Proxy.newProxyInstance(IUserService.class.getClassLoader(), new Class[] {IUserService.class}, h);
return (IUserService) o;
}
}
版本五
public class Client {
public static void main(String[] args) {
IUserService stub = Stub.getStub();
System.out.println(stub.findUserById(123));//你调findUserById这个方法会给你调invoke这个方法 这里给你返回的
}
}
public class Server {
private static boolean running = true;
public static void main(String[] args) throws Exception {
ServerSocket ss = new ServerSocket(8888);
while (running) {
Socket s = ss.accept();
process(s);
s.close();
}
}
private static void process(Socket s) throws Exception {
InputStream in = s.getInputStream();
OutputStream out = s.getOutputStream();
ObjectInputStream ois = new ObjectInputStream(in);
DataOutputStream dos = new DataOutputStream(out);
String methodName = ois.readUTF();//把方法名读进来
Class[] parameterTypes = (Class[])ois.readObject();//参数类型读进来
Object[] args = (Object[])ois.readObject();//参数读进来
IUserService service = new UserServiceImpl();
Method method = service.getClass().getMethod(methodName, parameterTypes);//通过反射的方式找到类里面的方法
User user = (User)method.invoke(service,args);//对方法进行调用
ObjectOutputStream oos = new ObjectOutputStream(out);//将输出的结果封装成Object
//直接把结果user对象返回给客户端
oos.writeObject(user);
dos.flush();
}
}
public class Stub {
public static IUserService getStub() {
InvocationHandler h = new InvocationHandler() {
/**
*
* @param proxy 代理的对象是谁
* @param method 调的是哪个方法 findUserById()
* @param args 这个方法传了哪些参数 123
* @return
* @throws Throwable
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Socket s = new Socket("127.0.0.1", 8888);
ObjectOutputStream oos = new ObjectOutputStream(s.getOutputStream());
//把方法的信息通过网络传过去
String methodName = method.getName();//现在调用方法的name
//通过 方法名 和 参数列表 就可以知道你要调用哪个方法了
Class[] parameterTypes = method.getParameterTypes();//方法的参数类型 防止出现方法重载 来辨认哪个方法
//将一个方法的基本信息都写出去
oos.writeUTF(methodName);
oos.writeObject(parameterTypes);
oos.writeObject(args);//args就是参数
oos.flush();
DataInputStream dis = new DataInputStream(s.getInputStream());
int id = dis.readInt();
String name = dis.readUTF();
User user = new User(id, name);
dis.close();
s.close();
return user;
}
};
//第一个参数:被代理对象的类加载器
//第二个参数:被代理对象的接口 IUserService本来就是个接口
//第三个参数:
Object o = Proxy.newProxyInstance(IUserService.class.getClassLoader(), new Class[] {IUserService.class}, h);
return (IUserService) o;
}
}
版本六
public class Client {
public static void main(String[] args) {
//传入一个类 给你返回一个指定对象 这是一个代理类
IUserService service = (IUserService) Stub.getStub(IUserService.class);
System.out.println(service.findUserById(123));
}
}
public class Server {
private static boolean running = true;
public static void main(String[] args) throws Exception {
ServerSocket ss = new ServerSocket(8888);
while (running) {
Socket s = ss.accept();
process(s);
s.close();
}
}
private static void process(Socket s) throws Exception {
InputStream in = s.getInputStream();
OutputStream out = s.getOutputStream();
ObjectInputStream ois = new ObjectInputStream(in);
//这几个获取的顺序和你客户端写出的顺序一样吧
//String clazzName = ois.readUTF();
String methodName = ois.readUTF();
Class[] parameterTypes = (Class[])ois.readObject();
Object[] args = (Object[])ois.readObject();
Class clazz = null;
//从服务注册表中找到具体的类 这个是具体的实现类
clazz = UserServiceImpl.class;
Method method = clazz.getMethod(methodName, parameterTypes);
//这里才是调用的方法 客户端把你需要调用的方法信息给你
//首先我要创建一个对象才能调用里面的方法 clazz.newInstance() 反射创建对象
Object o = (Object) method.invoke(clazz.newInstance(), args);
ObjectOutputStream oos = new ObjectOutputStream(out);
oos.writeObject(o);
oos.flush();
}
}
public class Stub {
//这样可以给你返回一个任意类型的对象
public static Object getStub(Class clazz) {
InvocationHandler h = new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Socket s = new Socket("127.0.0.1", 8888);
ObjectOutputStream oos = new ObjectOutputStream(s.getOutputStream());
String clazzName = clazz.getName();//获取类的名字
String methodName = method.getName();
Class<?>[] parameterTypes = method.getParameterTypes();
//oos.writeObject(clazzName);
oos.writeUTF(methodName);
oos.writeObject(parameterTypes);
oos.writeObject(args);
oos.flush();
ObjectInputStream ois = new ObjectInputStream(s.getInputStream());
Object o = ois.readObject();
oos.close();
s.close();
return o;
}
};
Object o = Proxy.newProxyInstance(clazz.getClassLoader(), new Class[]{clazz}, h);
return o;
}
}
上一篇: 手写RPC框架
下一篇: 可达性统计(图 拓扑排序 bitset)