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
最满意答案
让我们首先回答您的具体问题:
为什么我们需要一个
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>
interfaceIt is the only interface that provides mutable indexed access - contract for
List<T>
andT[]
- 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 anIList<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
那样将Xml文件序列化为一个接口?(Why isn't possible to serialize into a Xml File an interface like IList [2021-10-29]?) 我想你需要用IList保持设计的原因是因为它是其他模块的通用接口。 一种可能的方案: 代替: [XmlElement("Test")] public IListTests { get; set; } 你可以尝试: [XmlElement("Test")] public List TestList { get; set; } [XmlIg ... -
为什么要使用IList或List?(why use IList or List?)[2024-01-25]
这里有三个问题:我应该使用什么类型的形式参数? 本地变量应该用什么? 我应该怎么用于返回类型? 正式参数: 这里的原则是不要求比你需要的更多 。 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 ... -
将T转换为IList(Convert T to IList)[2023-07-04]
如何(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. -
int []是否有资格作为IList
?(int[] qualifies as IList [2023-01-20]?) 从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?(Why inheritence from IList?)[2023-08-02]
那是因为这个“某人”想要实现一种在官方类库中找不到的列表。 在某些情况下,具体要求将通过实现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 ...