首页 \ 问答 \ Java Socket RPC协议(Java Socket RPC protocol)

Java Socket RPC协议(Java Socket RPC protocol)

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

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

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

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

在服务器端,我必须通过检查'Action'枚举值并使用'if / else'语句来确定要调用哪种方法,这个可怕的任务。 当找到一场比赛时,我会调用适当的方法。

问题在于它很混乱,很难维护,并且最终是不好的设计。

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

非常感谢您的问候


I've been asking some questions about adapting the command protocol for use in my client server environment. However, after some experimentation, I have come to the conclusion that it will not work for me. It is not designed for this scenario. I'm thus at a loose end.

I have implemented a sort of RPC mechanism before whereby I had a class entitled "Operation". I also had an enum entitled "Action" that contained names for actions that could be invoked on the server.

Now, in my old project, every time that the client wanted to invoke an action on the server, it would create an instance of 'Operation' and set the action variable with a value from the "Action" enum. For example

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

On the server side, I had to perform the horrible task of determining which method to invoke by examining the 'Action' enum value with a load of 'if/else' statements. When a match was found, I would call the appropriate method.

The problem with this was that it was messy, hard to maintain and was ultimately bad design.

My question is thus - Is there some sort of pattern that I can follow to implement a nice, clean and maintainable rpc mechanism over a TCP socket in java? RMI is a no go for me here as the client (android) doesn't support RMI. I've exhausted all avenues at this stage. The only other option would maybe be a REST service. Any advice would be very helpful.

Thank you very much Regards


原文:https://stackoverflow.com/questions/5033548
更新时间:2021-07-08 19:07

最满意答案

让我们首先回答您的具体问题:

为什么我们需要一个IList<T>接口

它是唯一提供可变索引访问的接口 - List<T>T[]契约 - 因此它们可以作为参数互换地传递给需要这种契约的函数。

更不用说,当你想推出自己的实现时。 例如,我想将一个File公开为IList<char> - 它可能不是最好的主意,但你得到了漂移。

我同意IList<T>是一个糟糕的接口选择,因为添加和删除元素不是数组自然支持的。

现在来看大局:你可能会忽略这一点,因为这是非常主观的

.NET框架在其集合接口方面做得很差。 它们不仅不在一个命名空间中,而且随着时间的推移而发展 - 这意味着有很多代码(包括在BCL中),它们在编写时使用“最佳”可用接口,这可能是从今天开始是一个糟糕的选择。

我相信他们应该从下面的接口开始 - 也许有更好的名字:)

interface IEnumerable<T> {
    // just like we currently have
}

// currently called IReadOnlyCollection<T>
interface ICollection<T> : IEnumerable<T> {
    int Count { get; }
}

// currently called as IReadOnlyList<T>
interface IIndexedCollection<T> : ICollection<T> {
    T this[int index] { get; }
}

// currently called as ICollection<T>, but doesn't inherit from IReadOnlyCollection
interface IMutableCollection<T> : ICollection<T> {
    void Add(T item);
    bool Remove(T item);
    void Clear();
}

// We don't have this at all - OP's case
interface IArray<T> : IIndexedCollection<T> {
    T this[int index] { get; set; }
}

// currently exists as IList<T>, but inheritance is very different
interface IList<T> : IArray<T>, IMutableCollection<T> {
    void Insert(int index, T item);
    void RemoveAt(int index);
}

Let's start by answering your specific question:

Why do we need a IList<T> interface

It is the only interface that provides mutable indexed access - contract for List<T> and T[] - so they can be interchangeably passed as an argument to functions that need such a contract.

Not to mention, when you want to roll your own implementation. For example, I want to expose a File as an IList<char> - it might not be the best idea, but you get the drift.

I agree that IList<T> is a poor choice of interface, since adding and removing an element is not what an array naturally supports.

Now to the bigger picture: You may ignore this as this is very subjective

.NET framework has done a poor job with its collection interfaces. Not only they are not in a single namespace, but they have evolved over time - which means there is a lot of code out there (including in the BCL) which use the "best" available interface as of when it was written, which might be a bad choice as of today.

