RPC是在Socket的基础上实现的,它比socket需要更多的网络和系统资源。RPC(Remote Procedure Call,远程过程调用)是建立在Socket之上的,出于一种类比的愿望,在一台机器上运行的主程序,可以调用另一台机器上准备好的子程序,就像LPC(本地过程调用).

简单RPC之Socket实现
2016年10月28日 10:54:47

阅读数:2663

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

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

  1. import java.io.IOException;
  2. import java.io.ObjectInputStream;
  3. import java.io.ObjectOutputStream;
  4. import java.lang.reflect.InvocationTargetException;
  5. import java.lang.reflect.Method;
  6. import java.net.ServerSocket;
  7. import java.net.Socket;
  8. import java.util.concurrent.ConcurrentHashMap;
  9. /**
  10. * 服务端
  11. * @author tianjunwei
  12. */
  13. public class RPCServer {
  14. public static ConcurrentHashMap<String, Object> classMap = new ConcurrentHashMap<String,Object>();
  15. public static void main(String [] args) throws Exception{
  16. System.err.println("server start");
  17. RPCServer.invoker(8080);
  18. }
  19. public static void invoker(int port) throws Exception{
  20. ServerSocket server = new ServerSocket(port);
  21. for(;;){
  22. try{
  23. final Socket socket = server.accept();
  24. new Thread(new Runnable() {
  25. ObjectOutputStream output =  null;
  26. @Override
  27. public void run() {
  28. try{
  29. try {
  30. output = new ObjectOutputStream(socket.getOutputStream());
  31. ObjectInputStream input = new ObjectInputStream(socket.getInputStream());
  32. String className = input.readUTF();
  33. String methodName = input.readUTF();
  34. Class<?>[] parameterTypes = (Class<?>[])input.readObject();
  35. Object[] arguments = (Object[])input.readObject();
  36. Object claszz = null;
  37. if(!classMap.containsKey(className)){
  38. try {
  39. claszz = Class.forName(className).newInstance();
  40. classMap.put(className, claszz);
  41. } catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) {
  42. e.printStackTrace();
  43. }
  44. }else {
  45. claszz = classMap.get(className);
  46. }
  47. Method method = claszz.getClass().getMethod(methodName, parameterTypes);
  48. Object result = method.invoke(claszz, arguments);
  49. output.writeObject(result);
  50. } catch (IOException | ClassNotFoundException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException | SecurityException e) {
  51. output.writeObject(e);
  52. }finally {
  53. output.close();
  54. }
  55. }catch(Exception e){
  56. e.printStackTrace();
  57. }finally {
  58. try {
  59. socket.close();
  60. } catch (IOException e) {
  61. e.printStackTrace();
  62. }
  63. }
  64. }
  65. }).start();
  66. }catch (Exception e) {
  67. e.printStackTrace();
  68. }
  69. }
  70. }
  71. }

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

  1. public class RPCProxy {
  2. @SuppressWarnings("unchecked")
  3. public static <T> T create(Object target){
  4. return (T) Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(), new InvocationHandler(){
  5. @SuppressWarnings("resource")
  6. @Override
  7. public Object invoke(Object proxy, Method method, Object[] args)
  8. throws Throwable {
  9. Socket socket = new Socket("localhost", 8080);
  10. ObjectOutputStream output = new ObjectOutputStream(socket.getOutputStream());
  11. try {
  12. output.writeUTF(target.getClass().getName());
  13. output.writeUTF(method.getName());
  14. output.writeObject(method.getParameterTypes());
  15. output.writeObject(args);
  16. ObjectInputStream input = new ObjectInputStream(socket.getInputStream());
  17. try {
  18. Object result = input.readObject();
  19. if (result instanceof Throwable) {
  20. throw (Throwable) result;
  21. }
  22. return result;
  23. } finally {
  24. input.close();
  25. }
  26. } finally {
  27. output.close();
  28. socket.close();
  29. }
  30. }
  31. });
  32. }
  33. }

HelloRpc接口:

  1. public interface HelloRpc {
  2. String hello(String name);
  3. }

HelloRpcImpl实现类:

  1. public class HelloRpcImpl implements HelloRpc {
  2. @Override
  3. public String hello(String name) {
  4. return "hello "+name;
  5. }
  6. }

Main函数操作:

  1. public class Main {
  2. public static void main(String [] args){
  3. HelloRpc helloRpc = new HelloRpcImpl();
  4. helloRpc = RPCProxy.create(helloRpc);
  5. System.err.println(helloRpc.hello("rpc"));
  6. }
  7. }

执行结果:

hello rpc

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

