zoukankan      html  css  js  c++  java
  • RPC-基于原生java实现

    一:什么是RPC

    远程过程调用(Remote Procedure Call)。就是调用其他业务方的方法的时候,就像是调用自己本地的方法一样。

    二:java rpc实现简介

    服务端(使用反射)

    (1)服务端写一个接口和一个接口的实现。

    (2)服务端维护一个map,key为接口的类名,value为接口的实现类。

    (3)服务端通过 ServerSocket 接收客户端发送过来的数据(接口的类名,方法名,请求参数)

    (4)服务端根据接口的类名和方法名得到对应实现类的方法,通过反射调用服务

    (5)把处理之后的结果通过 ServerSocket  返回给客户端

    客户端(动态代理)

    (1)把服务端的接口copy过来

    (2)写一个代理类,调用服务端方法的时候,通过代理类的 invoke 方法把服务需要的 接口类名,方法名,请求参数 通过 Socket 发送给服务端;接收服务端处理的结果

    三:具体实现的代码

    (1)服务端的接口声明

    public interface IHello {
    	String sayHello(String string);
    }
    

    (2)服务端接口的实现(真正干活的类)

    public class HelloServiceImpl implements IHello{
    
    	@Override
    	public String sayHello(String string) {
    		// TODO Auto-generated method stub
    		return "你好:" + string;
    	}
    }
    

    (3)服务端的服务类

    import java.io.IOException;
    import java.io.ObjectInputStream;
    import java.io.ObjectOutputStream;
    import java.lang.reflect.Method;
    import java.net.InetSocketAddress;
    import java.net.ServerSocket;
    import java.net.Socket;
    import java.util.HashMap;
    
    public class RpcServer {
    
        private static final HashMap<String, Class<?>> serviceRegistry = new HashMap<>();
        private int port;
    
        public RpcServer(int port) {
            this.port =port;
        }
    
        public RpcServer register(Class serviceInterface, Class impl) {
            serviceRegistry.put(serviceInterface.getName(), impl);
            return this;
        }
    
        public void run() throws IOException {
    
            ServerSocket server = new ServerSocket();
            server.bind(new InetSocketAddress (port));
            System.out.println("start server");
            ObjectInputStream input =null;
            ObjectOutputStream output =null;
            Socket socket=null;
            try {
                while(true){
                    socket = server.accept ();
                    input =new ObjectInputStream(socket.getInputStream());
                    String serviceName = input.readUTF();
                    String methodName = input.readUTF();
                    System.out.println ("客户端调用了 " + methodName + "方法");
                    Class<?>[] parameterTypes = (Class<?>[]) input.readObject();
                    Object[] arguments = (Object[]) input.readObject();
                    Class serviceClass = serviceRegistry.get(serviceName);
                    if (serviceClass == null) {
                        throw new ClassNotFoundException(serviceName + " not found");
                    }
                    Method method = serviceClass.getMethod(methodName, parameterTypes);
                    Object result = method.invoke(serviceClass.newInstance(), arguments);
                    output = new ObjectOutputStream (socket.getOutputStream());
                    output.writeObject(result);
                }
            } catch (Exception e){
                e.printStackTrace();
            }
        }
    
        public static void main(String[] args) throws IOException {
            new RpcServer (8888).register(IHello.class,HelloServiceImpl.class).run();
        }
    
    }
    

    (4)客户端的实现

    import java.io.ObjectInputStream;
    import java.io.ObjectOutputStream;
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    import java.net.InetSocketAddress;
    import java.net.Socket;
    
    import com.cs.rpc.nativ.server.IHello;
    
    public class RpcClientProxy<T> implements InvocationHandler {
    
        private  Class<T> serviceInterface;//被调用者的接口声明
        private InetSocketAddress addr;//被调用者的地址(ip+port)
    
        public RpcClientProxy(Class<T> serviceInterface, String ip,String port) {
            this.serviceInterface = serviceInterface;
            this.addr = new InetSocketAddress(ip, Integer.parseInt ( port ));
        }
    
        public T getClientIntance(){
            return (T) Proxy.newProxyInstance (serviceInterface.getClassLoader(),new Class<?>[]{serviceInterface},this);
        }
    
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    
            Socket socket = null;
            ObjectOutputStream output = null;
            ObjectInputStream input = null;
    
            try {
                // 2.创建Socket客户端,根据指定地址连接远程服务提供者
                socket = new Socket();
                socket.connect(addr);
    
                // 3.将远程服务调用所需的接口类、方法名、参数列表等编码后发送给服务提供者
                output = new ObjectOutputStream(socket.getOutputStream());
                output.writeUTF(serviceInterface.getName());
                output.writeUTF(method.getName());
                output.writeObject(method.getParameterTypes());
                output.writeObject(args);
    
                // 4.同步阻塞等待服务器返回应答,获取应答后返回
                input = new ObjectInputStream(socket.getInputStream());
                return input.readObject();
            } finally {
                if (socket != null) socket.close();
                if (output != null) output.close();
                if (input != null) input.close();
            }
        }
    
        public static void main(String[] args) {
            RpcClientProxy client = new RpcClientProxy<>(IHello.class,"localhost","8888");
            IHello hello = (IHello) client.getClientIntance ();
            System.out.println (hello.sayHello ( "socket rpc" ));
        }
    }
    

      

  • 相关阅读:
    egret 里面设置MovieClip的scale缩放值时,没有效果的情况
    游戏中的胜场数,净胜场数的计算
    使用Laya引擎和AS3(非原生AS)开发手游相关 总结常见bug
    javascript 一些注意事项
    JavaScript面向对象学习小结
    编写协议时注意事项
    Jenkins 在windows系统上的安装与使用
    LayaAir2.0 自定义Mesh-画圆环
    LayaAir2.0 自定义Mesh-画扇形
    Cocos Creator 使用 protobuf
  • 原文地址:https://www.cnblogs.com/CUI-S/p/11625718.html
Copyright © 2011-2022 走看看