I believe they should have started with interfaces like below - perhaps with better names :)

interface IEnumerable<T> {
    // just like we currently have
}

// currently called IReadOnlyCollection<T>
interface ICollection<T> : IEnumerable<T> {
    int Count { get; }
}

// currently called as IReadOnlyList<T>
interface IIndexedCollection<T> : ICollection<T> {
    T this[int index] { get; }
}

// currently called as ICollection<T>, but doesn't inherit from IReadOnlyCollection
interface IMutableCollection<T> : ICollection<T> {
    void Add(T item);
    bool Remove(T item);
    void Clear();
}

// We don't have this at all - OP's case
interface IArray<T> : IIndexedCollection<T> {
    T this[int index] { get; set; }
}

// currently exists as IList<T>, but inheritance is very different
interface IList<T> : IArray<T>, IMutableCollection<T> {
    void Insert(int index, T item);
    void RemoveAt(int index);
}

相关问答

更多
  • 我想你需要用IList保持设计的原因是因为它是其他模块的通用接口。 一种可能的方案: 代替: [XmlElement("Test")] public IList Tests { get; set; } 你可以尝试: [XmlElement("Test")] public List TestList { get; set; } [XmlIg ...
  • 这里有三个问题:我应该使用什么类型的形式参数? 本地变量应该用什么? 我应该怎么用于返回类型? 正式参数: 这里的原则是不要求比你需要的更多 。 IEnumerable通信“我需要从头到尾得到这个序列的元素”。 IList通信“我需要以任意顺序获取并设置此序列的元素”。 List通信“我需要以任意顺序获取和设置此序列的元素,我只接受列表;我不接受数组。 通过要求比你需要的更多,你(1)使呼叫者做不必要的工作来满足你的不必要的需求,和(2)向读者传达虚假的信息。 只问你要使用什么 这样,如果 ...
  • 也许这不是直接回答你的问题,但是在.NET 4.5+中,我更喜欢在设计公共或受保护的API时遵循这些规则: 如果只有枚举可用,请返回IEnumerable ; 如果枚举和项计数都可用,请返回IReadOnlyCollection ; 返回IReadOnlyList ,如果枚举,项计数和索引访问可用; 如果枚举,项目计数和修改可用,请返回ICollection ; 返回IList ,如果枚举,项计数,索引访问和修改可用。 最后两个选项假设,该方法不能作为IList实现返回数 ...
  • 我有两条规则: 接受最基本的工作类型 返回用户将需要的最丰富的类型 所以当编写一个收集的函数或方法时,写入它不是一个List,而是一个IList ,一个ICollection 或者IEnumerable 。 通用接口仍然可以用于异构列表,因为System.Object也可以是T。 如果您决定使用Stack或其他数据结构,那么这样做会使您头疼。 如果所有你需要做的功能是通过它,IEnumerable 真的是你应该要求的所有。 另一方面,当从一个函数返回一个对象时,你想给用户最丰富的一组 ...
  • List实现IList和IList是为了使代码在假定为IList任何地方都可以使用它。 这将使它更容易转换到通用IList因为它是更合适的。 此外,如果您有.net 1.1或更早版本的代码,即使您的类是在.net 2.0或更高版本的程序集中实现的,您也希望重新使用该代码,这将使它成为可能。 The reason that List implements both IList and IList is to make it usable anywhere your code is ...
  • 如何(parameter as IList) 。 我假设您不希望在所有情况下仅将参数限制为IList 。 How about (parameter as IList). I assume you don't want to just restrict the parameter to an IList in all cases.
  • 从C#4规范的第12.1.2节: 一维数组T[]实现接口System.Collections.Generic.IList及其基接口。 因此,存在从T[]到IList及其基接口的隐式转换。 值得注意的是,如果您创建一个矩形数组或一个具有非零的下限的一维数组,那么这些数组不会实现IList 。 在CLI中,实际上有两个术语: 向量和数组 。 向量是一个具有零下限的一维集合,并且被JIT优化为heck和back。 数组可以具有多个维度和不同的下限,并且不需要进行彻底的优化。 C#中的T[] 始终 ...
  • 让我们首先回答您的具体问题: 为什么我们需要一个IList接口 它是唯一提供可变索引访问的接口 - List和T[]契约 - 因此它们可以作为参数互换地传递给需要这种契约的函数。 更不用说,当你想推出自己的实现时。 例如,我想将一个File公开为IList - 它可能不是最好的主意,但你得到了漂移。 我同意IList是一个糟糕的接口选择,因为添加和删除元素不是数组自然支持的。 现在来看大局:你可能会忽略这一点,因为这是非常主观的 .NET框架在其集合接口方面做得很差。 它们不仅 ...
  • 似乎做得更好: return ((IEnumerable)_items).GetEnumerator(); 当数组实现IEnumerable : [...]此类型实现IEnumerable和IEnumerable 你的第一种方法不起作用只是因为IEnumerable.GetEnumerator和IEnumerable.GetEnumerator之间存在歧义。 这里解释了为什么在IDE中无法看到它的问题: 从.NET Framework 2.0开始,Array类实现System.Co ...
  • 那是因为这个“某人”想要实现一种在官方类库中找不到的列表。 在某些情况下,具体要求将通过实现IList或任何其他(IList,ICollection ...)来强制实现特定类型的列表,以便让您自己的类与.NET API或第三方类兼容。 好吧,在一天结束时,这是一个界面的目标,不是吗? :) 合同! That's because this "someone" wanted to implement a kind of list that's not found in the official class li ...

