设计网络消息的类架构

时间:2009-07-06 23:32:28

标签: c++ oop networking client-server

我有客户端/服务器应用程序和非常简单的通信协议。更确切地说,它是服务器发送的一组命令和客户端可以发出的一组请求。

这个想法如下:

当服务器发出命令时,客户端必须执行它。 发出请求时,服务器会检查权限,如果一切正常,它会批准请求。

该应用程序是用C ++编写的,我对这种通信协议的架构设计略有不满。假设命令/请求是制表符分隔的字符串,第一个参数是消息的名称,我计划创建一个MessageManager类,它将所有消息存储在哈希表中,并在必要时检索它们。这里的问题是:

typedef std::vector< std::string > ArgArray;
class Request : public Message
{
public:
   Request( const char *name ) : Message( name ) { }
#ifdef CLIENT
   /** problem here **/
   virtual void make( ... ) = 0;
#elif defined SERVER
   virtual void grant( const Client &c, const ArgArray &params ) const = 0;
protected:
   virtual void checkPermissions( const Client &c, const ArgArray &params ) const = 0;
#endif
};

因为不同的消息可以构造不同的参数,所以我无法真正创建一个完整的接口。例如,某些消息可能需要构造一个简单的字符串,而其他消息可能需要一些数字数据。这使事情复杂化并使设计有点凌乱...... I.e。我必须通过从接口定义中省略make()来解决问题,只需为我发出的每个请求添加不同的make()。此外,如果我希望在一个容器中存储指向不同请求的指针,我不能使用dynamic_cast因为Request不是多态类型。一个显而易见(不整洁)的解决方案是使用make( int n, ... )定义并使用stdarg.h来提取不同的参数,但我认为这对于程序员来说是不安全和令人困惑的。

我的想法显然存在设计缺陷。我已经有了解决方案,但我只是想知道,SO的人们将如何解决这个问题?你会使用什么样的Object架构?是否有更简单的方法可以解决这个问题?对此没有任何具体要求,只是为了使其保持尽可能简单并保持实际协议不变(带制表符分隔的字符串,第一个参数指示它是哪个消息)。

3 个答案:

答案 0 :(得分:1)

我认为你设计中的问题是你试图将太多功能塞进一个类中。例如,关于构造/解析消息以包含数字数据或字符串(即序列化)的部分应该与底层连接逻辑分开。

如果允许您使用其他库,请查看Boost.Serialization。 Boost有一个非常好的网络库,也称为ASIO。即使您不被允许使用助推器,您也应该参考他们的图书馆设计。

答案 1 :(得分:1)

是的,你说“命令/请求是制表符分隔的字符串”:正如kuoson所说,“不同的消息可以采用不同的参数”并不是真的......相反,所有的消息都是从制表符分隔的字符串。

答案 2 :(得分:1)