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. Tomcat服务器的默认端口是多少?怎样修改tomcat的端口?

    Tomcat服务器的默认端口是多少?怎样修改tomcat的端口? 解答:默认端口为8080,可以通过service.xml的Connector元素的port属性来修改端口.

  2. (转)fock函数详解

    转自:http://www.cnblogs.com/bastard/archive/2012/08/31/2664896.html linux中fork()函数详解  一.fork入门知识 一个进程, ...

  3. 努比亚Z18mini多点对焦

    25点对焦 分为了中心对焦.中间对焦.边缘对焦三个区域 [参考文献] 手机上感受单反的“多点对焦”努比亚Z18mini给你想象 https://baijiahao.baidu.com/s?id=160 ...

  4. IOS . -转载-10行代码搞定九宫格

    //每个Item宽高 CGFloat W = ; CGFloat H = ; //每行列数 NSInteger rank = ; //每列间距 CGFloat rankMargin = (self.v ...

  5. Duilib教程-自动布局3-分隔条

    先看一个常用的图,如下: 左边是导航栏,右边是信息区. 中间可以自由拉伸. XML如下: <?xml version="1.0" encoding="utf-8&q ...

  6. ios消息推送机制原理与实现

    本文转载至 http://hi.baidu.com/yang_qi168/item/480304c542fd246489ad9e91 Push的原理: Push 的工作机制可以简单的概括为下图 图中, ...

  7. Android自定义上拉控件SpringView

    Demo 先看一下SpringView的效果图: 1.拖动灰色部分可拖动下方视图,点击jump按钮可让下方视图自行滑动. 使用方法 布局文件: <com.zql.android.springvi ...

  8. ETCD使用中需要注意的问题

    我们在实际生产中使用ETCD存储元数据, 起初集群规模不大的时候元数据信息不多没有发现什么问题. 随着集群规模越来越大问题逐渐暴露了 有些实际的配置还是需要在初始化的时候就研究确定 1. --auto ...

  9. Advanced Bash-Scripting Guide(学习笔记)

    http://www.tldp.org/LDP/abs/html/index.html       11.1. Loops tp://www.tldp.org/LDP/abs/html/loops1. ...

  10. 服务器端Session和客户端Session(和Cookie区别)

    Session其实分为客户端Session和服务器端Session. 当用户首次与Web服务器建立连接的时候,服务器会给用户分发一个 SessionID作为标识.SessionID是一个由24个字符组 ...