自行实现一个简单的RMI

在教主的带领下,完成了一个很简单的RMI工具。就当是练习网络编程吧。

RMI(Remote Method Invocation),远程方法调用。

涉及两个网络端。其核心思想是,一个端可以通过调用另一个端的方法,实现相关功能。
一个端“执行”一个方法,而这个方法的实际执行是在另一端进行的!

要进行远程方法调用,那么,两个端都应该有相同的类,相同的方法。一个端执行一个方法,其实本质是通过调用这个类的代理对象的方法,在其中拦截这个方法,将这个方法的哈希值和参数,通过网络通讯传输给另一端;另一端根据哈希值和参数,能唯一的确定到那个方法,执行完成后将结果返回给对端。

我采用的是短连接,jdk代理。

大致的处理流程:

 我的思路:

建立RPC服务器端:

主要有两个大的步骤:

1、需要给RpcBeanFactory注入方法的哈希值和方法参数(这两个数据相同,就能保证客户机准确的调用远程方法)。

注入的具体分析:

static void doRegist(RpcBeanFactory rpcBeanFactory, Class<?> interfaces, Object object) {
        Method[] methods  = interfaces.getDeclaredMethods();
        for (Method method : methods) {
            String rpcBeanId = String.valueOf(method.toString().hashCode());
            RpcBeanDefination rpcBeanDefination = new RpcBeanDefination();
            rpcBeanDefination.setKlass(interfaces);
            rpcBeanDefination.setMethod(method);
            rpcBeanDefination.setObject(object);

            rpcBeanFactory.AddRpcBean(rpcBeanId, rpcBeanDefination);
        }
    }

通过传过来的接口,得到这个接口中的所有方法,遍历,把每个方法的信息都注入到RpcBeanFactory的Map中。

2、RpcServer需要一直侦听客户机的请求,如果有请求,那么RpcServerExecutor进行具体的处理。

分析:

@Override
    public void run() {
        try {
            // 接收Rpc客户端传递的rpcBeanId和参数
            String rpcBeanId = ois.readUTF();
            Object[] parameters = (Object[]) ois.readObject();
            showParameters(parameters);
            // 定位相关类,对象和方法
            RpcBeanDefination rpcBeanDefination;
            rpcBeanDefination = rpcServer.getRpcBeanFactory().getRpcBean(rpcBeanId);
            // 执行Rpc客户端要求执行的方法
            Method method = rpcBeanDefination.getMethod();
            Object object = rpcBeanDefination.getObject();
            Object result = method.invoke(object, parameters);
            // 向客户端返回执行结果
            oos.writeObject(result);
        } catch (IOException | IllegalAccessException | InvocationTargetException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } finally {
            closeSocket();
        }
    }

 这是RpcServerExecutor中的处理,接收->定位->执行->返回结果。

建立RPC客户机端:

1、在代理对象的方法中,调用RpcClientExecutor。

/*jdk代理*/
    public Object getProxy(Class<?> klass) {
        // 判断klass是否是接口,若不是,则应该采用cglib代理模式
        return Proxy.newProxyInstance(klass.getClassLoader(), new Class<?>[] { klass }, new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                String rpcBeanId = String.valueOf(method.toString().hashCode());
                Object result = rpcClientExecutor.rpcExecutor(rpcBeanId, args);

                return result;
            }
        });
    }

 给方法生成哈希值,调用rpcExecutor。

2、执行RpcClientExecutor。

<T> T rpcExecutor(String rpcBeanId, Object[] para) throws IOException, ClassNotFoundException {
        Socket socket = new Socket(rpcServerIp, rpcServerPort);
        ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
        // 给RPC服务器发送rpcBeanId和参数
        oos.writeUTF(rpcBeanId);
        oos.writeObject(para);
        // 接收RPC服务器执行的结果,并返回
        ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
        Object result = ois.readObject();

        closeSocket(ois, oos, socket);

        return (T) result;
    }

客户端处理很简单:发送信息->接收信息。

源码链接:

https://github.com/yangchaoy259189888/A-simple-implementation-of-RMI/

 

发布了71 篇原创文章 · 获赞 208 · 访问量 16万+
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 书香水墨 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览