博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
手写一个简单的RPC
阅读量:3962 次
发布时间:2019-05-24

本文共 15270 字,大约阅读时间需要 50 分钟。

公共类

public class User implements Serializable {
private static final long serialversionUID = 1L; private Integer id; private String name; public User(Integer id, String name) {
this.id = id; this.name = name; } public static long getSerialversionUID() {
return serialversionUID; } public Integer getId() {
return id; } public void setId(Integer id) {
this.id = id; } public String getName() {
return name; } public void setName(String name) {
this.name = name; } @Override public String toString() {
return "User{" + "id=" + id + ", name='" + name + '\'' + '}'; }}
public interface IUserService {
public User findUserById(Integer id);}
public class UserServiceImpl implements IUserService {
@Override public User findUserById(Integer id) {
return new User(id, "Alice"); }}

版本一

public class Client {
public static void main(String[] args) throws IOException {
Socket socket = new Socket("127.0.0.1", 8888); ByteArrayOutputStream baos = new ByteArrayOutputStream(); DataOutputStream dos = new DataOutputStream(baos); dos.writeInt(123); socket.getOutputStream().write(baos.toByteArray());//把123变成二进制数组 在网络中传输的数据归根结底都是二进制数据 socket.getOutputStream().flush();//清空缓冲区 将数据强行输出去 DataInputStream dis = new DataInputStream(socket.getInputStream()); int id = dis.readInt(); String name = dis.readUTF(); User user = new User(id, name); System.out.println(user); dos.close(); socket.close(); }}
public class Server {
private static boolean running = true; public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(8888); while (running) {
Socket s = serverSocket.accept(); process(s); s.close(); } serverSocket.close(); } public static void process(Socket socket) throws IOException {
InputStream in = socket.getInputStream(); OutputStream out = socket.getOutputStream(); DataInputStream dis = new DataInputStream(in); DataOutputStream dos = new DataOutputStream(out); int id = dis.readInt(); IUserService service = new UserServiceImpl(); User user = service.findUserById(id); dos.writeInt(user.getId()); dos.writeUTF(user.getName()); dos.flush(); }}

版本二

public class Client {
public static void main(String[] args) throws IOException {
Stub stub = new Stub();//这么写就给你屏蔽了许多细节 System.out.println(stub.findUserById(223)); }}
//将网络进一步的封装public class Stub {
public User findUserById(Integer id) throws IOException {
Socket socket = new Socket("127.0.0.1", 8888); ByteArrayOutputStream baos = new ByteArrayOutputStream(); DataOutputStream dos = new DataOutputStream(baos); dos.writeInt(id); OutputStream out = socket.getOutputStream(); out.write(baos.toByteArray()); out.flush(); DataInputStream dis = new DataInputStream(socket.getInputStream()); int readId = dis.readInt(); String readName = dis.readUTF(); User user = new User(readId, readName); dis.close(); dos.close(); socket.close(); return user; }}
public class Server {
private static boolean running = true; public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(8888); while (running) {
Socket s = serverSocket.accept(); process(s); s.close(); } serverSocket.close(); } public static void process(Socket socket) throws IOException {
InputStream in = socket.getInputStream(); OutputStream out = socket.getOutputStream(); DataInputStream dis = new DataInputStream(in); DataOutputStream dos = new DataOutputStream(out); int id = dis.readInt(); IUserService service = new UserServiceImpl(); User user = service.findUserById(id); dos.writeInt(user.getId()); dos.writeUTF(user.getName()); dos.flush(); }}

版本三

public class Client {
public static void main(String[] args) {
IUserService service = Stub.getStub(); System.out.println(service.findUserById(123));//实际调的是invoke这个方法 }}
public class Server {
private static boolean running = true; public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(8888); while (running) {
Socket s = serverSocket.accept(); process(s); s.close(); } serverSocket.close(); } public static void process(Socket socket) throws IOException {
InputStream in = socket.getInputStream(); OutputStream out = socket.getOutputStream(); DataInputStream dis = new DataInputStream(in); DataOutputStream dos = new DataOutputStream(out); int id = dis.readInt(); IUserService service = new UserServiceImpl(); User user = service.findUserById(id); dos.writeInt(user.getId()); dos.writeUTF(user.getName()); dos.flush(); }}
public class Stub {
public static IUserService getStub() {
InvocationHandler h = new InvocationHandler() {
/** * * @param proxy 代理的对象是谁 * @param method 调的是哪个方法 findUserById() * @param args 这个方法传了哪些参数 123 * @return * @throws Throwable */ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("你好"); Socket s = new Socket("127.0.0.1", 8888); ByteArrayOutputStream baos = new ByteArrayOutputStream(); DataOutputStream dos = new DataOutputStream(baos); dos.writeInt(123); s.getOutputStream().write(baos.toByteArray()); s.getOutputStream().flush(); DataInputStream dis = new DataInputStream(s.getInputStream()); int id = dis.readInt(); String name = dis.readUTF(); User user = new User(id, name); dos.close(); s.close(); return user; } }; //第一个参数:被代理对象的类加载器 //第二个参数:被代理对象的接口 IUserService本来就是个接口 //第三个参数: Object o = Proxy.newProxyInstance(IUserService.class.getClassLoader(), new Class[] {
IUserService.class}, h); return (IUserService) o; }}