相关文章

更多

最新问答

更多
  • h2元素推动其他h2和div。(h2 element pushing other h2 and div down. two divs, two headers, and they're wrapped within a parent div)
  • 创建一个功能(Create a function)
  • 我投了份简历,是电脑编程方面的学徒,面试时说要培训三个月,前面
  • PDO语句不显示获取的结果(PDOstatement not displaying fetched results)
  • Qt冻结循环的原因?(Qt freezing cause of the loop?)
  • TableView重复youtube-api结果(TableView Repeating youtube-api result)
  • 如何使用自由职业者帐户登录我的php网站?(How can I login into my php website using freelancer account? [closed])
  • SQL Server 2014版本支持的最大数据库数(Maximum number of databases supported by SQL Server 2014 editions)
  • 我如何获得DynamicJasper 3.1.2(或更高版本)的Maven仓库?(How do I get the maven repository for DynamicJasper 3.1.2 (or higher)?)
  • 以编程方式创建UITableView(Creating a UITableView Programmatically)
  • 如何打破按钮上的生命周期循环(How to break do-while loop on button)
  • C#使用EF访问MVC上的部分类的自定义属性(C# access custom attributes of a partial class on MVC with EF)
  • 如何获得facebook app的publish_stream权限?(How to get publish_stream permissions for facebook app?)
  • 如何防止调用冗余函数的postgres视图(how to prevent postgres views calling redundant functions)
  • Sql Server在欧洲获取当前日期时间(Sql Server get current date time in Europe)
  • 设置kotlin扩展名(Setting a kotlin extension)
  • 如何并排放置两个元件?(How to position two elements side by side?)
  • 如何在vim中启用python3?(How to enable python3 in vim?)
  • 在MySQL和/或多列中使用多个表用于Rails应用程序(Using multiple tables in MySQL and/or multiple columns for a Rails application)
  • 如何隐藏谷歌地图上的登录按钮?(How to hide the Sign in button from Google maps?)
  • Mysql左连接旋转90°表(Mysql Left join rotate 90° table)
  • dedecms如何安装?
  • 在哪儿学计算机最好?
  • 学php哪个的书 最好,本人菜鸟
  • 触摸时不要突出显示表格视图行(Do not highlight table view row when touched)
  • 如何覆盖错误堆栈getter(How to override Error stack getter)
  • 带有ImageMagick和许多图像的GIF动画(GIF animation with ImageMagick and many images)
  • USSD INTERFACE - > java web应用程序通信(USSD INTERFACE -> java web app communication)
  • 电脑高中毕业学习去哪里培训
  • 正则表达式验证SMTP响应(Regex to validate SMTP Responses)