手写一个简单的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;
    }
}
介绍RCP的实现原理 目录 1. 前言 2 2. 基本概念 3 2.1. IDL 3 2.2. 代理(Proxy) 3 2.3. 存根(Stub) 4 3. 三要素 4 3.1. 网络通讯 4 3.2. 消息编解码 5 3.3. IDL编译器 5 4. flex和bison 5 4.1. 准备概念 5 4.1.1. 正则表达式(regex/regexp) 6 4.1.2. 符号∈ 6 4.1.3. 终结符/非终结符/产生式 6 4.1.4. 记号(Token) 6 4.1.5. 形式文法 7 4.1.6. 上下文无关文法(CFG) 7 4.1.7. BNF 8 4.1.8. 推导 8 4.1.9. 语法树 8 4.1.10. LL(k) 9 4.1.11. LR(k) 9 4.1.12. LALR(k) 9 4.1.13. GLR 9 4.1.14. 移进/归约 9 4.2. flex和bison文件格式 9 4.2.1. 定义部分 10 4.2.2. 规则部分 10 4.2.3. 用户子例程部分 10 4.3. flex基础 10 4.3.1. flex文件格式 11 4.3.2. 选项 11 4.3.3. 名字定义 11 4.3.4. 词法规则 12 4.3.5. 匹配规则 12 4.3.6. %option 13 4.3.7. 全局变量yytext 13 4.3.8. 全局变量yyval 13 4.3.9. 全局变量yyleng 13 4.3.10. 全局函数yylex 13 4.3.11. 全局函数yywrap 13 4.4. bison基础 14 4.4.1. bison文件格式 14 4.4.2. %union 14 4.4.3. %token 15 4.4.4. 全局函数yyerror() 15 4.4.5. 全局函数yyparse() 15 4.5. 例1:单词计数 15 4.5.1. 目的 15 4.5.2. flex词法文件wc.l 16 4.5.3. Makefile 16 4.6. 例2:表达式 17 4.6.1. 目的 17 4.6.2. flex词法exp.l 17 4.6.3. bison语法exp.y 17 4.6.4. Makefile 19 4.6.5. 代码集成 19 4.7. 例3:函数 20 4.7.1. 目的 20 4.7.2. func.h 20 4.7.3. func.c 21 4.7.4. IDL代码func.idl 22 4.7.5. flex词法func.l 22 4.7.6. bison语法func.y 24 4.7.7. Makefile 27 5. 进阶 27 5.1. 客户端函数实现 27 5.2. 服务端函数实现 28 5.2.1. Stub部分实现 28 5.2.2. 用户部分实现 29 6. 参考资料 29
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值