最近看到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. hihocoder #1142 : 三分·三分求极值

    时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 这一次我们就简单一点了,题目在此: 在直角坐标系中有一条抛物线y=ax^2+bx+c和一个点P(x,y),求点P到抛物线的 ...

  2. Java多线程基础总结

    一.线程和进程关系 二.创建方式1.继承Thread类,重写run方法2.实现Runable接口,重写run方法3.使用匿名内部类 三.API接口start()currentThread() 获取当前 ...

  3. c语言3种链接属性: 外部(external), 内部(internal),无设置(none)

    c语言中,多个文件组合的时候,有可能标示名相同,那么这个时候编译器如何判别的呢?    c语言中有3种链接属性: 外部(external), 内部(internal),无设置(none)    外部( ...

  4. Linux基本知识总结

    一.Linux的基本介绍 起源:大家知道先有Unix,后有的linux就行了,其他的细节可以自己查阅资料. 特点:开源!!! 安全(Linux的病毒远少于window). 免费(商业公司最喜欢这一点) ...

  5. 华科机考:N阶楼梯上楼

    时间限制:1秒空间限制:32768K 题目描述 N阶楼梯上楼问题:一次可以走两阶或一阶,问有多少种上楼方式.(要求采用非递归) 输入描述: 输入包括一个整数N,(1<=N<90). 输出描 ...

  6. 《Java技术》第三次作业

    (一)学习总结 1.阅读下面程序,分析是否能编译通过?如果不能,说明原因.应该如何修改?程序的运行结果是什么?为什么子类的构造方法在运行之前,必须调用父 类的构造方法?能不能反过来? class Gr ...

  7. GNS3 1.4.0b3 MSTP多生成树配置实验

    一.实验目标 掌握MSTP多生成树配置,VLAN配置,trunk配置,etherchannel配置 二.实验平台 系统:WIN7以上windows,X64版本.CPU支持虚拟化,并在BIOS中开启虚拟 ...

  8. Leetcode Scratching Recorder

    Author: Zhong-Liang Xiang Start from: August 7th, 2017 这个题为连滚带爬的Leetcode填坑记录就这么开始了. 网上看了看, 一堆小伙从2014 ...

  9. 使用Web Audio API绘制音波图

    摘要:Web Audio API是对<audio> 标签功能上的补充,我们可以用它完成混音.音效.平移等各种复杂的音频处理,本文简单的使用其完成音波图的绘制. PS:本例子使用ES6编程, ...

  10. About Windows 10 April 2018 Update

    在四月的最后一天,微软终于正式发布了 Windows 10 的又一次重大更新,并命名为 Windows 10 四月更新,轮压哨,我软确实谁也不服:再晚一天,我软改名部门恐怕又要发挥作用了,毕竟我软存在 ...