最近看到Dubbo大神写得使用Socket实现的简单的RPC调用,对RPC的理解更简单了,然后根据大神的代码自己也重构了一下。

RPC Server端代码,主要是使用ServerSocket获得rpc调用客户端发送过来的类信息,方法信息及方法参数信息,通过反射在RPCServer端进行代码执行,最后将执行结果发送给Socket,第一步需要首先执行RPCServer。

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ConcurrentHashMap;
/**
 * 服务端
 * @author tianjunwei
 */
public class RPCServer {

	public static ConcurrentHashMap<String, Object> classMap = new ConcurrentHashMap<String,Object>();

	public static void main(String [] args) throws Exception{
		System.err.println("server start");
		RPCServer.invoker(8080);
	}
	public static void invoker(int port) throws Exception{

		ServerSocket server = new ServerSocket(port);
		for(;;){
				try{
					final Socket socket = server.accept();
					new Thread(new Runnable() {
						ObjectOutputStream output =  null;
						@Override
						public void run() {
							try{
								try {
									output = new ObjectOutputStream(socket.getOutputStream());
									ObjectInputStream input = new ObjectInputStream(socket.getInputStream());
									String className = input.readUTF();
									String methodName = input.readUTF();
									Class<?>[] parameterTypes = (Class<?>[])input.readObject();
			                        Object[] arguments = (Object[])input.readObject();
									Object claszz = null;
									if(!classMap.containsKey(className)){
										try {
											claszz = Class.forName(className).newInstance();
											classMap.put(className, claszz);
										} catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) {
											e.printStackTrace();
										}
									}else {
										claszz = classMap.get(className);
									}
									Method method = claszz.getClass().getMethod(methodName, parameterTypes);
			                        Object result = method.invoke(claszz, arguments);
			                        output.writeObject(result);
								} catch (IOException | ClassNotFoundException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException | SecurityException e) {
									output.writeObject(e);
								}finally {
									output.close();
								}
							}catch(Exception e){
								e.printStackTrace();
							}finally {
								try {
									socket.close();
								} catch (IOException e) {
									e.printStackTrace();
								}
							}
						}
					}).start();
			}catch (Exception e) {
				e.printStackTrace();
			}
		}
	}
}

RPC 客户端代码,这里利用了代理机制的特性,在执行具体的方法时执行远程调用,执行方法时会调用invoke方法,这样就可以通过Socket向RPCServer发送需要执行的方法的信息,并且获取执行后的结果并返回。

public class RPCProxy {

	 @SuppressWarnings("unchecked")
	public static <T> T create(Object target){

		 return (T) Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(), new InvocationHandler(){

			@SuppressWarnings("resource")
			@Override
			public Object invoke(Object proxy, Method method, Object[] args)
					throws Throwable {
				 Socket socket = new Socket("localhost", 8080);
				 ObjectOutputStream output = new ObjectOutputStream(socket.getOutputStream());
                 try {
                	 output.writeUTF(target.getClass().getName());
                     output.writeUTF(method.getName());
                     output.writeObject(method.getParameterTypes());
                     output.writeObject(args);
                     ObjectInputStream input = new ObjectInputStream(socket.getInputStream());
                     try {
                         Object result = input.readObject();
                         if (result instanceof Throwable) {
                             throw (Throwable) result;
                         }
                         return result;
                     } finally {
                         input.close();
                     }
                 } finally {
                     output.close();
                     socket.close();
                 }
			}

		 });
	 }
}

HelloRpc接口:

public interface HelloRpc {
	String hello(String name);
}

HelloRpcImpl实现类:

public class HelloRpcImpl implements HelloRpc {

	@Override
	public String hello(String name) {
		return "hello "+name;
	}

}

Main函数操作:

public class Main {

	public static void main(String [] args){
		HelloRpc helloRpc = new HelloRpcImpl();
		helloRpc = RPCProxy.create(helloRpc);
		System.err.println(helloRpc.hello("rpc"));
	}
}

执行结果:

hello rpc

通过以上这个示例我们可能会对一些RPC框架的实现原理有一定的了解,比如和我之前发表的Hessian源码分析有一些相似的地方。示例源码地址github,当然这个实现只是作为一些简单的原理说明,还有很多不足的地方。

