手写一个简单的RPC

公共类

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;
    }
}

猜你喜欢

转载自blog.csdn.net/qq_45100361/article/details/113592043