基于Socket实现简单RPC框架

废话不多说,直接上代码:

1. RpcServer:rpc服务端,用于启动Socket监听端口

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class RpcServer {

    // 监听端口
    private int port = 8888;
    // 自定义线程池,用于处理客户端请求
    private static ThreadPoolExecutor threadPool = new ThreadPoolExecutor(5, 10, 3000L, TimeUnit.SECONDS, new ArrayBlockingQueue<>(100));

    // 模拟spring 注入Bean容器
    static Map<String, Object> beanContainer = new HashMap<>();
    static {
        beanContainer.put("helloService", new HelloServiceImpl());
    }

    public void start() {
        ServerSocket ss = null;
        try {
            ss = new ServerSocket(port);
        } catch (IOException e) {
            e.printStackTrace();
        }
        while(true) {
            try {
                System.out.println("服务端启动成功,等待请求。。。");
                Socket s = ss.accept();
                threadPool.submit(new RpcServerHandler(s));
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

2. RpcServerHandler:处理客户端请求

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Method;
import java.net.Socket;

public class RpcServerHandler implements Runnable{

    Socket s;

    public RpcServerHandler(Socket s) {
        this.s = s;
    }

    @Override
    public void run() {
        System.out.println("服务端开始处理请求");
        ObjectInputStream ois = null;
        ObjectOutputStream oos = null;
        try {
            ois = new ObjectInputStream(s.getInputStream());
            // 获取接口名称
            String serviceName = ois.readUTF();
            // 获取目标方法名
            String methodName = ois.readUTF();
            // 具体的实现类beanName
            String beanName = ois.readUTF();
            // 使用反射调用目标方法
            Class<?> c = Class.forName(serviceName);
            Method m = c.getMethod(methodName);
            Object result = m.invoke(RpcServer.beanContainer.get(beanName));
            oos = new ObjectOutputStream(s.getOutputStream());
            // 方法返回值返回客户端
            oos.writeObject(result);
            System.out.println("服务端处理请求成功");
        } catch (Exception e) {
            System.out.println("RpcHandler error: " + e.getMessage());
            e.printStackTrace();
        } finally {
            if(null != ois) {
                try {
                    ois.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(null != oos) {
                try {
                    oos.flush();
                    oos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

3. RpcClientProxy: 客户端接口代理类

import org.springframework.cglib.proxy.InvocationHandler;
import org.springframework.cglib.proxy.Proxy;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Method;
import java.net.Socket;

public class RpcClientProxy {
    // 服务端IP
    private final static String ipAddress = "localhost";
    // 服务端端口
    private final static int port = 4444;

    /* 创建代理对象,在代理对象中使用Socket请求服务端获取数据 */
    public static Object proxy(Class interfaces, String beanName) {
        return Proxy.newProxyInstance(RpcClientProxy.class.getClassLoader(), new Class[]{interfaces}, new InvocationHandler() {
            @Override
            public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
                ObjectInputStream ois = null;
                ObjectOutputStream oos = null;
                try {
                    System.out.println("客户端开始请求数据");
                    Socket s = new Socket(ipAddress, port);
                    oos = new ObjectOutputStream(s.getOutputStream());
                    oos.writeUTF(interfaces.getName());
                    oos.writeUTF(method.getName());
                    oos.writeUTF(beanName);
                    oos.flush();
                    ois = new ObjectInputStream(s.getInputStream());
                    Object obj = ois.readObject();
                    return obj;
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    if(null != ois) {
                        try {
                            ois.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                    if(null != oos) {
                        try {
                            oos.flush();
                            oos.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }
                return null;
            }
        });
    }
}

4. HelloService : 测试接口类

public interface HelloService {

    String hello();
}

5. HelloServiceImpl: 测试接口实现类

public class HelloServiceImpl implements HelloService {

    @Override
    public String hello() {
        System.out.println("RpcServer return hello world");
        return "hello world";
    }
}

6. RpcClient 测试类

public class RpcClient {

    public static void main(String[] args) {
        RpcServer rpcServer = new RpcServer();
        // 异步启动服务端
        new Thread(new Runnable() {
            @Override
            public void run() {
                rpcServer.start();
            }
        }).start();

        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("开始启动rpc客户端");

        // 模拟客户端调用接口
        for(int i = 0; i < 2; i++) {
            HelloService helloService = (HelloService) RpcClientProxy.proxy(HelloService.class, "helloService");
            String s = helloService.hello();
            System.out.println(s);
        }
    }
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值