简单RPC之Socket实现的更多相关文章

  1. 简单RPC实现之Netty实现

    所谓RPC就是远程方法调用(Remote  Process Call ),简单的来说就是通过MQ,TCP,HTTP或者自己写的网络协议来传输我要调用对方的什么接口,对方处理之后再把结果返回给我.就这么 ...

  2. RPC笔记之初探RPC:DIY简单RPC框架

    一.什么是RPC RPC(Remote Procedure Call)即远程过程调用,简单的说就是在A机器上去调用B机器上的某个方法,在分布式系统中极其常用. rpc原理其实很简单,比较容易理解,在r ...

  3. rpc、socket、mq

    关于RPC与MQ异同的理解 相同:1.都利于大型系统的解耦:2.都提供子系统之间的交互,特别是异构子系统(如java\node等不同开发语言):不同:1.RPC侧重功能调用,因此多半是同步的:备注:也 ...

  4. RPC和Socket

    RPC和Socket的区别 rpc是通过什么实现啊?socket! RPC(Remote Procedure Call,远程过程调用)是建立在Socket之上的,出于一种类比的愿望,在一台机器上运行的 ...

  5. Java实现简单RPC框架(转)

    一.RPC简介 RPC,全称Remote Procedure Call, 即远程过程调用,它是一个计算机通信协议.它允许像本地服务一样调用远程服务.它可以有不同的实现方式.如RMI(远程方法调用).H ...

  6. winsock2之最简单的win socket编程

    原文:winsock2之最简单的win socket编程 server.cpp #include <WINSOCK2.H> #include <stdio.h> #pragma ...

  7. UEditor编辑器和php简单的实现socket通信

    一.UEditor编辑器 使用这个编辑器是需要先下载编辑器文件,记得下载的时候放入自己的网站中,既然是php中使用,自然我下载的就是php的UEditor编辑器了,然后是utf-8的 其实使用很简单, ...

  8. 简单的异步Socket实现——SimpleSocket_V1.1

    简单的异步Socket实现——SimpleSocket_V1.1 笔者在前段时间的博客中分享了一段简单的异步.net的Socket实现.由于是笔者自己测试使用的.写的很粗糙.很简陋.于是花了点时间自己 ...

  9. RPC和Socket,RMI和RPC之间的关系

    远程通信机制RPC与RMI的关系 http://blog.csdn.net/zolalad/article/details/25161133       1.RPC RPC(Remote Proced ...

随机推荐

  1. 【USACO12JAN】视频游戏的连击Video Game Combos

    题目描述 Bessie is playing a video game! In the game, the three letters 'A', 'B', and 'C' are the only v ...

  2. ●BZOJ 3129 [Sdoi2013]方程

    题链: http://www.lydsy.com/JudgeOnline/problem.php?id=3129 题解: 容斥,扩展Lucas,中国剩余定理 先看看不管限制,只需要每个位置都是正整数时 ...

  3. hdu4605 树状数组+离散化+dfs

    Magic Ball Game Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) ...

  4. css3中-moz、-ms、-webkit各什么意思

    1.-moz代表firefox浏览器私有属性 2.-ms代表ie浏览器私有属性 3.-webkit代表safari.chrome私有属性 这些是为了兼容老版本的写法,比较新版本的浏览器都支持直接写:b ...

  5. node的异常处理

    Node是单线程运行环境,一旦抛出的异常没有被捕获,就会引起整个进程的崩溃.所以,Node的异常处理对于保证系统的稳定运行非常重要. node的处理方法: 1.使用throw语句抛出异常 常用的捕获异 ...

  6. Kibana插件sentinl使用教程

    简介 对于Kibana的一些数据我们有时候是想要对某些字段进行持续关注的,这时候通过报警的手段就可以大幅提升对这些信息状态了解的及时性及可靠性.使用sentinl插件就可以帮助我们实现这个功能. 此教 ...

  7. manjaro备忘录

    updated 2018/4/3 manjaro 使用Linux发行版时需要注意几个方面的问题: 包管理器 包管理器无疑时各家发行版的最大特色之一.软件同时也是一个平台是否能够产生足够的吸引力的来源之 ...

  8. Hadoop系列:(一)hdfs文件系统的基本操作

    可以执行所有常用的Linux文件操作命令(读取文件,新建文件,移动文件,删除文件,列表文件等) 1.help命令获取没个命令的帮助 [cloudera@quickstart ~]$ hadoop fs ...

  9. Emacs Python 自动补全--Elpy

    安装方法: 首先,安装一些依赖包: # Either of these pip install rope pip install jedi # flake8 用来检查语法错误 pip install ...

  10. 从头开始搭建一个VSCode+NetCore的项目

    看这个前,先要对VS开发C#有所了解 获取作案工具 NetCore SDK https://www.microsoft.com/net/learn/get-started/windows 安装 建立工 ...