手写简易版RPC 通信

手写RPC 通信,在客户端转入类,方法给服务端,服务端执行后,将执行结果通过socket发回给客户端:

坑记录: 客户端因为只知道调用 方法的接口,不知道接口方法的实现,所以在客户端生成代理对象的时候,传入是参数应该接口的class type, 那在代码函数中,生成代理对象的newProxyInstance时, 第二个参数就不能为clazz.getInterface, 而应该用new class[]{clazz}. 因为传入的参数已经是interface type, 就不用再getInterface()了。

以下是客户端代码:

package com.rpc.yubo;

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.Socket;

public class ClientProxyObject<T> {
    
    public T genProxy(Class<T> clazz)
    {
        return (T) (
                    Proxy.newProxyInstance(
                            clazz.getClassLoader(), 
                            new Class[] {clazz}, // 注意这里不是用clazz.getInterfaces(), 因为clazz 本来就是interface了
                            //clazz.getInterfaces(), 
                            new InvocationHandler() {
                                                        @Override
                                                        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable{
                                                            // write method to server
                                                            Socket s = new Socket("127.0.0.1", 8123);
                                                            Object obj = null;
                                                            
                                                            ObjectOutputStream oos = new ObjectOutputStream(s.getOutputStream());
                                                            try
                                                            {
                                                                oos.writeUTF(method.getName());
                                                                oos.writeObject(args);
                                                                oos.flush();
                                                            }
                                                            catch(Exception ex)
                                                            {
                                                                ex.printStackTrace();
                                                            }
                                                            
                                                            // get result and return
                                                            ObjectInputStream ois = new ObjectInputStream(s.getInputStream());
                                                            try
                                                            {
                                                                obj = ois.readObject();
                                                                
                                                            }
                                                            catch(Exception ex)
                                                            {
                                                                ex.printStackTrace();
                                                            }
                                                            finally
                                                            {
                                                                s.close();
                                                            }
                                                            
                                                            return obj;
                                                        }
                                                        
                                                    }
                                             )    
                    
                                 );
    }

    public static void main(String[] args) throws InterruptedException {
        ClientProxyObject<IHello> helloProxy = new ClientProxyObject<>();
        IHello hello = helloProxy.genProxy(IHello.class); // 注意这里传的接口,不是实现类,因为客户端不会知道实现类
        String s = hello.sayHello("hi 1 from client");
        System.out.println( "xx" + s);
        while(true) {
            System.out.println( "xxx" + s);
            Thread.sleep(100000000);
        }
    }

}

 

客户端和服务端均有以下代码:

package com.rpc.yubo;

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

服务端代码:

public class IHelloImpl implements IHello {

    @Override
    public String sayHello(String args) {
        // TODO Auto-generated method stub
        System.out.println("Server say" + args);
        return args + "--hehe";
    }
}

服务端代码:

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

public class ServerPulisher {
    // create serverSocket to accept 
    // read method
    // run method 
    // write result object
    
    public void pulicServer() throws IOException
    {
        IHello hello = new IHelloImpl();
        ServerSocket socket = new ServerSocket(8123);
        
        while(true)
        {
            System.out.println("Server start:");
            Socket client = socket.accept();
            try(ObjectInputStream ois = new ObjectInputStream( client.getInputStream() )){
                String method = ois.readUTF();
                Object [] objects = (Object [])ois.readObject();
                
                Class<?>[] types = new Class[objects.length];
                for(int i = 0; i < objects.length; i++)
                {
                    types[i] = objects[i].getClass();
                }
                
                System.out.println("Server received:" + method);
                
                Method m = IHelloImpl.class.getMethod(method, types);                
                Object result = m.invoke(hello, objects);
                
                
                ObjectOutputStream oos = new ObjectOutputStream(client.getOutputStream());
                try
                {
                    System.out.println("Server write:" + result.toString());
                    oos.writeObject(result);
//                    oos.writeObject("xxx");
                    //oos.flush();
                }
                catch(Exception ex) {
                    ex.printStackTrace();
                }
                
            }
            catch(Exception ex) {
                ex.printStackTrace();
            }
        }
        
    }
}

服务端代码:

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

public class ServerService {

    public static void main(String[] args) throws IOException {
        // TODO Auto-generated method stub
        // create server object
        // run accept
        new ServerPulisher().pulicServer();
    }

}
 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值