2011-02-17 52 views
3

我一直在问一些关于如何在我的客户端服务器环境中使用命令协议的问题。然而,经过一番实验,我得出的结论是它不适合我。它不是为这种情况设计的。因此我处于一个松散的结局。Java Socket RPC协议

我已经实现了一种RPC机制,在此之前我有一个名为“Operation”的类。我还有一个名为“Action”的枚举,其中包含可以在服务器上调用的操作的名称。

现在,在我的旧项目中,客户端每次想要在服务器上调用一个操作时,它都会创建一个“Operation”实例,并使用“Action”枚举中的值设置操作变量。例如

Operation serverOpToInvoke = new Operation();
serverOpToInvoke.setAction(Action.CREATE_TIME_TABLE);
serverOpToInvoke.setParameters(Map params);
ServerReply reply = NetworkManager.sendOperation(serverOpToInvoke);
...

在服务器端,我不得不执行确定通过用“的if/else”语句的负荷检查“操作”枚举值来调用该方法的可怕任务。当找到一场比赛时,我会调用适当的方法。

与此问题是,它是凌乱的,很难维护,最终是不好的设计。

我的问题是这样的 - 是否有某种模式,我可以按照java中的TCP套接字实现一个漂亮,清洁和可维护的rpc机制?由于客户端(android)不支持RMI,因此RMI对我来说是不可行的。在这个阶段我已经耗尽了所有的途径。唯一的其他选择可能是REST服务。任何建议都会非常有帮助。

非常感谢您 问候

回答

8

可能最简单的解决方案是松散地遵循RMI的路径。

您有一个接口和一个实现开出:

interface FooService { 
    Bar doThis(String param); 
    String doThat(Bar param); 
} 

class FooServiceImpl implements FooService { 
    ... 
} 

您部署的接口两侧和实施仅在服务器端。

然后要获取客户端对象,请创建一个动态代理。其调用处理程序除了序列化服务类名称,方法名称和参数并将其发送到服务器(最初可以使用ObjectOutputStream,但可以使用替代序列化技术,例如XStream)之外,不会执行任何其他操作。

服务器侦听器接受这个请求并使用反射来执行它,然后发回响应。

这个实现相当简单,双方都是透明的,唯一的主要问题是你的服务实际上是单身。

如果需要,我可以包含一些更多的实现细节,但如果我必须实现类似的东西,那么我会遵循这个总体思路。尽管如此,我可能会多搜索一下已有的解决方案,比如webservices或类似的东西。

更新:这是普通的(本地)调用处理程序会做的。

class MyHandler implements InvocationHandler { 

    private Object serviceObject; 

    @Override 
    public Object invoke(Object proxy, Method method, Object[] args) 
      throws Throwable { 
     return method.invoke(serviceObject, args); 
    } 
} 

其中serviceObject是您的服务实现对象包装到处理程序中。

这是你必须减少一半,而不是调用方法,您需要发送以下服务器:

  1. 接口的全名(或其他一些价值唯一标识服务接口)
  2. 方法的名称。
  3. 该方法需要的参数类型的名称。
  4. args array。

服务器端必须:

  1. 查找该接口的实现(最简单的方法是有某种地图,其中键是接口名称和值执行单个实例)
  2. 找到方法,使用Class.getMethod(name, paramTypes);
  3. 通过调用method.invoke(serviceObject, args);执行该方法并将返回值发回。
+0

嗨biziclop,当你提到使用反射执行命令的服务器,你能详细解释一下吗?你昨天回答了一个关于我的命令模式的帖子,从那以后,我读到了强大的动态代理。我很感谢代码。我对整体概念更感兴趣。非常感谢您的帮助 – Joeblackdev 2011-02-17 19:45:31

+1

@Joeblackdev更新了我的答案,希望它有所帮助。 – biziclop 2011-02-17 20:05:19

0

RMI是要走的路。

Java RMI的是Java应用程序 程序编程接口,其执行 面向对象的等效的 远程过程调用(RPC)。

+0

嗨Klark,我不能在这里使用RMI。客户端平台(Android)不利于使用RMI。 – Joeblackdev 2011-02-17 19:42:47

2

你应该看看协议缓冲区从谷歌:http://code.google.com/p/protobuf/

这个库定义了一个IDL用于产生等,其可以被写入并从流/字节数组/等读取的类结构体。他们还使用定义的消息定义RPC机制。

我用这个库来解决类似的问题,它工作得很好。