基于Socket手写实现RPC框架

目录

服务端搭建

客户端

执行结果


RPC(Remote Procedure Call)简称远程过程调用,就是从一台机器(客户端)上通过参数传递的方式(就像调用了本地方法一样)调用另一台机器(服务器)上的一个方法(可以统称为服务)并得到返回的结果。

服务端搭建

IHelloService接口(就是客户端想远程调用的)

public interface IHelloService {

    String sayHello(String str);
}

HelloServiceImpl  IHelloService的实现类

public class HelloServiceImpl implements IHelloService{

    @Override
    public String sayHello(String str) {
        return "Hello:" + str;
    }
}

RpcRequest 客户端请求的封装类 实现了可序列化(因为要序列化这个类进行网络IO)

public class RpcRequest implements Serializable {

    //对象名
    private String className;
    //方法名
    private String methodName;
    //参数
    private Object[] params;
    //参数类型
    private Class[] type;

    public String getClassName() {
        return className;
    }

    public void setClassName(String className) {
        this.className = className;
    }

    public String getMethodName() {
        return methodName;
    }

    public void setMethodName(String methodName) {
        this.methodName = methodName;
    }

    public Object[] getParams() {
        return params;
    }

    public void setParams(Object[] params) {
        this.params = params;
    }

    public Class[] getType() {
        return type;
    }

    public void setType(Class[] type) {
        this.type = type;
    }
}

RpcProxyServer 进行服务的发布

public class RpcProxyServer {
    //发布service

    //创建线程池
    private final ExecutorService executorService = Executors.newCachedThreadPool();

    /**
     * 进行服务的发布
     * @param service 想要发布的服务
     * @param port  接受端口号
     */
    public void publish(Object service, int port) {

        //创建监听
        ServerSocket serverSocket = null;
        try {
            serverSocket = new ServerSocket(port);
            System.out.println("开启服务");
            while(true) {
                final Socket socket = serverSocket.accept();
                System.out.println("客户端" + socket.getPort() +"已连接");
                executorService.execute(new ProcessorHandler(service, socket));
            }

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}

ProcessorHandler 执行连接和网络IO的线程

public class ProcessorHandler implements Runnable{
    //service对象
    Object service;
    Socket socket;
    public ProcessorHandler(Object service, Socket socket) {
        this.service = service;
        this.socket = socket;
    }

    @Override
    public void run() {
        System.out.println("执行线程任务");
        ObjectInputStream inputStream = null;
        ObjectOutputStream outputStream = null;
        try {
            inputStream = new ObjectInputStream(socket.getInputStream());
            //反序列化
            RpcRequest request = (RpcRequest) inputStream.readObject();
            System.out.println("收到客户端通过网络IO发送过来的request");
            //执行这个请求方法
            Object result = invoke(request);
            //把得到的返回结果序列化发送
            outputStream = new ObjectOutputStream(socket.getOutputStream());
            outputStream.writeObject(result);
            outputStream.flush();
            System.out.println("把结果返回给客户端"+socket.getPort());
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //关闭流
        }

    }

    /**
     * 把接收的RpcRequest对象利用反射来执行 并获得返回结果
     * @param request
     */
    public Object invoke(RpcRequest request) throws Exception {
        //获取class
        Class clazz = Class.forName(request.getClassName());
        //获取方法名
        Method method = clazz.getMethod(request.getMethodName(),request.getType());
        //利用反射调用方法 获取返回结果
        Object result = method.invoke(service,request.getParams());
        return result;
    }
}

启动代码

public class Application {
    public static void main(String[] args) {
        //发布服务
        RpcProxyServer rpcProxyServer = new RpcProxyServer();
        HelloServiceImpl helloService = new HelloServiceImpl();
        //调用publish方法开启监听
        rpcProxyServer.publish(helloService,7486);
        System.out.println("end");
    }
}

客户端

RpcProxyClient JDK动态代理类  代理我们的调用方法

带你了解动态代理

public class RpcProxyClient{


    public <T> T creatProxyClient (Class<T> interfaceCls, String host, int port) {
        return (T) Proxy.newProxyInstance(interfaceCls.getClassLoader(),
                new Class<?>[]{interfaceCls}, new ProxyInvocationHandler(host,port) );
    }
}

ProxyInvocationHandler  JDK动态代理中InvocationHandler 的实现类

public class ProxyInvocationHandler implements InvocationHandler {
    String host;
    int port;

    public ProxyInvocationHandler(String host, int port) {
        this.host = host;
        this.port = port;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("调用l代理方法");
        //创建请求对象
        RpcRequest request = new RpcRequest();
        request.setClassName(method.getDeclaringClass().getName());
        request.setMethodName(method.getName());
        request.setParams(args);
        request.setType(method.getParameterTypes());
        //把请求对象发送给服务端
        RpcNetTransport transport = new RpcNetTransport(host,port);
        Object result = transport.send(request);
        return result;
    }
}

RpcNetTransport 进行网络IO所封装的工具类

public class RpcNetTransport {

    String host;
    int port;

    public RpcNetTransport(String host, int port) {
        this.host = host;
        this.port = port;
    }

    //给服务端发送数据
    public Object send(RpcRequest request) {
        Socket socket;
        ObjectOutputStream outputStream;
        ObjectInputStream inputStream;
        Object result = null;
        try {
            socket = new Socket(host, port);
            outputStream = new ObjectOutputStream(socket.getOutputStream());
            System.out.println("把request序列化通过网络IO发送给服务短");
            //序列化
            outputStream.writeObject(request);
            outputStream.flush();
            inputStream = new ObjectInputStream(socket.getInputStream());
            //反序列化
            result = inputStream.readObject();
            System.out.println("接收服务端返回的结果");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //关闭流
        }
        return result;
    }
}

main方法

public static void main( String[] args )
    {
       IHelloService iHelloService = null;
       //用代理的方式调用
         iHelloService = new RpcProxyClient().creatProxyClient(IHelloService.class,"localhost", 7486);
        System.out.println(iHelloService.sayHello("client-01"));//类似调用本地方法
    }

执行结果

客户端控制台

服务端控制台

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

w7486

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值