版本四

public class Client {
public static void main(String[] args) {
IUserService stub = Stub.getStub(); System.out.println(stub.findUserById(123));//你调findUserById这个方法会给你调invoke这个方法 }}
public class Server {
private static boolean running = true; public static void main(String[] args) throws Exception {
ServerSocket ss = new ServerSocket(8888); while (running) {
Socket s = ss.accept(); process(s); s.close(); } } private static void process(Socket s) throws Exception {
InputStream in = s.getInputStream(); OutputStream out = s.getOutputStream(); ObjectInputStream ois = new ObjectInputStream(in); DataOutputStream dos = new DataOutputStream(out); String methodName = ois.readUTF();//把方法名读进来 Class[] parameterTypes = (Class[])ois.readObject();//参数类型读进来 Object[] args = (Object[])ois.readObject();//参数读进来 IUserService service = new UserServiceImpl(); Method method = service.getClass().getMethod(methodName, parameterTypes);//通过反射的方式找到类里面的方法 User user = (User)method.invoke(service,args);//对方法进行调用 dos.writeInt(user.getId());//返回数据 dos.writeUTF(user.getName()); dos.flush(); }}
public class Stub {
public static IUserService getStub() {
InvocationHandler h = new InvocationHandler() {
/** * * @param proxy 代理的对象是谁 * @param method 调的是哪个方法 findUserById() * @param args 这个方法传了哪些参数 123 * @return * @throws Throwable */ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Socket s = new Socket("127.0.0.1", 8888); ObjectOutputStream oos = new ObjectOutputStream(s.getOutputStream()); //把方法的信息通过网络传过去 String methodName = method.getName();//现在调用方法的name //通过 方法名 和 参数列表 就可以知道你要调用哪个方法了 Class
[] parameterTypes = method.getParameterTypes();//方法的参数类型 防止出现方法重载 来辨认哪个方法 //将一个方法的基本信息都写出去 oos.writeUTF(methodName); oos.writeObject(parameterTypes); oos.writeObject(args); oos.flush(); DataInputStream dis = new DataInputStream(s.getInputStream()); int id = dis.readInt(); String name = dis.readUTF(); User user = new User(id, name); dis.close(); s.close(); return user; } }; //第一个参数:被代理对象的类加载器 //第二个参数:被代理对象的接口 IUserService本来就是个接口 //第三个参数: Object o = Proxy.newProxyInstance(IUserService.class.getClassLoader(), new Class[] {
IUserService.class}, h); return (IUserService) o; }}

版本五

public class Client {
public static void main(String[] args) {
IUserService stub = Stub.getStub(); System.out.println(stub.findUserById(123));//你调findUserById这个方法会给你调invoke这个方法 这里给你返回的 }}
public class Server {
private static boolean running = true; public static void main(String[] args) throws Exception {
ServerSocket ss = new ServerSocket(8888); while (running) {
Socket s = ss.accept(); process(s); s.close(); } } private static void process(Socket s) throws Exception {
InputStream in = s.getInputStream(); OutputStream out = s.getOutputStream(); ObjectInputStream ois = new ObjectInputStream(in); DataOutputStream dos = new DataOutputStream(out); String methodName = ois.readUTF();//把方法名读进来 Class[] parameterTypes = (Class[])ois.readObject();//参数类型读进来 Object[] args = (Object[])ois.readObject();//参数读进来 IUserService service = new UserServiceImpl(); Method method = service.getClass().getMethod(methodName, parameterTypes);//通过反射的方式找到类里面的方法 User user = (User)method.invoke(service,args);//对方法进行调用 ObjectOutputStream oos = new ObjectOutputStream(out);//将输出的结果封装成Object //直接把结果user对象返回给客户端 oos.writeObject(user); dos.flush(); }}
public class Stub {
public static IUserService getStub() {
InvocationHandler h = new InvocationHandler() {
/** * * @param proxy 代理的对象是谁 * @param method 调的是哪个方法 findUserById() * @param args 这个方法传了哪些参数 123 * @return * @throws Throwable */ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Socket s = new Socket("127.0.0.1", 8888); ObjectOutputStream oos = new ObjectOutputStream(s.getOutputStream()); //把方法的信息通过网络传过去 String methodName = method.getName();//现在调用方法的name //通过 方法名 和 参数列表 就可以知道你要调用哪个方法了 Class[] parameterTypes = method.getParameterTypes();//方法的参数类型 防止出现方法重载 来辨认哪个方法 //将一个方法的基本信息都写出去 oos.writeUTF(methodName); oos.writeObject(parameterTypes); oos.writeObject(args);//args就是参数 oos.flush(); DataInputStream dis = new DataInputStream(s.getInputStream()); int id = dis.readInt(); String name = dis.readUTF(); User user = new User(id, name); dis.close(); s.close(); return user; } }; //第一个参数:被代理对象的类加载器 //第二个参数:被代理对象的接口 IUserService本来就是个接口 //第三个参数: Object o = Proxy.newProxyInstance(IUserService.class.getClassLoader(), new Class[] {
IUserService.class}, h); return (IUserService) o; }}

版本六

public class Client {
public static void main(String[] args) {
//传入一个类 给你返回一个指定对象 这是一个代理类 IUserService service = (IUserService) Stub.getStub(IUserService.class); System.out.println(service.findUserById(123)); }}
public class Server {
private static boolean running = true; public static void main(String[] args) throws Exception {
ServerSocket ss = new ServerSocket(8888); while (running) {
Socket s = ss.accept(); process(s); s.close(); } } private static void process(Socket s) throws Exception {
InputStream in = s.getInputStream(); OutputStream out = s.getOutputStream(); ObjectInputStream ois = new ObjectInputStream(in); //这几个获取的顺序和你客户端写出的顺序一样吧 //String clazzName = ois.readUTF(); String methodName = ois.readUTF(); Class[] parameterTypes = (Class[])ois.readObject(); Object[] args = (Object[])ois.readObject(); Class clazz = null; //从服务注册表中找到具体的类 这个是具体的实现类 clazz = UserServiceImpl.class; Method method = clazz.getMethod(methodName, parameterTypes); //这里才是调用的方法 客户端把你需要调用的方法信息给你 //首先我要创建一个对象才能调用里面的方法 clazz.newInstance() 反射创建对象 Object o = (Object) method.invoke(clazz.newInstance(), args); ObjectOutputStream oos = new ObjectOutputStream(out); oos.writeObject(o); oos.flush(); }}
public class Stub {
//这样可以给你返回一个任意类型的对象 public static Object getStub(Class clazz) {
InvocationHandler h = new InvocationHandler() {
@Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Socket s = new Socket("127.0.0.1", 8888); ObjectOutputStream oos = new ObjectOutputStream(s.getOutputStream()); String clazzName = clazz.getName();//获取类的名字 String methodName = method.getName(); Class
[] parameterTypes = method.getParameterTypes(); //oos.writeObject(clazzName); oos.writeUTF(methodName); oos.writeObject(parameterTypes); oos.writeObject(args); oos.flush(); ObjectInputStream ois = new ObjectInputStream(s.getInputStream()); Object o = ois.readObject(); oos.close(); s.close(); return o; } }; Object o = Proxy.newProxyInstance(clazz.getClassLoader(), new Class[]{
clazz}, h); return o; }}

转载地址:http://lmhzi.baihongyu.com/

你可能感兴趣的文章
golang ubuntu 配置 笔记
查看>>
vim 常用命令
查看>>
golang 开源项目
查看>>
ubntu 开发服务进程
查看>>
linux 常用命令以及技巧
查看>>
记录1年免费亚马逊AWS云服务器申请方法过程及使用技巧
查看>>
golang文章
查看>>
Source Insight 经典教程
查看>>
快速打开菜单附件中的工具
查看>>
Windows系统进程间通信
查看>>
linux exec的用法
查看>>
C语言中如何使用宏
查看>>
Http与RPC通信协议的比较
查看>>
Source Insight的对齐问题
查看>>
ubuntu设置开机默认进入字符界面方法
查看>>
chrome 快捷键
查看>>
Linux下buffer和cache的区别
查看>>
程序员不应该再犯的五大编程错误
查看>>
[转载][转帖]Hibernate与Sleep的区别
查看>>
Linux系统的默认编码设置
查看>>