hadoop17---RPC和Socket的区别的更多相关文章

  1. RPC和Socket

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

  2. rpc、socket、mq

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

  3. TCP/IP,HTTP,Socket的区别与联系

    一 忆往昔,尽是悔恨泪.       在学校的时候学过,网络七层,也知道tcp的三次握手.但因为根本没用在实际开发中,所以逐渐淡忘.现在就再次理解下三个的区别与联系. 二 正题       网络七层: ...

  4. Http、tcp、Socket连接区别

    转自Http.tcp.Socket连接区别 相信不少初学手机联网开发的朋友都想知道Http与Socket连接究竟有什么区别,希望通过自己的浅显理解能对初学者有所帮助. 1.TCP连接 要想明白Sock ...

  5. RPC和RMI的区别(Difference Between RPC and RMI)

    RPC和RMI的区别(Difference Between RPC and RMI) RPC vs RMI RPC (Remote Procedure Call) and RMI (Remote Me ...

  6. TCP/IP、Http、Socket的区别与关系

    --TCP/IP.Http.Socket的区别与关系 --------------------------------------2014/05/14 网络由下往上分为 物理层.数据链路层.网络层.传 ...

  7. SOA,Webservice,SOAP,REST,RPC,RMI的区别与联系

    SOA,Webservice,SOAP,REST,RPC,RMI的区别与联系 SOA面向服务的软件架构(Service Oriented Architecture) 是一种计算机软件的设计模式,主要应 ...

  8. RPC与RMI的区别

    分布式项目按照以下发展经历了以下技术: CORBA: RMI:基于远程接口的调用 RMI-RROP:这是RMI与CORBA的结合,用在了EJB技术上,EJB留给世界上是优秀的理论和糟糕的架构. WEB ...

  9. WebSocket和Socket的区别

    前段时间写了两篇介绍HTTP和WebSocket的文章,回复中有人说希望了解下WebSocket和Socket的区别.这个问题之前也有想过,自己对此是有大概的答案,可是并不太确定,于是去搜集了些资料( ...

  10. TCP socket和web socket的区别

    小编先习惯性的看了下某中文百科网站对Web Socket的介绍,觉得很囧.如果大家按照这个答案去参加BAT等互联网公司的前端开发面试,估计会被鄙视. 还是让我们阅读一些英文材料吧. 让我们直接看sta ...

随机推荐

  1. 第一百六十一节,封装库--JavaScript,完整封装库文件

    封装库--JavaScript,完整封装库文件 /** *feng_zhuang_ku_1.0版本,js封装库,2016/12/29日:林贵秀 **/ /** 前台调用 * 每次调用$()创建库对象, ...

  2. 刚新建好的动态网站项目,创建jsp页面就报错

    拿到刚刚可以运行的Eclipse,就马上想敲码了,但一创建项目之后再创建jsp页面就报错= =! 报错的内容大概为缺乏对应的jar包. 我们常用Tomcat为中间体,而他本身是带有开发jsp网站的对应 ...

  3. C#反射Assembly 详细说明,有项目例子

    1.对C#反射机制的理解2.概念理解后,必须找到方法去完成,给出管理的主要语法3.最终给出实用的例子,反射出来dll中的方法 反射是一个程序集发现及运行的过程,通过反射可以得到*.exe或*.dll等 ...

  4. bootstrap基础学习十篇

    bootstrap字体图标(Glyphicons) a.什么是字体图标 字体图标是在 Web 项目中使用的图标字体.虽然,Glyphicons Halflings 需要商业许可,但是您可以通过基于项目 ...

  5. 更改Ubuntu的默认开机启动项

    终端下: sudo vim /etc/default/grub 修改以下红色语句即可,注意是从0开始: GRUB_DEFAULT=5 #GRUB_HIDDEN_TIMEOUT= GRUB_HIDDEN ...

  6. Django Admin后台管理模块的使用

    Admin后台管理模块的使用 Django的管理员模块是Django的标准库django.contrib的一部分.这个包还包括其它一些实用的模块: django.contrib.auth django ...

  7. C# 中利用反射机制拷贝类的字段和属性(拷贝一个类对象的所有东西付给另一个类对象,而不是付给引用地址)

    from:https://blog.csdn.net/poxiaohai2011/article/details/27555951 //C# 中利用反射机制拷贝类的字段和属性(拷贝一个类对象的所有东西 ...

  8. sql查询某个字段最长的记录

    select `字段`, length(`字段`) from 表名 where length(`字段`) = ( select max(length(`字段`)) from 表名  )

  9. Segmented 标签栏 切换效果

    转载:http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2014/0512/1615.html http://www.it165.net/pr ...

  10. Android 4.4 (KitKat) SMS Apis Change——Android 4.4的一个重大变化

    Android团队通过Android开发博客透漏今年会放出Android 4.4 (KitKat) ,同时更新了 SMS 的部分API.博客上讲只有default SMS app才能对短信数据库有写权 ...